xauusd M15: halve the RSI regime multiplier in every regime (M15 override 5, rule-1 validated)

Owner-approved 2026-09-09 after the pre-registered weight test
(backtest/research/weight_test_2026-09-09.md). M15-only
technical.regime_weights_override = the shipped table with rsi x 0.5
(0.5 trending family / 0.75 ranging / 0.5 transitioning), derived in the
factory and pinned literally by the Module 9 equivalence test; a Module 33
test locks that M5/H1/H4 carry no override.

Evidence, 2-year Oanda window 2024-09-05..2026-09-05 at $0.65: 793/+117.62R
PF 1.41 -> 931/+146.14R PF 1.43 (fixed halves +27.9/+0.6R vs control); OOS
2024-06-01..2025-03-30 300/+40.59R PF 1.38 -> 355/+60.67R PF 1.49; 3-year
+151.90R -> +186.61R (max DD 15.5 -> 19.3R, 2026 -4R). Parity: the factory
run with no --set flag reproduces the validated candidate books byte-for-
byte (2-yr MD5 d185f099..., OOS 6f8f24b4...). M15 canonical book re-pinned
to backtest/oanda_m15_2yr_065_20260909.csv. Docs carry a one-line note.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nc9Ninzyi18QkWezrxeBvB
This commit is contained in:
Harwinder Sekhon
2026-09-09 17:36:41 -04:00
parent f6c7635c59
commit 2ac73017b8
6 changed files with 115 additions and 7 deletions
+35 -2
View File
@@ -90,6 +90,23 @@ metric. One clause waived BY OWNER DECISION 2026-07-21: 5yr max DD is
accepted in exchange for +20% total R. M5 keeps the global 0.6 arm
(same per-TF divergence pattern as tp_floor_rr and the hour-9 block).
M15 override 5 — RSI regime multiplier x 0.5 in every regime
(validated 2026-09-09, 2-year Oanda window 2024-09-05 -> 2026-09-05 at
$0.65, pre-registered rule in backtest/research/
weight_test_2026-09-09.md): 793/+117.62R PF 1.41 DD 14.8R ->
931/+146.14R PF 1.43 DD 16.1R, fixed halves +27.9/+0.6R vs control;
OOS 2024-06-01 -> 2025-03-30 300/+40.59R PF 1.38 -> 355/+60.67R
PF 1.49; 3-year 1092/+151.90R PF 1.38 -> 1273/+186.61R PF 1.39 (max DD
15.5 -> 19.3R, all in the 2023-24 year; 2026 -4R is the one calendar
year that does not improve). Mechanism: RSI is neutral on ~73% of M15
entries and votes against the trend when it fires; halving it lets more
trend-following entries clear the score band (210 added trades +26.8R,
mostly B-grade BUYs; 72 removed -7.1R). Candidate came from the
recorded replay screen (replay_recording_2026-09-09.md); the same
screen's M5 picks (MACD-down) all FAILED the replay, and ema_trend x 2
/ divergence -> 0 on M15 failed too. Canonical M15 book re-pinned to
backtest/oanda_m15_2yr_065_20260909.csv.
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
@@ -210,8 +227,8 @@ bollinger all look mis-weighted in-book and all replay worse when
oppose vote is a load-bearing quality bar, like ROC).
"""
from typing import Optional, List
from config import PlatformConfig, Timeframe
from typing import Dict, Optional, List
from config import PlatformConfig, TechnicalConfig, Timeframe
from app_config import apply_pair_overrides
_CONFIRMATIONS = {
@@ -222,6 +239,19 @@ _CONFIRMATIONS = {
}
def _m15_regime_weights() -> Dict[str, Dict[str, float]]:
"""Shipped regime weight table with the RSI multiplier halved in
every regime — the M15-only override validated 2026-09-09 (see the
module docstring, M15 override 5). Derived from the default table so
the intent ("RSI x 0.5, everything else as shipped") stays explicit;
the Module 9 equivalence test pins the resulting numbers."""
from engine import regime_weight_table # local import: keep the factory import-light
table = regime_weight_table(TechnicalConfig()) # a fresh TechnicalConfig has no override -> the shipped table
return {regime: {name: (mult * 0.5 if name == "rsi" else mult)
for name, mult in weights.items()}
for regime, weights in table.items()}
def make_config(
primary_tf: Timeframe,
confirmation_tfs: Optional[List[Timeframe]] = None,
@@ -272,6 +302,9 @@ def make_config(
# Later trailing-stop arm on M15 only — see module docstring.
config.signals.trail_arm_r = 0.70
config.signals.trail_dist_r = 0.75
# RSI regime multiplier × 0.5 in every regime on M15 only — see
# module docstring (M15 override 5, validated 2026-09-09).
config.technical.regime_weights_override = _m15_regime_weights()
if primary_tf == Timeframe.H1:
# Block every H1 SELL — the SELL quality gate (6e in
# signal_aggregator.py) downgrades any actionable-grade short