This is a research codebase where correctness is non-negotiable: a silent accounting bug or a strategy that looks good only in-sample is worse than no change at all. Two rules below are hard gates.
Build through the PowerShell terminal using _build.bat (which loads
vcvars64.bat, then runs cmake --build build). The Git Bash / MSYS layer on
Windows silently mangles cmd /c — it rewrites /c into a path, so cmd opens
interactively and the build no-ops while appearing to succeed. Every build and
every verification command in this file assumes PowerShell.
cmake -S . -B build -G Ninja # once, or after editing CMakeLists.txt
cmd /c _build.bat # build all targetsAll four must pass. Run them from PowerShell after building:
.\build\indverify.exe # incremental-indicator parity (must say ALL PARITY CHECKS PASSED)
.\build\parttest.exe # partial-trim P&L accounting (must say ALL CHECKS PASSED)
.\build\shorttest.exe # short / cover / flip accounting (must say ALL CHECKS PASSED)
.\build\backtest.exe config.json --data data | Select-String "Final equity|Trades "The last command above must print exactly:
Final equity 471874.87
Trades 328
If your change moves these numbers while the feature you added is disabled (the
default), that is a bug, not a feature — it means a "no-op" change altered
existing behavior. Do not merge until the gate is bit-exact again. (The
100-name rotation gate, 490,511,624,146.48 / 1,257 trades via
--universe data_cache/universe_100.txt, has the same status.) New behavior
must live behind a config flag that is off by default, so the gate run sees
the original code path unchanged.
Any new strategy feature must demonstrate improvement in walk-forward
out-of-sample results, not just in-sample. A full-history backtest that looks
better proves nothing — it is trivial to curve-fit. The bar is: run the
walk-forward (--walkforward 5 1), and if you tuned parameters, reserve a
holdout the tuner never touches and report performance there. Five extensions
have already been built, looked great in-sample, and been rejected on clean
out-of-sample data (RESEARCH_LOG.md). Rejecting a hypothesis
with honest data is a successful contribution; shipping an in-sample mirage is
not. State the OOS numbers in your PR description.
- Don't modify the fill model in
src/Backtest.cppwithout adding/extending a unit proof (parttest/shorttest) that pins the new behavior to the penny. - Don't commit credentials. Keys come from
APCA_API_KEY_ID/APCA_API_SECRET_KEYenvironment variables;config.jsonholds placeholders. - Keep
quantbot(live bot) free of test-only or research-only code paths.