Files
ForexBot2/backtest/research/m5_5yr_cuda_2026-09-18.md
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

157 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# M5 five-year book on the CUDA research twin — 2026-09-18
Owner request, the companion of `m15_5yr_cuda_2026-09-18.md`: a five-year M5 backtest with
`backtest/cudaBasedBacktesting.py`. Same owner-requested exception to the three-year cap
(CLAUDE.md rule 1), same status: a read-out of the shipped configuration on a longer window,
nothing tuned, nothing ships.
## 1. Runs
Window 2021-08-01 → 2026-08-04 (kept 5-year cache, padded files
`oanda_XAU_USD_{5min,15min,1h}_20210531_20260804.parquet`; 0 cache fallbacks; 367,394 M5 bars,
355,096 replayed; skipped 139,064 `SESSION_WINDOW`, 247 `WEEKEND_FILTER`). Factory config (M5:
hour 9 blocked and 21 open, chart-pattern entries on, pullbacks off), no overrides.
```
venv/bin/python backtest/cudaBasedBacktesting.py --pair XAUUSD --primary-tf 5min --start 2021-08-01 --end 2026-08-04 --spread 0.65 --export-csv cuda_m5_5yr_0.65.csv
venv/bin/python backtest/cudaBasedBacktesting.py --pair XAUUSD --primary-tf 5min --start 2021-08-01 --end 2026-08-04 --spread 0.30 --export-csv cuda_m5_5yr_0.30.csv
venv/bin/python backtest/gpu_backtest.py --pair XAUUSD --primary-tf 5min --start 2021-08-01 --end 2026-08-04 --spread 0.65 --workers 12 --export-csv ctrl_m5_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)` | 5.2 s (K1 520,523 bars 0.045 s, K2 355,096 bars 0.004 s, trade sim 0.38 s) | `0429885713ca34653a39754c013db501` |
| twin $0.30 | `CuPy GPU (NVIDIA GeForce RTX 4070 SUPER, cupy 14.0.1)` | 5.6 s | `87bfdba14090459f715e1ee1f751a6cb` |
| reference $0.65 | `CuPy GPU (NVIDIA GeForce RTX 4070 SUPER, cupy 14.0.1)`, `GPU cache fallbacks: 0` | 353.2 s (replay 348.7 s, 12 workers, 1,018 bars/s) | `0429885713ca34653a39754c013db501` — identical to the twin's (`cmp` equal) |
## 2. Results
905 trades at both costs (561 `TRAIL`, 290 `SL`, 54 `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 | 905 | +127.08 | 51.4% | 1.39 | 13.5 |
| $0.65 | first half 2021-08-01 → 2024-02-01 | 129 | −8.98 | 43.4% | 0.82 | 12.4 |
| $0.65 | second half 2024-02-02 → 2026-08-04 | 776 | +136.06 | 52.7% | 1.49 | 9.6 |
| $0.30 | whole | 905 | +147.83 | 52.5% | 1.46 | 10.6 |
| $0.30 | first half | 129 | −5.20 | 45.0% | 0.89 | 10.6 |
| $0.30 | second half | 776 | +153.03 | 53.7% | 1.57 | 8.9 |
Against rule 1 for the record: the five-year window fails it (first half negative), on a first
half of only 129 trades. The shipped M5 configuration was validated on 2024-09-05 → 2026-09-05
(+146.1R, PF 1.52, 781 trades) and the 12-month window (+108.8R, PF 1.54).
### Per year
| Year | Trades | $0.65 R | WR | PF | Max DD | $0.30 R | PF |
|---|---|---|---|---|---|---|---|
| 2021 (Aug–Dec) | 12 | −1.99 | 41.7% | 0.59 | 2.5 | −1.60 | 0.65 |
| 2022 | 50 | −2.18 | 44.0% | 0.90 | 11.1 | −0.71 | 0.97 |
| 2023 | 61 | −2.75 | 42.6% | 0.87 | 10.3 | −1.00 | 0.95 |
| 2024 | 102 | +0.97 | 49.0% | 1.02 | 8.2 | +4.30 | 1.11 |
| 2025 | 332 | +40.54 | 50.6% | 1.34 | 9.6 | +48.63 | 1.42 |
| 2026 (Jan–Aug 4) | 348 | +92.49 | 55.7% | 1.77 | 9.2 | +98.21 | 1.83 |
Two things the M15 window did not show as sharply:
1. **M5 barely trades before 2025.** 225 trades in the first 3.4 years against 680 in the last
1.6. Trade generation on M5 is governed by dollar-denominated floors: target 1 must clear
30 × $0.30 = $9 (`SPREAD GATE`), the generic and chart-pattern stops are floored at $8, and a
chart pattern needs a $9 height. At 2021–2023 prices and volatility an M5 ATR of $1.5–3 puts a
1.5 × ATR target far below the floor, so the spread gate vetoed almost every setup and only
high-volatility bursts survived. The pre-2025 M5 book is therefore a burst-only sample, not the
shipped strategy under normal conditions.
2. **One quarter carries the window.** 2026-Q1 made +90.2R of the +127.1R total (71%); 2025 Q1–Q2
another +32.3R. Quarterly R outside those three quarters ranges −6.5 … +5.8. This is the
fat-right-tail shape of every M5 reading (cycle 1: the top 5% of trades = 94–96% of R; here the
top 5%, 45 trades, carry +145.8R of +127.1R) compounded by a single very favourable quarter.
### Breakdowns ($0.65)
| Grade | Trades | Total R | WR | PF | Max DD |
|---|---|---|---|---|---|
| A+ | 1 | −0.03 | 0.0% | 0.00 | 0.0 |
| A | 247 | +53.72 | 55.1% | 1.69 | 7.2 |
| B | 637 | +73.66 | 50.2% | 1.30 | 16.4 |
| C | 20 | −0.26 | 45.0% | 0.97 | 3.2 |
| Generator | Trades | Total R | WR | PF | Max DD |
|---|---|---|---|---|---|
| GENERIC | 447 | +70.36 | 52.8% | 1.46 | 8.1 |
| XAU_CP | 427 | +48.52 | 49.9% | 1.29 | 14.4 |
| XAU_ATR | 31 | +8.20 | 51.6% | 1.89 | 3.8 |
Generator by year (trades / R): GENERIC 2021 4 / +0.4, 2022 23 / +4.4, 2023 32 / −2.9, 2024
37 / +6.6, 2025 170 / +18.1, 2026 181 / +43.8; XAU_CP 2021 8 / −2.4, 2022 27 / −6.5, 2023
29 / +0.2, 2024 65 / −5.7, 2025 159 / +21.6, 2026 139 / +41.3; XAU_ATR appears only in 2025 (3)
and 2026 (28), the same dollar-floor effect as on M15. The chart-pattern path is negative through
2024 (−14.4R over 129 trades) and positive since (+62.9R over 298); its validation
(2026-08-04, +38.9R of the 12-month book) covered the recent regime only.
| Direction | Trades | Total R | WR | PF | Max DD |
|---|---|---|---|---|---|
| BUY | 808 | +119.68 | 51.4% | 1.41 | 15.2 |
| SELL | 97 | +7.40 | 51.5% | 1.21 | 11.4 |
Shorts are nearly absent before 2025 (9 trades in 2021–2024) under the M5 SELL gates; 2025 32 /
−2.8R, 2026 56 / +12.0R.
| Regime | Trades | Total R | WR | PF | Max DD |
|---|---|---|---|---|---|
| trending_up | 481 | +75.44 | 53.4% | 1.44 | 11.9 |
| ranging | 174 | +24.78 | 50.0% | 1.36 | 8.3 |
| trending_down | 94 | +6.61 | 51.1% | 1.19 | 12.4 |
| transitioning | 84 | +19.59 | 46.4% | 1.69 | 6.9 |
| trending (mixed) | 72 | +0.67 | 47.2% | 1.02 | 10.5 |
| Volatility | Trades | Total R | WR | PF | Max DD |
|---|---|---|---|---|---|
| low | 250 | +62.92 | 51.6% | 1.70 | 12.4 |
| normal | 169 | +0.69 | 47.9% | 1.01 | 12.5 |
| extreme | 486 | +63.47 | 52.5% | 1.38 | 13.3 |
(`high` has no row: the M5 chop-transition gate blocks it.)
| Entry hour UTC | Trades | Total R | WR | PF | | Entry hour UTC | Trades | Total R | WR | PF |
|---|---|---|---|---|---|---|---|---|---|---|
| 03 | 52 | +8.49 | 50.0% | 1.41 | | 15 | 121 | +12.81 | 53.7% | 1.30 |
| 04 | 31 | +3.22 | 61.3% | 1.27 | | 17 | 47 | −2.61 | 48.9% | 0.86 |
| 05 | 50 | +7.15 | 52.0% | 1.32 | | 18 | 51 | +13.17 | 58.8% | 1.76 |
| 06 | 56 | +24.31 | 58.9% | 2.47 | | 19 | 51 | +2.96 | 49.0% | 1.18 |
| 07 | 52 | +2.50 | 53.8% | 1.14 | | 20 | 43 | +31.45 | 46.5% | 2.80 |
| 08 | 63 | −4.88 | 41.3% | 0.81 | | 21 | 12 | +16.02 | 75.0% | 6.16 |
| 12 | 69 | +7.01 | 53.6% | 1.28 | | 22 | 37 | +4.14 | 45.9% | 1.32 |
| 14 | 170 | +1.37 | 47.6% | 1.02 | | | | | | |
(Entry hour is the open of the bar after the signal bar; M5 blocks close hours 0, 1, 2, 9, 10,
11, 13, 16 and leaves 21 open.)
| Weekday | Trades | Total R | WR | PF | Max DD |
|---|---|---|---|---|---|
| Mon | 172 | +20.80 | 55.8% | 1.36 | 12.3 |
| Tue | 180 | +24.22 | 52.8% | 1.36 | 13.2 |
| Wed | 200 | +30.84 | 48.5% | 1.43 | 11.4 |
| Thu | 167 | +5.27 | 48.5% | 1.08 | 13.3 |
| Fri | 177 | +41.41 | 50.3% | 1.62 | 9.2 |
| Sun | 9 | +4.55 | 77.8% | 3.22 | 1.0 |
Tail: median R +0.031; largest win +5.53R, largest loss −1.84R; mean hold 76.6 bars.
## 3. What to do with this
Nothing ships. Two honest readings for the owner:
- The five-year M5 figure (+127R) is not "five years of edge"; it is the validated 2024-09 →
2026-09 book plus three and a half years in which the dollar floors kept M5 almost out of the
market and the few trades that got through lost a little. The three-year cap already keeps
decisions inside the period where the gates behave as designed.
- The concentration in 2026-Q1 (71% of the window's R) is a fact about the shipped M5 edge, not
about the window length. It is consistent with every earlier M5 reading and is the reason the
advisory outcomes over a quiet fortnight can look nothing like the book.
If the owner wants the floor effect measured rather than inferred, a `--record --record-bars`
run of this window on the twin (seconds) with a by-year count of `SPREAD GATE` and `LOW ATR
FILTER` warnings per analysed bar would settle it. Changing the floors is a rule-1 event in its
own right (`round_trip_cost` drives the live target floor, CLAUDE.md rule 1) and is not proposed.