Daily-trend veto on M15 + lot-size / already-open lines (campaign 2026-09-30), and the 2026-10-01 whole-codebase bug review
Two bodies of work that touch the same files, so one commit. Direction and setup-size campaign (2026-09-30 → 10-01, owner's RISK-FIRST rule, written before the runs): - SIGNAL: M15 daily-trend veto (factory override 7, xau_strategy.daily_trend_veto "both"). A finished setup against a clear daily trend (closed D1 bars, Sunday stubs dropped; close vs its 50-bar EMA AND vs the close 60 kept days earlier) is removed as the last step of the core. One definition (signal_aggregator.daily_trend_series) for live, the bar replay and the twin's host side; D1 is a required frame of the M15 scan; mirrored in cuda_signal_kernels.py K2. W3 824 / +205.12R / PF 1.73 / max DD 12.4R vs 1105 / +195.79R / 1.49 / 20.9R; 2019 → 2026 1473 / +223.33R / 1.42 / 41.5R vs 2091 / +192.53R / 1.24 / 64.8R; unseen holdout −4.62R vs −6.63R. - FAILED, not shipped: the veto on M5 (W3 drawdown 10.1R → 15.2R) and on H1 (−9.7R), buy-only and sell-only on M15, the wide-stop cap (xau_strategy.wide_stop_cap_atr stays 0.0, a research knob). - New M15 pins: W2 dfc647ee…, OOS e87b6de1…, W3 ad3b0dbd…. M5 / H1 / H4 pins unchanged. --set xau_strategy.daily_trend_veto=off reproduces the previous M15 pins byte for byte. Twin and reference script MD5-equal on every window; recorder and feature-export parity re-proved; base-rate table rebuilt. - DISPLAY (books byte-identical): exposure.py — the lot size for trade_size.risk_per_trade (new config.json block, off by default, private to the owner) and the count of alerted same-direction plans still open (signals.alerted_at, read-only open_alerted_setups); the daily trend in words on Telegram, the CLI and the dashboard; signals.daily_trend logged. - providers/oanda: a date window with no bars is an empty page, not an error (a D1 pad starting on a Saturday could not be fetched). - Reports only, nothing shipped: seven context screens (no state nominated) and eight outside data sources (none adds a forecast to gold's own daily trend). - Independent verification (report section 5.13): every figure reproduced on both scripts, scoring identical to the previous commit on all four timeframes, no look-ahead. Caveats recorded there: this is a risk filter, not a more accurate direction call; nine tenths of the 2019 → 2026 gain is 2022; the neighbour clause is thin (a simple 100-day average misses the R line by 1.2R); "never adds a trade" is an observation, not a guarantee. Bug review of the whole codebase (2026-10-01). Signal path clean. 17 defects elsewhere, plus 4 found by an independent review of the fixes; all fixed, each with a test; no trade book changed: - telegram_bot: one _deliver_alert for the candle scan and the level break. The row is stamped alerted_at BEFORE the send, on a one-worker alert-db pool, and un-stamped when no chat received it or the task is cancelled mid-stamp, so two alerts at one candle close count each other and no SQLite write runs on the event loop. The 5-bar cooldown counts bars of the scan's own frame (== gpu_backtest._apply_cooldown; clock time released the 22:00 UTC bar after the settlement pause) and is restored from signals.db at start-up. The lot-size line goes to the owner's own chat only (a group the owner ran /autoscan in used to receive it). /status gains a news-model line and escapes failure details. - signal_log: mark_alerted returns the stamp it wrote; unmark_alerted; last_alerted_bars (read-only). - advisory_outcome: candle continuity is judged bar by bar inside the walk; a hole after a trade's exit no longer voids it. The stored-candle replay resolves 108 of 111 logged setups instead of 99, all equal to the live resolver's R. - providers/oanda: an empty date window is accepted only when it is 5 days or shorter and no malformed candle was skipped; a longer one is retried, then refused, instead of being cached as history with a hole. - news_engine: blank RSS titles skipped; one unreadable headline no longer costs the local model its whole batch (checked on the real bundle); model health recorded; no DeepSeek audit call in a process that does not archive; event-direction cache keyed per release; peek_week_events never fetches. - llm_client: chat_json never raises and never logs the API key (requests quotes the Authorization value in InvalidHeader; error bodies are redacted). - signal_aggregator: the scan's news block is guarded; the replay path (use_news=False) assigns exactly the values it did before. - agent_panel: PANEL_PROMPT_VERSION v2.2 — same prompt text, corrected input (event timing over the cached calendar week, headlines newest first). scripts/panel_replay.py replays the logged payload per persona; scripts/label_scan_outcomes.py counts with an ISO cutoff. - test_all.py: no ALTER TABLE … DROP COLUMN (the live box has SQLite 3.34); tests that write Parquet print a notice and return without pyarrow. Verification after the last code change: suite 632 passed, 0 failed (also with both Parquet engines blocked and FB2_BACKEND=cpu, the live box's view); the five reference MD5s reproduce on both backtesters, 0 cache fallbacks; Module 37 green; static Python 3.9 / SQLite 3.34 check clean on every touched file. Evidence: backtest/research/daily_trend_campaign_2026-09-30.md, context_screens_2026-10.md, new_inputs_2026-10.md; CLAUDE.md sections 2, 4, 6, 8, 9, 10 and 11; pair_signals/xauusd.py docstring (M15 override 7).
This commit is contained in:
@@ -0,0 +1,639 @@
|
||||
# Daily-trend veto and wide-stop cap — pre-registered campaign, 2026-09-30
|
||||
|
||||
Owner request (2026-09-30): improve the direction call and the trade setup size; anything may
|
||||
change if the evidence supports it. This file holds the rules first, then the results. Sections 1
|
||||
to 4 were written before any formal run. Section 2 records what was already looked at while
|
||||
planning, so the reader knows which numbers are a confirmation and which are a first look.
|
||||
|
||||
## 1. What is tested
|
||||
|
||||
**Candidate T — daily-trend veto.** The engine sees at most the H1 chart (M5 confirms on M15 and
|
||||
H1, M15 on M5 and H1). None of the 65 decision-time features of the earlier campaigns reads the
|
||||
daily chart. The candidate drops a finished trade setup that goes against a clear daily trend.
|
||||
|
||||
Definition (fixed; `signal_aggregator.daily_trend_series`):
|
||||
- daily candles from the provider (UTC-aligned, label = 00:00 UTC of the day), closed bars only:
|
||||
a bar labelled D is used once D + 1 day ≤ the close of the primary bar;
|
||||
- bars labelled Sunday are dropped first (Oanda's 1 to 2 hour reopening stub);
|
||||
- `ema = Close.ewm(span=50, adjust=False).mean()`, `change = Close / Close.shift(60) − 1`;
|
||||
- state +1 when `Close > ema` and `change > 0`; −1 when `Close < ema` and `change < 0`; else 0;
|
||||
- after every setup archetype has run (gold ATR, swing, pullback, chart pattern) a setup against a
|
||||
non-zero state is removed: grade D, no setup, warning `DAILY TREND FILTER: …`.
|
||||
Switch `xau_strategy.daily_trend_veto`: `off` (default, books byte-identical), `both`, `buy`
|
||||
(only buys against a falling daily trend are removed), `sell`.
|
||||
|
||||
**Candidate C — wide-stop cap.** `xau_strategy.wide_stop_cap_atr = K` caps the stop distance of
|
||||
the swing (GENERIC) and chart-pattern setups at `max(K × ATR, the existing floor)`, applied after
|
||||
the min-RR and spread gates so the set of trades cannot change. K = 6, with 5, 7 and 8 declared
|
||||
as neighbours. M15 only (the exit-only screen was negative on M5).
|
||||
|
||||
## 2. What was already seen (planning phase, 2026-09-30, read-only, in memory)
|
||||
|
||||
Prototype: K1 and K2 of the CUDA twin, then a host-side mask on the final candidates before the
|
||||
5-bar cooldown, then the shared resolver. The control rows of the prototype reproduce the pinned
|
||||
books (M15 W3 1105 / +195.79R, M5 W3 870 / +153.64R, H1 W3 253 / +70.02R).
|
||||
|
||||
| Book ($0.65) | Control | Veto, both directions |
|
||||
|---|---|---|
|
||||
| M15 W3 2023-09-05 → 2026-09-05 | 1105 / +195.8R / PF 1.49 / DD 20.9 | 824 / +205.1R / PF 1.73 / DD 12.4 |
|
||||
| M15 LONG 2019-01-01 → 2026-08-07 | 2091 / +192.5R / PF 1.24 / DD 64.8 | 1473 / +223.3R / PF 1.42 / DD 41.5 |
|
||||
| M15 rising window 2024-06-01 → 2025-03-30 | 313 / +68.5R / PF 1.67 | 258 / +63.8R / PF 1.80 |
|
||||
| M5 W3 | 870 / +153.6R / PF 1.50 / DD 10.1 | 668 / +159.1R / PF 1.70 / DD 15.2 |
|
||||
| M5 W3, buy side only | | 741 / +156.5R / PF 1.60 / DD 9.6 |
|
||||
| M5 LONG | 1052 / +128.1R / PF 1.34 / DD 18.4 | 790 / +127.5R / PF 1.45 / DD 25.2 |
|
||||
| H1 W3 | 253 / +70.0R / PF 1.98 / DD 4.4 | 231 / +60.3R / PF 1.90 / DD 4.4 |
|
||||
|
||||
Also seen: neighbouring definitions on M15 (60-day change alone +188.3R W3 / +228.1R LONG;
|
||||
90-day +196.1 / +228.8; 120-day +199.4 / +233.2; 100-day average +201.2 / +227.3); the share of
|
||||
M15 W3 trades reaching +1R before −1R (58.6% → 61.4%); the live September 2026 setups with the
|
||||
veto applied after the fact (cooldown view −11.6R → −6.0R to −8.8R); an exit-only re-simulation
|
||||
of 25 stop and exit variants (cap 6 × ATR on M15 W3 +14.0R, LONG +11.8R; cap 5 negative on LONG);
|
||||
two variants dropped at this stage and NOT tested formally: lifting the SELL gates when the daily
|
||||
trend is down (worse on LONG on both timeframes), and removing the existing M15 short blocks
|
||||
under the veto (costs 4 to 22R).
|
||||
|
||||
So the windows W3, W2, the rising window and LONG are a CONFIRMATION through the real code path.
|
||||
First looks are: the HOLDOUT window through the backtester, the $0.30 numbers on LONG, and every
|
||||
number produced by the shipped code rather than the prototype.
|
||||
|
||||
## 3. Harness
|
||||
|
||||
`venv/bin/python backtest/cudaBasedBacktesting.py --pair XAUUSD --primary-tf <tf> --start <s>
|
||||
--end <e> --spread <0.65|0.30> [--set xau_strategy.daily_trend_veto=<mode>]
|
||||
[--set xau_strategy.wide_stop_cap_atr=<K>] --export-csv <out>`; factory configuration otherwise.
|
||||
Twin numbers count only with the paired `backtest/gpu_backtest.py` MD5 (same flags plus
|
||||
`--workers 12`). Neighbouring trend definitions are not shipped code: they run on the research
|
||||
harness (the prototype), after the harness book for the shipped definition is shown identical to
|
||||
the twin's.
|
||||
|
||||
Windows: **W3** 2023-09-05 → 2026-09-05 (halves at 2025-03-05); **W2** 2024-09-05 → 2026-09-05
|
||||
(halves at 2025-09-05); **RISING** 2024-06-01 → 2025-03-30 (the old out-of-sample window; a
|
||||
rising market throughout); **LONG** 2019-01-01 → 2026-08-07; **HOLDOUT** 2026-09-05 → 2026-10-01
|
||||
(fetched for this campaign, never seen by any tuning or by the prototype).
|
||||
|
||||
## 4. Acceptance rules (written before the runs)
|
||||
|
||||
**Rule T (risk-first; owner decision 2026-09-30).** Candidate T on a timeframe PASSES only if,
|
||||
against the same-harness control:
|
||||
- (a) W3 total R ≥ 97% of the control's at $0.65;
|
||||
- (b) W3 profit factor ≥ control + 0.10;
|
||||
- (c) W3 max drawdown ≤ the control's;
|
||||
- (d) LONG: total R ≥ control, max drawdown ≤ control, and 2021 + 2022 combined R better;
|
||||
- (e) HOLDOUT total R ≥ control − 0.5R;
|
||||
- (f) clauses (a) to (c) also hold at $0.30;
|
||||
- (g) at least 3 of the 4 neighbouring definitions (60-day change alone, 90-day, 120-day,
|
||||
100-day average alone) satisfy (a) and (c): a plateau, not a spike;
|
||||
- (h) at least 20 trades differ on W3.
|
||||
Reported, NOT clauses (the owner accepted this cost on 2026-09-30): the W2 halves and the RISING
|
||||
window, where the veto is expected to give up some R. The 2026-09-26 template (every half and the
|
||||
old out-of-sample window must not lose) would reject this candidate by construction; that is the
|
||||
difference between the two rules and it is deliberate.
|
||||
Decision per timeframe: `both` if it passes; else `buy` if that passes; else no veto (the daily
|
||||
trend is then shown on the alert as information only). H1 is run for the record.
|
||||
|
||||
**Rule C (standard).** K = 6 on M15 against the post-T control PASSES only if: W3 ΔR ≥ +5R; both
|
||||
W3 halves ≥ control − 1R; PF ≥ control − 0.02; W3 max drawdown ≤ control + 10%; LONG total R ≥
|
||||
control; the same sign of ΔR at $0.30; at least 20 trades differ; and the neighbours K = 5 and
|
||||
K = 7 are not negative on W3 or on LONG.
|
||||
|
||||
No rescue for either rule: no second definition, no other K, no window shopping after the result.
|
||||
|
||||
## 5. Results
|
||||
|
||||
All runs 2026-09-30 on the dev box, branch `sql-integration`, working tree = HEAD `0c56b4e` plus
|
||||
this campaign's code. Every twin log reads
|
||||
`Backend: CuPy GPU (NVIDIA GeForce RTX 4070 SUPER, cupy 14.0.1)` and
|
||||
`GPU cache fallbacks: 0 (no per-bar recompute path in cudaBasedBacktesting)`; every reference log
|
||||
reads the same `Backend:` line and `GPU cache fallbacks: 0`. 86 formal twin books (5 windows × 2
|
||||
costs × the variants below, plus the fixed-1R-target books). R is per trade in units of the
|
||||
initial risk; "DD" is the largest peak-to-trough fall of the running total, in R.
|
||||
|
||||
### 5.1 Proofs before any formal number
|
||||
|
||||
- **Baseline.** Before any code change the five reference MD5s of CLAUDE.md §9 were reproduced on
|
||||
both scripts (ten books).
|
||||
- **Default-off neutrality.** With the new code and both knobs at their defaults the same ten
|
||||
books are byte-identical to the pins (`e599c8a8…` M5 W2, `5b65ecf6…` M15 W2, `09b8a8e7…` M15
|
||||
OOS, `a44fd19b…` H1 W3, `f3587bae…` H4 W3).
|
||||
- **Twin = reference on every new path** (`--spread 0.65`, W3 2023-09-05 → 2026-09-05, equal MD5
|
||||
from `backtest/gpu_backtest.py --workers 12` and `backtest/cudaBasedBacktesting.py`):
|
||||
|
||||
| Flags | Trades / R / DD | MD5 (both scripts) |
|
||||
|---|---|---|
|
||||
| M15 `--set xau_strategy.daily_trend_veto=both` | 824 / +205.12 / 12.39 | `ad3b0dbda0bf77b659caea1c53be6a50` |
|
||||
| M15 `…=buy` | 999 / +188.21 / 20.87 | `6e0f3b742d9690f78c97319d1b1c8a43` |
|
||||
| M15 `…=sell` | 930 / +212.70 / 13.72 | `31aa5762964d846f15d111cd4a718adc` |
|
||||
| M15 `--set xau_strategy.wide_stop_cap_atr=6` | 1105 / +209.78 / 19.32 | `4ec0e4450d5dab143a4ed37e80545626` |
|
||||
| M5 `--set xau_strategy.daily_trend_veto=both` | 668 / +159.07 / 15.20 | `39cc0f198d38b532720dce4f98d99452` |
|
||||
| M5 `--set xau_strategy.wide_stop_cap_atr=6` | 870 / +141.57 / 13.95 | `4da0997256b272ffcd11a90bf9658eef` |
|
||||
|
||||
The M15 `both` book equals the planning prototype trade for trade (824 / +205.1R / PF 1.73 /
|
||||
DD 12.4), so the shipped definition is the one that was screened.
|
||||
- **Suite.** 595 passed / 0 failed after Stage 1 (Module 39 new, Module 37 extended).
|
||||
|
||||
### 5.2 Candidate T — every window, both costs
|
||||
|
||||
Command per row: `venv/bin/python backtest/cudaBasedBacktesting.py --pair XAUUSD --primary-tf
|
||||
<15min|5min> --start <s> --end <e> --spread <0.65|0.30> [--set xau_strategy.daily_trend_veto=<mode>]
|
||||
--export-csv <out>`. "control" = no `--set`.
|
||||
|
||||
**M15**
|
||||
|
||||
| Window | Cost | Variant | Trades | Total R | Win rate | PF | Max DD | First half | Second half | MD5 (8) |
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
| W3 | $0.65 | control | 1105 | +195.79 | 61.1% | 1.49 | 20.9 | +76.87 | +118.92 | 70195fb0 |
|
||||
| W3 | $0.65 | both | 824 | +205.12 | 63.1% | 1.73 | 12.4 | +76.72 | +128.40 | ad3b0dbd |
|
||||
| W3 | $0.65 | buy | 999 | +188.21 | 61.3% | 1.52 | 20.9 | +60.40 | +127.81 | 6e0f3b74 |
|
||||
| W3 | $0.65 | sell | 930 | +212.70 | 62.7% | 1.66 | 13.7 | +93.19 | +119.52 | 31aa5762 |
|
||||
| W3 | $0.30 | control | 1105 | +216.53 | 61.4% | 1.55 | 19.6 | +88.86 | +127.67 | ce074a1b |
|
||||
| W3 | $0.30 | both | 824 | +221.18 | 63.6% | 1.81 | 11.4 | +86.41 | +134.77 | 96a87454 |
|
||||
| W3 | $0.30 | buy | 999 | +207.23 | 61.7% | 1.59 | 19.6 | +71.83 | +135.41 | 2ada14e4 |
|
||||
| W3 | $0.30 | sell | 930 | +230.48 | 63.1% | 1.73 | 12.8 | +103.45 | +127.03 | 49665c41 |
|
||||
| W2 | $0.65 | control | 813 | +154.15 | 62.2% | 1.53 | 15.6 | +70.10 | +84.04 | 5b65ecf6 |
|
||||
| W2 | $0.65 | both | 597 | +155.89 | 64.3% | 1.78 | 11.4 | +61.83 | +94.06 | dfc647ee |
|
||||
| W2 | $0.65 | buy | 718 | +154.67 | 63.0% | 1.62 | 14.4 | +65.03 | +89.65 | f23bfda4 |
|
||||
| W2 | $0.65 | sell | 692 | +155.36 | 63.3% | 1.65 | 13.7 | +66.91 | +88.46 | 1a071ac7 |
|
||||
| W2 | $0.30 | control | 813 | +167.53 | 62.6% | 1.59 | 14.5 | +78.61 | +88.91 | 15486607 |
|
||||
| W2 | $0.30 | both | 597 | +166.22 | 64.8% | 1.85 | 11.0 | +68.82 | +97.39 | d2f678bf |
|
||||
| W2 | $0.30 | buy | 718 | +166.64 | 63.4% | 1.68 | 14.0 | +73.12 | +93.52 | f3abc1e8 |
|
||||
| W2 | $0.30 | sell | 692 | +167.10 | 63.7% | 1.71 | 12.8 | +74.31 | +92.79 | d7d038fd |
|
||||
| RISING | $0.65 | control | 313 | +68.50 | 63.6% | 1.67 | 12.4 | +18.87 | +49.63 | 09b8a8e7 |
|
||||
| RISING | $0.65 | both | 258 | +63.78 | 64.3% | 1.80 | 9.1 | +23.97 | +39.81 | e87b6de1 |
|
||||
| RISING | $0.65 | buy | 303 | +60.15 | 63.0% | 1.60 | 12.4 | +18.87 | +41.28 | f001a0a6 |
|
||||
| RISING | $0.65 | sell | 268 | +72.13 | 64.9% | 1.89 | 9.1 | +23.97 | +48.16 | cbe4cb24 |
|
||||
| RISING | $0.30 | control | 313 | +76.21 | 64.5% | 1.77 | 11.1 | +22.92 | +53.29 | 5fc34cef |
|
||||
| RISING | $0.30 | both | 258 | +70.24 | 65.5% | 1.91 | 7.9 | +27.31 | +42.92 | 5de32f51 |
|
||||
| RISING | $0.30 | buy | 303 | +67.59 | 64.0% | 1.70 | 11.1 | +22.92 | +44.67 | 69b41026 |
|
||||
| RISING | $0.30 | sell | 268 | +78.86 | 66.0% | 2.00 | 7.9 | +27.31 | +51.54 | 3631466e |
|
||||
| LONG | $0.65 | control | 2091 | +192.53 | 57.8% | 1.24 | 64.8 | | | c2228398 |
|
||||
| LONG | $0.65 | both | 1473 | +223.33 | 59.7% | 1.42 | 41.5 | | | aa5253aa |
|
||||
| LONG | $0.65 | buy | 1762 | +214.62 | 58.9% | 1.33 | 34.5 | | | 952d64d8 |
|
||||
| LONG | $0.65 | sell | 1802 | +201.23 | 58.3% | 1.30 | 76.4 | | | d3965ab8 |
|
||||
| LONG | $0.30 | control | 2091 | +240.00 | 58.8% | 1.31 | 49.6 | | | 0c58b300 |
|
||||
| LONG | $0.30 | both | 1473 | +257.25 | 60.8% | 1.50 | 37.2 | | | 1835b341 |
|
||||
| LONG | $0.30 | buy | 1762 | +254.33 | 59.9% | 1.40 | 29.5 | | | a2b519bd |
|
||||
| LONG | $0.30 | sell | 1802 | +242.92 | 59.4% | 1.37 | 62.3 | | | f6edb469 |
|
||||
| HOLDOUT | $0.65 | control | 24 | −6.63 | 50.0% | 0.42 | 7.0 | | | c42470a0 |
|
||||
| HOLDOUT | $0.65 | both | 18 | −4.62 | 50.0% | 0.50 | 4.8 | | | fa50bcd0 |
|
||||
| HOLDOUT | $0.65 | buy | 22 | −6.81 | 45.5% | 0.41 | 7.0 | | | 548a4bf4 |
|
||||
| HOLDOUT | $0.65 | sell | 20 | −4.44 | 55.0% | 0.52 | 4.8 | | | 1459ef5f |
|
||||
| HOLDOUT | $0.30 | control | 24 | −6.29 | 50.0% | 0.44 | 6.7 | | | d7fbee9d |
|
||||
| HOLDOUT | $0.30 | both | 18 | −4.35 | 50.0% | 0.52 | 4.5 | | | 2179c08c |
|
||||
| HOLDOUT | $0.30 | buy | 22 | −6.49 | 45.5% | 0.43 | 6.7 | | | 0b90faeb |
|
||||
| HOLDOUT | $0.30 | sell | 20 | −4.15 | 55.0% | 0.54 | 4.5 | | | 70932b7e |
|
||||
|
||||
**M5**
|
||||
|
||||
| Window | Cost | Variant | Trades | Total R | Win rate | PF | Max DD | First half | Second half | MD5 (8) |
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
| W3 | $0.65 | control | 870 | +153.64 | 53.3% | 1.50 | 10.1 | +16.73 | +136.91 | d20ec8a3 |
|
||||
| W3 | $0.65 | both | 668 | +159.07 | 53.9% | 1.70 | 15.2 | +14.01 | +145.06 | 39cc0f19 |
|
||||
| W3 | $0.65 | buy | 741 | +156.53 | 53.4% | 1.60 | 9.6 | +15.68 | +140.85 | 631f25ac |
|
||||
| W3 | $0.30 | control | 870 | +172.40 | 54.3% | 1.57 | 8.9 | +21.08 | +151.32 | 5acafcba |
|
||||
| W3 | $0.30 | both | 668 | +174.43 | 54.8% | 1.79 | 14.3 | +18.09 | +156.34 | 34f2e282 |
|
||||
| W3 | $0.30 | buy | 741 | +172.72 | 54.3% | 1.69 | 8.9 | +19.87 | +152.86 | c8bdc9e2 |
|
||||
| W2 | $0.65 | control | 781 | +146.07 | 52.9% | 1.52 | 10.1 | +26.42 | +119.65 | e599c8a8 |
|
||||
| W2 | $0.65 | both | 585 | +153.82 | 53.7% | 1.78 | 15.2 | +33.16 | +120.66 | b9fa356c |
|
||||
| W2 | $0.65 | buy | 656 | +151.09 | 53.0% | 1.66 | 9.6 | +27.42 | +123.66 | 30e243b0 |
|
||||
| W2 | $0.30 | control | 781 | +162.09 | 53.9% | 1.60 | 8.9 | +31.71 | +130.37 | 7ab48db9 |
|
||||
| W2 | $0.30 | both | 585 | +166.59 | 54.7% | 1.87 | 14.3 | +38.05 | +128.54 | 3427b933 |
|
||||
| W2 | $0.30 | buy | 656 | +164.66 | 54.0% | 1.74 | 8.9 | +32.58 | +132.08 | 7dd9e2a2 |
|
||||
| RISING | $0.65 | control | 86 | +9.47 | 53.5% | 1.33 | 8.2 | +0.01 | +9.46 | 65c46e62 |
|
||||
| RISING | $0.65 | both | 81 | +9.07 | 54.3% | 1.34 | 7.5 | +0.67 | +8.40 | e20fdef2 |
|
||||
| RISING | $0.65 | buy | 85 | +10.55 | 54.1% | 1.39 | 7.2 | +0.01 | +10.54 | de24b2e8 |
|
||||
| RISING | $0.30 | control | 86 | +12.42 | 54.7% | 1.46 | 6.7 | +1.65 | +10.77 | 5c154360 |
|
||||
| RISING | $0.30 | both | 81 | +11.91 | 55.6% | 1.47 | 6.1 | +2.28 | +9.63 | 3b1a8f9e |
|
||||
| RISING | $0.30 | buy | 85 | +13.46 | 55.3% | 1.52 | 5.7 | +1.65 | +11.81 | 21ffab88 |
|
||||
| LONG | $0.65 | control | 1052 | +128.10 | 50.5% | 1.34 | 18.4 | | | 3f0c091c |
|
||||
| LONG | $0.65 | both | 790 | +127.47 | 50.4% | 1.45 | 25.2 | | | 9872c068 |
|
||||
| LONG | $0.65 | buy | 871 | +123.37 | 49.9% | 1.39 | 27.1 | | | 613dcf0e |
|
||||
| LONG | $0.30 | control | 1052 | +153.02 | 51.7% | 1.41 | 13.0 | | | 6708d8cc |
|
||||
| LONG | $0.30 | both | 790 | +147.13 | 51.5% | 1.54 | 19.6 | | | 201d968f |
|
||||
| LONG | $0.30 | buy | 871 | +144.02 | 51.1% | 1.47 | 22.3 | | | d9cba459 |
|
||||
| HOLDOUT | $0.65 | control | 33 | −2.45 | 51.5% | 0.82 | 6.1 | | | 351f7149 |
|
||||
| HOLDOUT | $0.65 | both | 26 | −2.04 | 50.0% | 0.81 | 5.4 | | | b9c8cb82 |
|
||||
| HOLDOUT | $0.65 | buy | 33 | −2.45 | 51.5% | 0.82 | 6.1 | | | 351f7149 |
|
||||
| HOLDOUT | $0.30 | control | 33 | −1.85 | 51.5% | 0.86 | 5.6 | | | 5a6aea9c |
|
||||
| HOLDOUT | $0.30 | both | 26 | −1.56 | 50.0% | 0.85 | 5.0 | | | ddd29068 |
|
||||
| HOLDOUT | $0.30 | buy | 33 | −1.85 | 51.5% | 0.86 | 5.6 | | | 5a6aea9c |
|
||||
|
||||
**H1, for the record** ($0.65): W3 control 253 / +70.02R / PF 1.98 / DD 4.4 (`a44fd19b`), `both`
|
||||
231 / +60.28R / PF 1.90 / DD 4.4 (`cdac563b`); HOLDOUT 3 / −3.04R in both (no trade removed).
|
||||
Fails (a) (60.28 < 67.92) and (b). H4 was not run: it confirms on the daily chart already.
|
||||
|
||||
### 5.3 Per calendar year ($0.65), total R / trades
|
||||
|
||||
M15, LONG 2019-01-01 → 2026-08-07:
|
||||
|
||||
| Variant | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| control | +9.0 / 117 | +48.8 / 283 | −25.6 / 210 | −24.6 / 267 | +11.7 / 211 | +53.3 / 343 | +81.2 / 425 | +38.7 / 235 |
|
||||
| both | +14.0 / 88 | +45.1 / 207 | −27.3 / 121 | +3.2 / 149 | +1.8 / 163 | +53.5 / 275 | +92.5 / 341 | +40.6 / 129 |
|
||||
| buy | +7.6 / 111 | +44.2 / 253 | −21.4 / 135 | +7.4 / 166 | +1.6 / 189 | +46.4 / 335 | +83.1 / 416 | +45.9 / 157 |
|
||||
| sell | +15.4 / 94 | +49.7 / 237 | −31.5 / 196 | −28.8 / 250 | +11.9 / 185 | +60.4 / 283 | +90.6 / 350 | +33.4 / 207 |
|
||||
|
||||
M5, LONG:
|
||||
|
||||
| Variant | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| control | −1.0 / 20 | −2.8 / 95 | −1.7 / 32 | −2.2 / 50 | −2.8 / 61 | +1.0 / 102 | +40.5 / 332 | +97.0 / 360 |
|
||||
| both | +0.2 / 17 | −6.9 / 76 | −3.4 / 14 | −4.7 / 28 | −3.5 / 54 | +1.5 / 96 | +43.2 / 297 | +101.0 / 208 |
|
||||
| buy | +0.2 / 17 | −6.7 / 83 | −3.2 / 16 | −6.0 / 30 | −4.6 / 56 | +2.1 / 101 | +40.5 / 329 | +101.0 / 239 |
|
||||
|
||||
M15, W3 per calendar year (total R / trades / max DD inside the year):
|
||||
|
||||
| Variant | 2023 (from 09-05) | 2024 | 2025 | 2026 (to 09-05) |
|
||||
|---|---|---|---|---|
|
||||
| control | +10.8 / 66 / 9.0 | +53.3 / 343 / 16.3 | +81.2 / 425 / 15.6 | +50.5 / 271 / 10.3 |
|
||||
| both | +9.3 / 47 / 6.9 | +53.5 / 275 / 11.0 | +92.5 / 341 / 11.4 | +49.9 / 161 / 8.3 |
|
||||
|
||||
M15, R per month from 2025-09 (W3):
|
||||
|
||||
| Variant | 2025-09 | 10 | 11 | 12 | 2026-01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 (to 09-05) |
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
| control | +14.7 | −1.4 | +3.7 | +19.4 | +29.1 | −2.2 | +9.5 | +4.4 | +0.0 | +1.7 | −4.6 | +12.4 | +0.2 |
|
||||
| both | +19.4 | +0.6 | +8.4 | +18.7 | +32.4 | −2.4 | +1.5 | +7.2 | −2.4 | +5.1 | +2.3 | +5.9 | +0.2 |
|
||||
|
||||
Losing runs on M15: longest run of losing trades 9 → 8 (W3 and LONG); worst calendar month
|
||||
−10.1R → −6.1R (W3, 2024-01) and −11.7R → −10.0R (LONG); losing months 11 → 8 of 37 on W3,
|
||||
39 of 92 → 37 of 91 on LONG.
|
||||
|
||||
### 5.4 Rule T, clause by clause
|
||||
|
||||
**M15 `both` — PASS**
|
||||
|
||||
| Clause | Result | Numbers (candidate vs control) |
|
||||
|---|---|---|
|
||||
| (a) W3 R ≥ 97% of control | PASS | +205.12 vs +195.79 (97% = +189.92) |
|
||||
| (b) W3 PF ≥ control + 0.10 | PASS | 1.734 vs 1.488 |
|
||||
| (c) W3 max DD ≤ control | PASS | 12.39 vs 20.87 |
|
||||
| (d) LONG R ≥ control | PASS | +223.33 vs +192.53 |
|
||||
| (d) LONG max DD ≤ control | PASS | 41.54 vs 64.77 |
|
||||
| (d) 2021 + 2022 better | PASS | −24.12 vs −50.21 |
|
||||
| (e) HOLDOUT R ≥ control − 0.5 | PASS | −4.62 (18 trades) vs −6.63 (24) |
|
||||
| (f) (a) at $0.30 | PASS | +221.18 vs +216.53 (97% = +210.04) |
|
||||
| (f) (b) at $0.30 | PASS | 1.809 vs 1.551 |
|
||||
| (f) (c) at $0.30 | PASS | 11.44 vs 19.56 |
|
||||
| (g) ≥ 3 of 4 neighbours pass (a) and (c) | PASS | 3 of 4 (table 5.5) |
|
||||
| (h) ≥ 20 trades differ on W3 | PASS | 281 removed, 0 added |
|
||||
|
||||
**M15 `buy` — FAIL**: (a) +188.21 < +189.92; (b) 1.523 < 1.588; the same two at $0.30.
|
||||
**M15 `sell` — FAIL**: (d) LONG max DD 76.39 > 64.77 and 2021 + 2022 −60.29 < −50.21. It has the
|
||||
best W3 total (+212.70R) and that is exactly the trap the long window was there to catch: in the
|
||||
falling years the buys against the daily trend are the losers, and `sell` keeps them.
|
||||
**M5 `both` — FAIL**: (c) W3 DD 15.20 > 10.11 (also at $0.30: 14.30 > 8.88); (d) LONG R
|
||||
+127.47 < +128.10, LONG DD 25.25 > 18.39, 2021 + 2022 −8.02 < −3.91; (g) 0 of 4.
|
||||
**M5 `buy` — FAIL**: (d) LONG R +123.37 < +128.10, LONG DD 27.14 > 18.39, 2021 + 2022 −9.13 <
|
||||
−3.91; (g) 1 of 4.
|
||||
**H1 `both` — FAIL** (a), (b).
|
||||
|
||||
### 5.5 Clause (g): neighbouring definitions (research harness)
|
||||
|
||||
The harness (K1 + K2 of the twin with the veto OFF, a host-side mask on the final candidates
|
||||
before the cooldown, the shared resolver) reproduces the twin's `--set` books byte for byte for
|
||||
the shipped definition, so it is the same thing as the shipped path for a final veto:
|
||||
|
||||
| Book ($0.65) | Harness CSV MD5 | Twin CSV MD5 |
|
||||
|---|---|---|
|
||||
| M15 W3 control | `70195fb0e6865b3a46ee8a9aa8844e51` | same |
|
||||
| M15 W3 `both` | `ad3b0dbda0bf77b659caea1c53be6a50` | same |
|
||||
| M15 LONG control | `c222839878f791e980b2dbc99fb6dfbd` | same |
|
||||
| M15 LONG `both` | `aa5253aab206fd21fa6a8d5ba25b75b5` | same |
|
||||
| M5 W3 control / `both` / `buy` | `d20ec8a3…` / `39cc0f19…` / `631f25ac…` | same |
|
||||
| M5 LONG control / `both` / `buy` | `3f0c091c…` / `9872c068…` / `613dcf0e…` | same |
|
||||
|
||||
M15, veto in both directions, each neighbour replacing the definition of "clear daily trend":
|
||||
|
||||
| Definition | W3 trades | W3 R | W3 PF | W3 DD | (a) | (c) | LONG trades | LONG R | LONG PF | LONG DD |
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
| control | 1105 | +195.79 | 1.49 | 20.87 | (97% = +189.92) | | 2091 | +192.53 | 1.24 | 64.77 |
|
||||
| **shipped: 50-day average AND 60-day change** | 824 | +205.12 | 1.73 | 12.39 | PASS | PASS | 1473 | +223.33 | 1.42 | 41.54 |
|
||||
| 60-day change alone | 752 | +188.25 | 1.73 | 11.89 | FAIL | PASS | 1328 | +228.11 | 1.49 | 27.30 |
|
||||
| 90-day change alone | 782 | +196.14 | 1.72 | 12.46 | PASS | PASS | 1412 | +228.75 | 1.46 | 37.36 |
|
||||
| 120-day change alone | 781 | +199.36 | 1.75 | 12.26 | PASS | PASS | 1397 | +233.19 | 1.47 | 34.79 |
|
||||
| 100-day average alone | 796 | +201.23 | 1.74 | 12.26 | PASS | PASS | 1375 | +227.30 | 1.47 | 32.56 |
|
||||
|
||||
3 of 4 pass. Every neighbour beats the control on PF and on drawdown in both windows; the one
|
||||
miss is 1.7R under the 97% line. It is a plateau. (Each neighbour has a lower LONG drawdown than
|
||||
the shipped definition; switching to one now would be the rescue the rule forbids.)
|
||||
|
||||
M5: `both` 0 of 4 (every neighbour keeps the 15.2R drawdown), `buy` 1 of 4 (90-day, 120-day and
|
||||
100-day average all fall under the 97% line). No plateau on M5.
|
||||
|
||||
### 5.6 What the veto removes (M15, $0.65)
|
||||
|
||||
Zero trades are added in any window (W3 and LONG, every variant, both timeframes): the setups
|
||||
inside a vetoed setup's 5-bar cooldown point the same way under the same daily state and are
|
||||
vetoed with it, so the cooldown displaces nothing.
|
||||
|
||||
| Slice | W3 trades | W3 R | W3 mean R | LONG trades | LONG R | LONG mean R |
|
||||
|---|---|---|---|---|---|---|
|
||||
| all removed | 281 | −9.32 | −0.033 | 618 | −30.80 | −0.050 |
|
||||
| BUY against a falling daily trend | 106 | +7.59 | +0.072 | 329 | −22.10 | −0.067 |
|
||||
| SELL against a rising daily trend | 175 | −16.91 | −0.097 | 289 | −8.70 | −0.030 |
|
||||
| removed, grade B | 210 | −11.53 | −0.055 | 408 | −25.69 | −0.063 |
|
||||
| removed, grade A | 46 | +1.28 | +0.028 | 164 | −1.12 | −0.007 |
|
||||
| removed, grade A+ | 14 | +4.26 | +0.304 | 26 | +1.81 | +0.069 |
|
||||
| removed, grade C | 11 | −3.34 | −0.304 | 20 | −5.80 | −0.290 |
|
||||
| kept (the new book) | 824 | +205.12 | +0.249 | 1473 | +223.33 | +0.152 |
|
||||
| kept BUY | 763 | +194.20 | +0.255 | 1302 | +222.50 | +0.171 |
|
||||
| kept SELL | 61 | +10.91 | +0.179 | 171 | +0.83 | +0.005 |
|
||||
|
||||
Reading: the removed trades are close to break-even after costs (−0.03 to −0.05R each) while the
|
||||
kept trades earn +0.15 to +0.25R each. The veto does not find big losers; it drops about a quarter
|
||||
of the trades, the ones with no edge, and with them the long flat-to-down stretches. The two
|
||||
halves of the veto are carried by different windows: the SELL half by the rising 3-year window,
|
||||
the BUY half by the falling years of the long window. Only the symmetric rule holds on both.
|
||||
|
||||
Share of trades that reach +1R before −1R (same entries, fixed 1R target, `--fixed-rr-tp 1.0`,
|
||||
$0.65): M15 W3 58.6% → 61.4% (1105 → 824 trades), M15 LONG 55.9% → 58.2%; M5 W3 56.8% → 58.2%,
|
||||
M5 LONG 55.3% → 56.1%.
|
||||
|
||||
Checklist breakdowns, M15 W3 → with the veto (trades / R), $0.65:
|
||||
|
||||
| Slice | Control | Veto | Change in R |
|
||||
|---|---|---|---|
|
||||
| regime ranging | 140 / +46.75 | 106 / +49.23 | +2.48 |
|
||||
| regime transitioning | 264 / +47.05 | 199 / +49.47 | +2.42 |
|
||||
| regime trending_down | 165 / −4.39 | 43 / +9.71 | +14.10 |
|
||||
| regime trending_up | 536 / +106.38 | 476 / +96.70 | −9.68 |
|
||||
| volatility extreme | 508 / +103.91 | 361 / +95.86 | −8.05 |
|
||||
| volatility high | 228 / +4.00 | 135 / +18.32 | +14.32 |
|
||||
| volatility normal | 202 / +58.96 | 177 / +57.01 | −1.96 |
|
||||
| volatility low | 167 / +28.92 | 151 / +33.94 | +5.01 |
|
||||
| BUY | 869 / +201.79 | 763 / +194.20 | −7.59 |
|
||||
| SELL | 236 / −6.00 | 61 / +10.91 | +16.91 |
|
||||
| setup GENERIC | 1004 / +184.73 | 757 / +192.15 | +7.42 |
|
||||
| setup XAU_ATR | 101 / +11.07 | 67 / +12.97 | +1.90 |
|
||||
| Monday | 188 / +36.54 | 145 / +52.46 | +15.92 |
|
||||
| Tuesday | 240 / +44.89 | 186 / +41.82 | −3.07 |
|
||||
| Wednesday | 234 / +12.08 | 165 / +13.36 | +1.28 |
|
||||
| Thursday | 216 / +63.84 | 157 / +70.36 | +6.51 |
|
||||
| Friday | 214 / +33.51 | 162 / +21.04 | −12.47 |
|
||||
| Sunday evening | 13 / +4.94 | 9 / +6.08 | +1.14 |
|
||||
|
||||
By entry hour (UTC), change in R on W3 / on LONG: 03 +0.3 / +1.5; 04 −2.1 / −0.1; 05 −0.2 / +2.6;
|
||||
06 +1.9 / −1.5; 07 +2.9 / +0.9; 08 −5.3 / −0.3; 09 −6.6 / −4.0; 12 −2.9 / +2.7; 14 +11.8 / +12.9;
|
||||
15 −4.0 / +1.8; 17 −0.5 / −2.4; 18 +11.4 / +11.3; 19 +0.9 / +2.7; 20 +0.8 / +2.9; 22 +0.8 / −0.1.
|
||||
The weekday and hour changes are not stable in sign between the two windows except hours 14 and 18
|
||||
(positive in both) and hour 9 (negative in both); none of it is a reason to act.
|
||||
|
||||
### 5.7 Verdict T
|
||||
|
||||
- **M15: `both` PASSES every clause and SHIPS** (`pair_signals/xauusd.py`, M15 override 7).
|
||||
- **M5: no veto.** `both` deepens the worst losing run (10.1R → 15.2R) and loses the long window;
|
||||
`buy` passes the 3-year window and fails the long one, with no plateau. The M5 book earns
|
||||
almost all of its R in 2025–2026 and the daily trend adds nothing reliable to it.
|
||||
- **H1 / H4: no veto.** H1 loses 10R of 70R; H4 already confirms on the daily chart.
|
||||
- On the timeframes without the veto the daily trend is shown on the alert as information only.
|
||||
|
||||
What the owner gives up, as agreed: in the purely rising stretch the veto costs R. W2 first half
|
||||
(2024-09 → 2025-09) +61.83R vs +70.10R; the RISING window +63.78R vs +68.50R; W2 at $0.30
|
||||
+166.22R vs +167.53R. What it buys: the worst losing run on the 3-year window falls from 20.9R to
|
||||
12.4R, on the 7.6-year window from 64.8R to 41.5R, 2022 turns from −24.6R to +3.2R, and the three
|
||||
weeks after the test window (HOLDOUT, never seen by any tuning) lose 4.6R instead of 6.6R. 2021
|
||||
does not improve (−27.3R vs −25.6R) and 2023 is worse (+1.8R vs +11.7R): in a year that chops
|
||||
sideways the daily trend flips late and the veto cannot help.
|
||||
|
||||
### 5.8 Candidate C — wide-stop cap on M15 (post-T control)
|
||||
|
||||
Control = the factory configuration after the M15 flip (daily-trend veto on). Command per row:
|
||||
`venv/bin/python backtest/cudaBasedBacktesting.py --pair XAUUSD --primary-tf 15min --start <s>
|
||||
--end <e> --spread <0.65|0.30> [--set xau_strategy.wide_stop_cap_atr=<K>] --export-csv <out>`.
|
||||
Paired proof on this control: W3, K = 6, `gpu_backtest.py --workers 12` and the twin both give
|
||||
`f94f1429fb4c9172427ea34c2f4d92a1` (824 / +216.87R / DD 11.37).
|
||||
|
||||
| Window | Cost | K | Trades | Total R | Win rate | PF | Max DD | First half | Second half | MD5 (8) |
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
| W3 | $0.65 | off | 824 | +205.12 | 63.1% | 1.73 | 12.4 | +76.72 | +128.40 | ad3b0dbd |
|
||||
| W3 | $0.65 | 5 | 824 | +211.26 | 61.4% | 1.74 | 15.0 | +81.77 | +129.48 | 055d72a4 |
|
||||
| W3 | $0.65 | **6** | 824 | +216.87 | 62.9% | 1.78 | 11.4 | +80.67 | +136.20 | f94f1429 |
|
||||
| W3 | $0.65 | 7 | 824 | +213.15 | 63.1% | 1.76 | 11.8 | +79.08 | +134.07 | 5ea4ab4b |
|
||||
| W3 | $0.65 | 8 | 824 | +208.01 | 62.9% | 1.74 | 12.3 | +77.18 | +130.84 | 372ac298 |
|
||||
| W3 | $0.30 | off | 824 | +221.18 | 63.6% | 1.81 | 11.4 | +86.41 | +134.77 | 96a87454 |
|
||||
| W3 | $0.30 | 5 | 824 | +228.46 | 62.1% | 1.82 | 14.0 | +92.27 | +136.18 | 7453b5f7 |
|
||||
| W3 | $0.30 | **6** | 824 | +233.37 | 63.6% | 1.86 | 11.0 | +90.67 | +142.70 | bf7e4157 |
|
||||
| W3 | $0.30 | 7 | 824 | +229.37 | 63.7% | 1.84 | 11.0 | +88.88 | +140.48 | e44cb5b5 |
|
||||
| W3 | $0.30 | 8 | 824 | +224.12 | 63.5% | 1.82 | 11.3 | +86.91 | +137.22 | c214455b |
|
||||
| W2 | $0.65 | off | 597 | +155.89 | 64.3% | 1.78 | 11.4 | +61.83 | +94.06 | dfc647ee |
|
||||
| W2 | $0.65 | 5 | 597 | +156.59 | 63.3% | 1.79 | 11.4 | +62.63 | +93.96 | 5e5c0207 |
|
||||
| W2 | $0.65 | **6** | 597 | +160.79 | 64.0% | 1.81 | 11.4 | +61.31 | +99.48 | 3614c98a |
|
||||
| W2 | $0.65 | 7 | 597 | +158.70 | 64.3% | 1.79 | 11.4 | +60.19 | +98.51 | afa7eb01 |
|
||||
| W2 | $0.65 | 8 | 597 | +156.58 | 64.2% | 1.78 | 11.4 | +60.54 | +96.04 | ba29cc41 |
|
||||
| RISING | $0.65 | off | 258 | +63.78 | 64.3% | 1.80 | 9.1 | +23.97 | +39.81 | e87b6de1 |
|
||||
| RISING | $0.65 | 5 | 258 | +57.68 | 61.6% | 1.71 | 8.0 | +22.85 | +34.83 | 295731a3 |
|
||||
| RISING | $0.65 | **6** | 258 | +58.03 | 64.0% | 1.72 | 8.6 | +23.84 | +34.19 | 8dba71d7 |
|
||||
| RISING | $0.65 | 7 | 258 | +62.18 | 64.3% | 1.78 | 8.8 | +26.44 | +35.74 | c461380f |
|
||||
| RISING | $0.65 | 8 | 258 | +62.12 | 63.6% | 1.77 | 9.1 | +24.06 | +38.07 | fce21577 |
|
||||
| LONG | $0.65 | off | 1473 | +223.33 | 59.7% | 1.42 | 41.5 | | | aa5253aa |
|
||||
| LONG | $0.65 | 5 | 1473 | +204.76 | 58.4% | 1.38 | 53.1 | | | b365f28f |
|
||||
| LONG | $0.65 | **6** | 1473 | +233.56 | 59.7% | 1.44 | 47.2 | | | 4aa12918 |
|
||||
| LONG | $0.65 | 7 | 1473 | +228.83 | 59.8% | 1.43 | 46.5 | | | 6e91e0dd |
|
||||
| LONG | $0.65 | 8 | 1473 | +223.79 | 59.7% | 1.42 | 43.2 | | | 36267a43 |
|
||||
| LONG | $0.30 | off | 1473 | +257.25 | 60.8% | 1.50 | 37.2 | | | 1835b341 |
|
||||
| LONG | $0.30 | 5 | 1473 | +241.64 | 59.8% | 1.46 | 44.9 | | | 6a346020 |
|
||||
| LONG | $0.30 | **6** | 1473 | +268.63 | 60.8% | 1.52 | 41.6 | | | 526ffa4a |
|
||||
| LONG | $0.30 | 7 | 1473 | +263.16 | 60.9% | 1.51 | 42.1 | | | 3f42a60e |
|
||||
| LONG | $0.30 | 8 | 1473 | +257.84 | 60.8% | 1.50 | 38.9 | | | ffbba3e4 |
|
||||
| HOLDOUT | $0.65 | off, 6, 7, 8 | 18 | −4.62 | 50.0% | 0.50 | 4.8 | | | fa50bcd0 |
|
||||
| HOLDOUT | $0.65 | 5 | 18 | −4.62 | 50.0% | 0.50 | 4.8 | | | 3ff32a0d |
|
||||
|
||||
(W2 and RISING at $0.30 and the HOLDOUT at $0.30 are in the same direction as the $0.65 rows:
|
||||
W2 +171.35 vs +166.22 for K = 6; RISING +64.66 vs +70.24; HOLDOUT unchanged.)
|
||||
|
||||
LONG per calendar year ($0.65), total R (trades are identical: 88 / 207 / 121 / 149 / 163 / 275 /
|
||||
341 / 129):
|
||||
|
||||
| K | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| off | +14.0 | +45.1 | −27.3 | +3.2 | +1.8 | +53.5 | +92.5 | +40.6 |
|
||||
| 5 | +19.0 | +27.9 | −32.4 | −1.0 | +2.5 | +63.1 | +89.2 | +36.6 |
|
||||
| 6 | +19.5 | +46.7 | −31.8 | +1.8 | +4.7 | +59.8 | +88.1 | +44.8 |
|
||||
| 7 | +16.5 | +45.4 | −32.2 | +4.3 | +1.8 | +59.2 | +91.1 | +42.7 |
|
||||
| 8 | +14.5 | +43.9 | −29.0 | +3.4 | +2.9 | +54.4 | +92.3 | +41.4 |
|
||||
|
||||
Trades the cap touches (the trade set is identical by construction; only stops, and through them
|
||||
results, move). All of them are swing (GENERIC) setups; the gold ATR setup is never capped:
|
||||
|
||||
| Window | K | Stops changed | R of those trades: control → capped |
|
||||
|---|---|---|---|
|
||||
| W3 | 5 / 6 / 7 / 8 | 281 / 168 / 89 / 44 | +66.4 → +72.5 / +49.2 → +60.9 / +25.6 → +33.6 / +12.2 → +15.1 |
|
||||
| LONG | 5 / 6 / 7 / 8 | 597 / 350 / 170 / 83 | +97.5 → +78.9 / +56.7 → +66.9 / +37.0 → +42.5 / +12.5 → +13.0 |
|
||||
| RISING | 5 / 6 / 7 / 8 | 97 / 58 / 25 / 12 | +28.1 → +22.0 / +21.0 → +15.3 / +13.1 → +11.5 / +5.7 → +4.0 |
|
||||
| HOLDOUT | 5 / 6 / 7 / 8 | 3 / 0 / 0 / 0 | −3.03 → −3.04 |
|
||||
|
||||
**Rule C, K = 6**
|
||||
|
||||
| Clause | Result | Numbers |
|
||||
|---|---|---|
|
||||
| W3 change in R ≥ +5R | PASS | +11.75 (+216.87 vs +205.12) |
|
||||
| W3 first half ≥ control − 1R | PASS | +80.67 vs +76.72 |
|
||||
| W3 second half ≥ control − 1R | PASS | +136.20 vs +128.40 |
|
||||
| W3 PF ≥ control − 0.02 | PASS | 1.777 vs 1.734 |
|
||||
| W3 max DD ≤ control + 10% | PASS | 11.37 vs 12.39 |
|
||||
| LONG total R ≥ control | PASS | +233.56 vs +223.33 (but max DD 47.19 vs 41.54) |
|
||||
| same sign at $0.30 | PASS | +12.19 (+233.37 vs +221.18) |
|
||||
| ≥ 20 trades differ | PASS | 168 stops and results changed |
|
||||
| neighbour K = 5 not negative on W3 | PASS | +6.14 |
|
||||
| **neighbour K = 5 not negative on LONG** | **FAIL** | **−18.57** |
|
||||
| neighbour K = 7 not negative on W3 | PASS | +8.04 |
|
||||
| neighbour K = 7 not negative on LONG | PASS | +5.50 |
|
||||
|
||||
**Verdict C: FAIL. Nothing ships; `wide_stop_cap_atr` stays 0.0 (research knob only).** K = 6 is a
|
||||
narrow peak, not a plateau: one step tighter loses 18.6R over the long window (2020 alone −17R),
|
||||
one step wider keeps half the gain, two steps wider keeps none. The cap also costs R in the rising
|
||||
window at every K (−1.6R to −6.1R), deepens the long-window drawdown at every K (41.5R → 43.2R to
|
||||
53.1R) and changes nothing in the unseen three weeks. This agrees with the planning-phase screen
|
||||
of 25 stop and exit variants: the stop geometry is at a plateau, and tightening it is the one
|
||||
direction that reliably loses. No second K is tried (the rule's no-rescue clause).
|
||||
|
||||
### 5.9 What shipped, and the re-pinned books
|
||||
|
||||
Shipped: `pair_signals/xauusd.py` M15 override 7, `config.xau_strategy.daily_trend_veto = "both"`
|
||||
on M15 only. Not shipped: any veto on M5 / H1 / H4; the wide-stop cap (knob kept at 0.0).
|
||||
|
||||
Reference books after the flip, factory configuration, `--spread 0.65`, regenerated with BOTH
|
||||
scripts (`gpu_backtest.py --workers 12` and `cudaBasedBacktesting.py`), `Backend: CuPy GPU
|
||||
(NVIDIA GeForce RTX 4070 SUPER, cupy 14.0.1)`, `GPU cache fallbacks: 0`:
|
||||
|
||||
| Book | Window | Trades / R / PF / DD | MD5 (reference = twin) | |
|
||||
|---|---|---|---|---|
|
||||
| M5 W2 | 2024-09-05 → 2026-09-05 | 781 / +146.07 / 1.52 / 10.1 | `e599c8a8652f95b7fcdf5a7ef2b564f5` | unchanged |
|
||||
| M15 W2 | 2024-09-05 → 2026-09-05 | 597 / +155.89 / 1.78 / 11.4 | `dfc647ee02afd179dd9e031f344ed380` | re-pinned (was `5b65ecf6…`, 813 / +154.15 / 1.53) |
|
||||
| M15 OOS | 2024-06-01 → 2025-03-30 | 258 / +63.78 / 1.80 / 9.1 | `e87b6de12f90f3b5a5d41a953ee9ff7a` | re-pinned (was `09b8a8e7…`, 313 / +68.50 / 1.67) |
|
||||
| H1 W3 | 2023-09-05 → 2026-09-05 | 253 / +70.02 / 1.98 / 4.4 | `a44fd19b4067f46e5bd98d50cc3eff92` | unchanged |
|
||||
| H4 W3 | 2023-09-05 → 2026-09-05 | 114 / +21.7 / 1.59 | `f3587bae3c5dc3eda468ea3588b17dcb` | unchanged |
|
||||
| M15 W3 | 2023-09-05 → 2026-09-05 | 824 / +205.12 / 1.73 / 12.4 | `ad3b0dbda0bf77b659caea1c53be6a50` | was `70195fb0…`, 1105 / +195.79 / 1.49 |
|
||||
|
||||
The factory books are byte-identical to the `--set xau_strategy.daily_trend_veto=both` books of
|
||||
section 5.2, as they must be.
|
||||
|
||||
### 5.10 A fetch bug found on the way (fixed, not a signal change)
|
||||
|
||||
The first HOLDOUT and RISING runs with the daily frame failed with `OandaDataError: XAU/USD 1d:
|
||||
3 consecutive failures fetching window 2020-08-01–2020-08-01 … (Empty candle response)`. Since
|
||||
2026-09-13 `fetch_range` retries a failing page and aborts after three tries, while the Oanda
|
||||
provider raised on an EMPTY date window. A padded window that starts on a closed day (the daily
|
||||
pad is 1,400 days = exactly 200 weeks, so a window starting on a Saturday pads to a Saturday)
|
||||
begins with a page nothing traded in, and the whole fetch aborted. Fix in `providers/oanda.py`:
|
||||
a DATE-WINDOW request with no candles returns an empty frame (a `count` request, the live path,
|
||||
still raises); two Module 15 tests. Books are unaffected (every pinned window was already cached;
|
||||
the ten MD5s reproduce). New cache files fetched for this campaign: the daily frames
|
||||
`oanda_XAU_USD_1d_20201105_20260905`, `_20150303_20260807`, `_20200801_20250330`,
|
||||
`_20221105_20261001`, and the HOLDOUT window `5min` / `15min` / `1h` `_20260705_20261001` and
|
||||
`4h_20260114_20261001`. The two interior gaps the HOLDOUT fetch logged are market closures
|
||||
(Labor Day 2026-09-07, Good Friday 2026-04-02), not dropped pages.
|
||||
|
||||
### 5.11 Setup size: what the evidence supports, and the display lines that shipped
|
||||
|
||||
"Trade setup size" was tested two ways.
|
||||
|
||||
**The stop itself.** Candidate C (section 5.8) fails its rule, and the planning-phase screen of
|
||||
25 stop and exit variants found nothing better than the shipped geometry (a flat 2 × ATR stop on
|
||||
M15 turns +196R into +3R). The stops stay as they are.
|
||||
|
||||
**How much is at risk at once.** If every alert is taken, the plans pile up. Shipped books, W3,
|
||||
$0.65 (`M15` = veto on):
|
||||
|
||||
| Books taken together | Trades | Same-direction plans already open at an entry: mean | median | max | Entries with ≥ 1 open | with ≥ 3 open | Open at once while anything is open: mean | max | Share of the time something is open |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| M15 alone | 824 | 1.17 | 1 | 6 | 62% | 15% | 1.70 | 7 | 41% |
|
||||
| M5 alone | 870 | 0.69 | 0 | 6 | 40% | 7% | 1.36 | 7 | 23% |
|
||||
| M5 + M15 | 1694 | 1.70 | 1 | 12 | 66% | 26% | 1.97 | 13 | 51% |
|
||||
| M5 + M15 + H1 | 1947 | 2.75 | 2 | 15 | 78% | 43% | 2.60 | 16 | 65% |
|
||||
|
||||
The stacked entries are not worse trades (M5 + M15, by the number of same-direction plans already
|
||||
open at the entry: 0 → +0.154R per trade over 577; 1 → +0.218R over 410; 2 → +0.241R over 271;
|
||||
3–4 → +0.282R over 267; 5 or more → +0.236R over 169). So there is no evidence for skipping them,
|
||||
and the 2026-09-06 sizing campaign already showed that varying the stake by signal features does
|
||||
not pay. What the numbers do say is that "1% per alert" is in practice several percent on one move
|
||||
of gold. That is a sizing fact for the reader, so it ships as information, not as a gate:
|
||||
|
||||
- **Size line** (`exposure.py`, off until `config.json` `trade_size.risk_per_trade` is set): the
|
||||
number of lots that keeps the loss at the printed stop inside the owner's risk limit, rounded
|
||||
DOWN to the lot step. Private by default (owner chats and the CLI); the channel and the public
|
||||
dashboard get it only with `trade_size.telegram_channel` / `trade_size.dashboard`.
|
||||
- **Already-open line**: how many ALERTED plans in the same direction are still open in the
|
||||
advisory outcome model (`signal_log.open_alerted_setups`, a read-only query; the bot stamps
|
||||
`alerted_at` on a row once its alert reached a chat).
|
||||
- **Daily-trend line** on every surface (`main.daily_trend_words`): on M15 the veto has already
|
||||
removed a plan against a clear daily trend; on M5 / H1 / H4, where the veto failed its rule, the
|
||||
line is context ("Daily trend: falling — this buy goes against it"). The live wrapper stamps the
|
||||
trend on every logged scan row (`signals.daily_trend`), so the live record can answer the M5
|
||||
question again after a few months.
|
||||
|
||||
None of the three is read by a gate, the backtester or the twin.
|
||||
|
||||
### 5.12 Final verification (2026-10-01)
|
||||
|
||||
- `venv/bin/python test_all.py`: **607 passed, 0 failed** (40 modules: Module 39 daily-trend veto
|
||||
and wide-stop cap, Module 40 the display lines, Module 37 extended, two Module 15 tests for the
|
||||
empty-window fetch).
|
||||
- The five reference books regenerated with both scripts after the last code change: ten MD5s
|
||||
equal the table in section 5.9.
|
||||
- Recorder and feature export with the veto on, M15 2024-06-01 → 2025-03-30, `--export-features
|
||||
--record DIR --record-bars` on both scripts: feature CSV `732f396bb3ee6036b62750a8c755194e` on
|
||||
both; `trades` 258 × 137, `indicators` 5900 × 15, `events` 5098 × 14 and `bars` 12315 × 172
|
||||
identical; both manifests carry book MD5 `e87b6de12f90f3b5a5d41a953ee9ff7a` and differ only in
|
||||
`cli`, `created_at`, `replay_seconds`, `workers`; `replay_scorecard.py DIR --check`: all
|
||||
invariants held.
|
||||
- `agent_panel_base_rates.json` rebuilt from the re-pinned books (M15 timeframe row 597 trades,
|
||||
64.3% winners, +0.261R; was 813 / 62.2% / +0.190R).
|
||||
|
||||
### 5.13 Independent verification (2026-10-01)
|
||||
|
||||
An agent that had not done the work re-derived the change list from `git diff HEAD` and
|
||||
re-ran the books itself (24 on the twin, 9 on the reference script, all offline, 0 cache
|
||||
fallbacks). Every figure of sections 5.2 to 5.9 it was given matched to the cent, on both
|
||||
scripts where it ran both: the M15 books with the veto on and off (W3, W2, the 2024-06-01 →
|
||||
2025-03-30 window, LONG with its per-year R, the holdout), the unchanged M5 / H1 / H4 pins, the
|
||||
failed M5, H1, `buy` and `sell` variants, and the removed-trade tables (281 removed on W3, 0
|
||||
added, all 63 columns of the 824 kept trades identical). Its own implementation of the rule
|
||||
from closed daily bars predicts the removed trades exactly (281 / 281, 618 / 618, 55 / 55); the
|
||||
same rule fed the still-forming day mis-predicts 52, 129 and 14 of them, so there is no
|
||||
look-ahead. The scoring configuration is identical to HEAD on all four timeframes; the only
|
||||
decision-side difference is the M15 veto.
|
||||
|
||||
It also raised four points this report did not make clearly enough. They change no verdict;
|
||||
they are recorded so the size of the claim is not overstated.
|
||||
|
||||
1. **Clause (g) is thinner than "3 of 4" reads.** The "100-day average alone" neighbour of
|
||||
table 5.5 is an EXPONENTIAL average, the same kind as the shipped 50-day one (harness key
|
||||
`e100`). With a SIMPLE 100-day average the M15 W3 book is 781 / +188.68R / PF 1.70 /
|
||||
drawdown 12.27R: it beats the control on profit factor and drawdown like the others, but
|
||||
sits 1.2R under the 97% line (+189.92R), so with that reading the count would be 2 of 4.
|
||||
The four definitions were fixed before the runs in the harness's own form and the clause
|
||||
passes as written; the honest summary is "five alternative definitions, all better than the
|
||||
control on profit factor and drawdown, two of them 1.2R and 1.7R short on total R".
|
||||
2. **"The veto never adds a trade" is an observation, not a guarantee.** The rule itself only
|
||||
removes a plan. In a book, removing an entry also moves the 5-bar cooldown, which could
|
||||
free a later entry; that happened 0 times in every control / candidate pair compared (13).
|
||||
3. **It is a risk filter, not a better direction call.** Nothing in how direction is scored
|
||||
changed, and a vetoed bar still shows its buy or sell reading. The removed plans were close
|
||||
to break-even (−0.03R each on W3, −0.05R on LONG; 55% winners against 63% for the kept
|
||||
ones), so total R barely moves while profit factor and the losing runs improve.
|
||||
4. **The help is concentrated.** Effect of the rule by year on LONG (shipped minus off):
|
||||
2019 +4.9R, 2020 −3.7R, 2021 −1.8R, 2022 **+27.8R**, 2023 **−10.0R**, 2024 +0.1R, 2025
|
||||
+11.4R, 2026 +1.9R; total +30.8R, of which 2022 (buys against a falling daily trend) is
|
||||
nine tenths. On W3 the whole gain in R comes from sells removed in 2025, and the drawdown
|
||||
cut from 20.9R to 12.4R is one episode: 13 sells between 2023-12-01 and 2024-02-23
|
||||
(−8.5R). In a year where the daily trend flips often (2023) the rule costs. The multi-year
|
||||
windows had been looked at with the prototype before rule T was written (section 2), and
|
||||
the only period nobody had seen is four weeks long and differs by six trades.
|
||||
|
||||
Cross-checked here from the formal books (a filter on the control book reproduces the shipped
|
||||
book and the exponential neighbour exactly, and gives the simple-average figure above).
|
||||
|
||||
## 6. Summary of decisions
|
||||
|
||||
| Item | Verdict |
|
||||
|---|---|
|
||||
| Daily-trend veto, M15, both directions | **PASSED rule T on every clause, SHIPPED** (factory M15 override 7) |
|
||||
| Daily-trend veto, M15, buy-only / sell-only | FAILED (W3 R and PF / LONG drawdown and 2021–22) |
|
||||
| Daily-trend veto, M5 (both, buy-only) | FAILED (W3 drawdown; LONG R, drawdown, 2021–22; no plateau) |
|
||||
| Daily-trend veto, H1 | FAILED (W3 −9.7R); H4 not run |
|
||||
| Wide-stop cap K = 6 on M15 | FAILED rule C (neighbour K = 5 loses 18.6R on LONG); knob kept at 0.0, research-only |
|
||||
| Lot-size, already-open and daily-trend lines | SHIPPED, display only (books byte-identical) |
|
||||
| Oanda empty date window | FIXED (fetch_range no longer aborts on a closed-day page) |
|
||||
| Seven further context screens | no state nominated, nothing shipped (`context_screens_2026-10.md`) |
|
||||
| Eight outside data sources (dollar, silver, bonds, real yield, fund flows, futures and Oanda client positioning) | none adds a forecast to gold's own daily trend; broad dollar index on M5 = WATCH; nothing shipped, no feed added (`new_inputs_2026-10.md`) |
|
||||
Reference in New Issue
Block a user