Files
ForexBot2/backtest/research/m15_5yr_cuda_2026-09-18.md
Harwinder Sekhon 32ad73c59a 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.
2026-09-18 16:11:47 -04:00

8.0 KiB
Raw Permalink Blame History

M15 five-year book on the CUDA research twin — 2026-09-18

Owner request: a five-year M15 backtest with backtest/cudaBasedBacktesting.py. This window goes past the three-year cap the owner set on 2026-09-05 (CLAUDE.md rule 1); it was run as an explicit owner-requested exception. It is a read-out of the shipped configuration on a longer window, not a candidate change: nothing was tuned, nothing ships from it.

1. Runs

Window 2021-08-01 → 2026-08-04 (the kept 5-year cache, padded files oanda_XAU_USD_{5min,15min,1h}_20210531_20260804.parquet; 0 cache fallbacks; 122,489 M15 bars, 118,389 replayed; skipped 43,245 SESSION_WINDOW, 247 WEEKEND_FILTER). Factory config, no overrides.

venv/bin/python backtest/cudaBasedBacktesting.py --pair XAUUSD --primary-tf 15min --start 2021-08-01 --end 2026-08-04 --spread 0.65 --export-csv cuda_m15_5yr_0.65.csv
venv/bin/python backtest/cudaBasedBacktesting.py --pair XAUUSD --primary-tf 15min --start 2021-08-01 --end 2026-08-04 --spread 0.30 --export-csv cuda_m15_5yr_0.30.csv
venv/bin/python backtest/gpu_backtest.py        --pair XAUUSD --primary-tf 15min --start 2021-08-01 --end 2026-08-04 --spread 0.65 --workers 12 --export-csv ctrl_m15_5yr_0.65.csv   # paired reference
Run Backend line (verbatim) Wall Book MD5
twin $0.65 CuPy GPU (NVIDIA GeForce RTX 4070 SUPER, cupy 14.0.1) 6.6 s (K1 520,523 bars 0.046 s, K2 118,389 bars 0.001 s, trade sim 0.80 s) d5e432bdb3dc9923e00594125b4867dd
twin $0.30 CuPy GPU (NVIDIA GeForce RTX 4070 SUPER, cupy 14.0.1) 5.3 s 4ac5c0307123557c0740e57f5b91ff72
reference $0.65 CuPy GPU (NVIDIA GeForce RTX 4070 SUPER, cupy 14.0.1), GPU cache fallbacks: 0 93.7 s (replay 89.2 s, 12 workers) d5e432bdb3dc9923e00594125b4867dd — identical to the twin's (cmp equal)

The paired reference run is the parity evidence the 2026-09-18 addendum in backtest/instructions_for_backtest.txt requires before a number from the twin is quoted.

2. Results

1,822 trades at both costs (1,087 TRAIL, 666 SL, 69 TIMEOUT, no NO_DATA). Halves split at 2024-02-02.

Cost Segment Trades Total R Win rate PF Max DD (R)
$0.65 whole 2021-08-01 → 2026-08-04 1822 +157.43 56.8% 1.22 43.6
$0.65 first half 2021-08-01 → 2024-02-01 704 −9.61 52.4% 0.97 43.6
$0.65 second half 2024-02-02 → 2026-08-04 1118 +167.04 59.5% 1.40 17.1
$0.30 whole 1822 +196.77 57.7% 1.28 36.3
$0.30 first half 704 +9.38 54.0% 1.03 36.3
$0.30 second half 1118 +187.39 60.1% 1.46 14.9

Read against rule 1 for the record: the five-year window does not pass it (the first half is negative at $0.65 and the whole-window PF is 1.22). The shipped M15 configuration was validated on 2024-09-05 → 2026-09-05 (+146.1R, PF 1.43) and the 2024-06 → 2025-03 out-of-sample window (+60.7R, PF 1.49); the extra 2021–2023 years are where the R is missing, which is the same picture the Oanda re-pin of 2026-08-04 gave ("all timeframes earn only 2024+") and the reason for the three-year cap.

Per year

Year Trades $0.65 R WR PF Max DD $0.30 R PF
2021 (Aug–Dec) 97 +1.17 47.4% 1.03 15.5 +3.85 1.10
2022 318 −15.37 51.9% 0.89 39.1 −6.73 0.95
2023 264 +10.91 55.7% 1.10 15.7 +17.86 1.17
2024 397 +52.86 58.7% 1.36 17.1 +62.53 1.44
2025 480 +77.35 60.0% 1.43 14.8 +85.69 1.48
2026 (Jan–Aug 4) 266 +30.51 58.3% 1.30 13.2 +33.57 1.34

