"""XAU/USD signal producer config. PlatformConfig defaults ARE the tuned XAU/USD configuration, so this factory sets the timeframes plus documented per-timeframe overrides. It must stay equivalent to the inline PlatformConfig(symbol=XAUUSD, ...) construction (plus those overrides) used by the backtester and Telegram bot (enforced by a test in test_all.py). M15 override (validated 2026-07-11, window 2025-03-30 -> 2026-05-31, $0.30 spread, trailing exits): tp_floor_rr 1.0 scores +116.6R/460 trades PF 1.83 vs +105.4R/424 PF 1.82 at the 0.5 default — better in both train/val halves and on the 2024-06 -> 2025-03 out-of-sample window (+30.3R vs +10.6R; the 1R floor lifts targets past the min-TP spread gate, roughly doubling trades there). The same knob HURTS M5 (pinned 12mo book: +131.3R/699 vs +139.9R/547, PF 1.55 vs 1.78), so it is per-timeframe, exactly as PENDING_STEPS' decision rule anticipated. M15 override 2 (validated 2026-07-11, 12mo window 2025-07-11 -> 2026-07-11 + OOS 2024-06-01 -> 2025-03-30, $0.30 spread): block the mixed "trending" regime (ADX strong but EMAs unaligned — momentum without directional structure). Those trades lost -6.8R/24 on 12mo, negative in BOTH halves; blocking scores +65.7R/499 PF 1.38 DD 10.4R vs +59.0R/521 PF 1.32 DD 12.6R baseline, better in both halves. OOS is neutral (-1.4R = the 4 such trades that existed there; no power to confirm or refute). M5 never trades this regime (its gates already exclude it), so the block is M15-only. A second candidate — blocking transitioning-regime SELLs (-4.0R/47 on 12mo) — was REJECTED: those sells made +5.7R/32 in the 2024 OOS window (bull-market artifact). M5 override (validated 2026-07-11, full-history replay 2020-03-17 -> 2026-07-11 + 12mo book, $0.30 spread): block hour 9 UTC (post-London- open whipsaw). Hour-9 entries lost -28.9R/143 over 6 years, negative in 5/7 calendar years including winning years (2022 -9.2R). Blocking: +207.1R vs +178.3R baseline on the 6-year replay, max DD 28.7R vs 35.5R, improves 5/7 years (2023 goes -13.0R -> breakeven); the tuned 12mo book is unchanged (+139.0R vs +139.3R). M15-and-up keep hour 9: it is POSITIVE there (M15 6yr +1.7R, M15 OOS +8.6R), so the block is M5-only, same per-timeframe pattern as the M15 overrides. """ from typing import Optional, List from config import PlatformConfig, Timeframe _CONFIRMATIONS = { Timeframe.M5: [Timeframe.M15, Timeframe.H1], Timeframe.M15: [Timeframe.M5, Timeframe.H1], Timeframe.H1: [Timeframe.M15, Timeframe.H4], Timeframe.H4: [Timeframe.H1, Timeframe.D1], } def make_config( primary_tf: Timeframe, confirmation_tfs: Optional[List[Timeframe]] = None, ) -> PlatformConfig: config = PlatformConfig() config.primary_timeframe = primary_tf config.confirmation_timeframes = ( confirmation_tfs or _CONFIRMATIONS.get(primary_tf, [Timeframe.M15, Timeframe.H4]) ) if primary_tf == Timeframe.M5: # Block hour 9 UTC on M5 only — see module docstring. config.xau_strategy.blocked_hours_utc = ( config.xau_strategy.blocked_hours_utc + [9] ) if primary_tf == Timeframe.M15: # 1R minimum target on M15 only — see module docstring. config.signals.tp_floor_rr = 1.0 # Block the mixed "trending" regime on M15 only — see docstring. config.xau_strategy.blocked_regimes = ["trending"] return config