Files
ForexBot2/backtest/instructions_for_backtest.txt
T
Harwinder Sekhon 1e8110ea5e backtest: full-GPU research twin (cudaBasedBacktesting.py + cuda_signal_kernels.py); books byte-identical to gpu_backtest.py (2026-09-18)
Owner decisions: research only (live scans stay on the CPU code), gpu_backtest.py
stays the base reference, every research flag supported, the one exemption from
instructions item 6 recorded in backtest/instructions_for_backtest.txt.

- backtest/cuda_signal_kernels.py: the CUDA decision stage. K1 = engine.py + the
  GPUTechnicalEngine overrides (one thread per bar), K2 = analyze_from_dataframes
  end to end incl. gates 6b-6i, the four setup generators and the regime filter
  (one thread per primary bar), K3 = position_sizing.build_features, K4 cooldown,
  K5 prefix median, K6 recorder bar rows. Config packer with generated #defines;
  leaf module; --fmad=false; Python evaluation order kept (ternary min/max,
  pairwise sums, Neumaier sum(), exact round(x, 2)).
- backtest/cudaBasedBacktesting.py: same CLI, cache files and writers as the
  reference; the host turns kernel codes into the exact strings; no CPU path.
- test_all.py Module 37 (16 tests): every stage pinned against the live code;
  suite 552 / 552 on the GPU, without CUDA and with FB2_BACKEND=cpu.
- Proof: five reference MD5s, four 6-month acceptance books (M5/M15, $0.65/$0.30),
  M15 OOS --export-features and --record --record-bars tables, ten research-flag
  variants, and the owner's five-year M5 and M15 books, all byte-identical to
  gpu_backtest.py. Wall time 0.8-6.6 s per book against 13-353 s.
- CLAUDE.md sections 1, 3, 6, 7, 9, 10, 11 and the instructions addendum: any
  signal change is now a parity event for the twin.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 16:11:47 -04:00

68 lines
4.9 KiB
Plaintext

Backtest reporting checklist — ForexBot2 (XAU/USD)
==================================================
Every backtest report must record:
- The exact command line (window, --primary-tf, --spread, and any --set /
--quality / --strategies / --confirm-tfs overrides) and the "Backend:" log line.
- Trades, total R, win rate, profit factor and max drawdown for the whole
window AND for both halves, at both cost conventions ($0.65 measured-Oanda
headline, $0.30 cross-book comparability) — CLAUDE.md rule 1.
- Per trade (the exported CSV already carries these): entry/exit time and
price, exit reason, R multiple, MFE/MAE, entry reasons, and every
indicator's signal / value / agreement at decision time.
- Breakdowns by session/hour, weekday, regime and volatility regime, and,
for any candidate change, the removed/added/shifted trade diff against the
control book (the 5-bar cooldown displaces entries, so judge run-level
numbers, never the added-trade bucket alone).
- The md5 of the exported book whenever the run is a parity or regression check.
Replays go through the real signal code (analyze_from_dataframes) — never a
re-implementation.
--- 2026-09-06: decision-time feature export ---
- `--export-features` appends stake_multiplier, r_sized and the 65 `f_*` decision-time
features (position_sizing.FEATURE_ORDER) AFTER the 63 pinned columns; default export is
byte-identical to the pinned books.
- Any sizing report must show the FLAT book and the SIZED book side by side and the
label-shuffle null; the 2026-09-06 campaign verdict (nothing ships,
backtest/research/sizing_campaign_2026-09.md) is the reference.
--- 2026-09-09: replay recording (--record DIR [--record-bars]) ---
- `--record DIR` writes manifest.json + trades/indicators/events parquet for every ACCEPTED trade:
every indicator's signal / value / confidence / BASE weight / regime multiplier / EFFECTIVE
weight / contribution on the primary AND both confirmation timeframes, penalties, the setup, the
outcome, and the Forex Factory calendar events around the trade (backtest/cache/calendar.parquet,
refreshed with scripts/ff_calendar_scraper.py). `--record-bars` adds one row per ANALYZED primary
bar with the same votes plus forward moves (1h/4h/24h in ATR units).
- Recording is read-only w.r.t. the signal path: any recorded run must be paired with a control
run (same CLI without --record) and the report must show the two books' MD5s equal
(manifest.book_csv_md5 is the md5 of the 63-column book).
- Scorecards and "what-if" tables from these files (backtest/replay_scorecard.py) are IN-BOOK
descriptive statistics: they cannot add trades a change would create and ignore the gates.
Any weight / indicator change they suggest is a hypothesis for a full rule-1 rerun, never a decision.
--- 2026-09-18: GPU backend (backtest/gpu_kernels.py) ---
- The "Backend:" line now names the CUDA device ("CuPy GPU (<device>, cupy <version>)") or the
reason for the NumPy fallback; quote it verbatim. `--backend cpu` forces the NumPy twins, `gpu`
refuses to fall back. Books are byte-identical on both backends (reference MD5s, CLAUDE.md §9).
- Any change to a kernel or to its CPU twin is a parity event: re-run Module 36, regenerate the
five reference books on BOTH backends and show the ten MD5s unchanged. Never replace a kernel
with a differently ordered algorithm (parallel scan, two-pass variance) even if it is faster.
--- 2026-09-18: CUDA research twin (backtest/cudaBasedBacktesting.py) ---
- Exemption from "replays go through the real signal code" above, granted by the owner for this
ONE research script: its per-bar decision is a CUDA re-implementation of engine.py,
signal_aggregator.py and chart_patterns.py (backtest/cuda_signal_kernels.py). gpu_backtest.py
stays the base reference and live scans never use the twin.
- Its numbers count as evidence only while parity holds. After ANY change to engine.py,
signal_aggregator.py, chart_patterns.py, position_sizing.py, the recorder's row layout or the
GPUTechnicalEngine overrides: mirror the change in cuda_signal_kernels.py in the same commit,
keep test_all.py Module 37 green, and regenerate at least the M15 OOS book (2024-06-01 ->
2025-03-30, $0.65) with BOTH scripts and show equal MD5s before quoting a CUDA-script result.
- A report built from the twin quotes both scripts' "Backend:" lines (the twin's necessarily
starts with "CuPy GPU (") and the paired MD5 of at least one book from the reference script on
the same code and cache. Whole-window and half-window figures, costs and breakdowns are then
read from the twin's book exactly as from the reference's; the CSVs are identical.
- The twin has no CPU path (--backend cpu / FB2_BACKEND=cpu are refused), --workers is ignored,
and it refuses configurations beyond its compile-time limits (more than 4 confirmation
timeframes, divergence lookback >= 64, swing lookback >= 256, cp_lookback >= 128) with a
message that points back to gpu_backtest.py.