The 43.6R drawdown is entirely 2021-Q4 → 2022-Q3 (quarterly R: −13.5, +13.5, −7.6, −22.6); from 2024 on the worst quarter is −3.4R (2024-Q2) and the worst since is −8.3R for the five weeks of 2026-Q3 in the window.

Breakdowns ($0.65)

Grade Trades Total R WR PF Max DD
A+ 36 +5.48 63.9% 1.41 3.3
A 970 +92.30 56.5% 1.24 21.3
B 728 +41.16 56.5% 1.14 31.3
C 88 +18.49 59.1% 1.55 4.8
Generator Trades Total R WR PF Max DD
GENERIC 1658 +153.28 57.0% 1.24 43.6
XAU_ATR 164 +4.15 54.3% 1.06 17.0

XAU_ATR produces no trade before 2024 (5 in 2024, 48 in 2025, 111 in 2026). The gold ATR setup is gated by dollar-denominated floors (min_atr_threshold, the $8 stop floor, the 30 × $0.30 target floor); at 2021–2023 gold prices and volatility they blocked the generator and the GENERIC swing setup took every A-grade signal. The pre-2024 book therefore runs under an effectively different setup mix. Observation only; no proposal.

Direction Trades Total R WR PF Max DD
BUY 1212 +147.91 58.3% 1.32 48.3
SELL 610 +9.52 53.8% 1.04 36.2

Direction by year (trades / R): BUY 2021 58 / −9.8, 2022 215 / −28.9, 2023 166 / +10.9, 2024 273 / +56.8, 2025 344 / +95.2, 2026 156 / +23.7; SELL 2021 39 / +10.9, 2022 103 / +13.6, 2023 98 / 0.0, 2024 124 / −3.9, 2025 136 / −17.9, 2026 110 / +6.8. Shorts carried the book in the 2021–2022 bear phase and lost in the 2024–2025 rally; the parked cycle-2 candidate (block M15 grade-A SELLs, cycle_2026-09-10.md) is about the recent years only and this table does not change its status.

Regime Trades Total R WR PF Max DD
ranging 168 +45.30 61.3% 1.73 7.7
transitioning 400 +51.25 58.2% 1.33 7.0
trending_up 788 +55.43 56.9% 1.18 37.3
trending_down 466 +5.44 53.6% 1.03 26.0

(The mixed trending regime is blocked on M15, so it has no row.)

Volatility Trades Total R WR PF Max DD
low 193 +34.75 60.1% 1.48 11.2
normal 251 +41.65 61.0% 1.50 20.6
high 393 +2.77 53.7% 1.02 19.2
extreme 985 +78.27 56.2% 1.20 32.0
Entry hour UTC Trades Total R WR PF Entry hour UTC Trades Total R WR PF
03 98 +8.18 60.2% 1.24 14 381 +24.60 55.4% 1.16
04 38 +4.62 55.3% 1.29 15 146 +17.60 57.5% 1.30
05 77 +16.50 61.0% 1.58 17 79 +27.77 68.4% 2.20
06 117 +27.74 66.7% 1.85 18 112 −6.65 50.9% 0.87
07 116 −9.29 50.0% 0.83 19 80 +10.95 62.5% 1.40
08 158 +1.62 53.2% 1.03 20 55 +11.68 61.8% 1.66
09 145 −7.31 49.7% 0.89 22 40 +12.48 67.5% 2.01
12 180 +16.94 54.4% 1.22

(Entry hour is the open of the bar after the signal bar; the blocked close hours 0, 1, 2, 10, 11, 13, 16, 21 leave the gaps.)

Weekday Trades Total R WR PF Max DD
Mon 309 +25.97 57.3% 1.21 15.8
Tue 394 +40.58 60.2% 1.29 17.4
Wed 386 −18.07 50.5% 0.90 25.4
Thu 356 +50.99 56.5% 1.37 22.3
Fri 358 +47.13 58.4% 1.35 19.3
Sun 19 +10.82 78.9% 3.64 2.1

Tail: the top 5% of trades (91) carry +249.8R of the +157.4R total; median R +0.113; largest win +9.07R, largest loss −2.04R; mean hold 70.5 bars. Same fat-right-tail shape as the 3-year cycle-1 reading (94–96% of R in the top 5% there).

3. What to do with this

Nothing. The numbers describe the shipped configuration on a window the owner does not use for decisions; the per-hour, per-weekday and per-direction tables are in-book statistics on a five-year mix of setup gates and must not be turned into filters (rule 1 needs a control-vs- candidate run on the validated windows, and the 2026-08-04 age/stretch and 2026-09-06 sizing verdicts already refute the obvious ones). If the owner wants the pre-2024 weakness explained, the honest next step is a --record --record-bars run on this window with the twin (seconds) and a scorecard on the dollar-floor gates by year, not a parameter change.