Separate S/R detector tests from primary R:R policy

This commit is contained in:
2026-07-12 23:18:38 +02:00
parent 178abd4b2d
commit bd72fa75f9
4 changed files with 28 additions and 15 deletions
+10 -5
View File
@@ -137,6 +137,10 @@ SR_RESEARCH_VARIANTS = {
"soft_zones", "soft_zones",
"confirmed_rounds", "confirmed_rounds",
"gate_v2", "gate_v2",
"rewrite_legacy_primary",
"soft_zones_legacy_primary",
"confirmed_rounds_legacy_primary",
"gate_v2_legacy_primary",
} }
@@ -268,10 +272,11 @@ def _window_setups(
return [] return []
sr_variant = _sr_research_variant() sr_variant = _sr_research_variant()
if sr_variant in {"production_control", "rr_aligned_control"}: detector_variant = sr_variant.removesuffix("_legacy_primary")
if detector_variant in {"production_control", "rr_aligned_control"}:
detected_levels = detect_sr_levels_legacy(highs, lows, closes, volumes) detected_levels = detect_sr_levels_legacy(highs, lows, closes, volumes)
else: else:
detector_cap = 0 if sr_variant == "gate_v2" else MAX_LEVELS detector_cap = 0 if detector_variant == "gate_v2" else MAX_LEVELS
detected_levels = detect_sr_levels( detected_levels = detect_sr_levels(
highs, lows, closes, volumes, max_levels=detector_cap highs, lows, closes, volumes, max_levels=detector_cap
) )
@@ -281,11 +286,11 @@ def _window_setups(
gate_levels = _gate_eligible_levels( gate_levels = _gate_eligible_levels(
sr_levels, sr_levels,
confirmed_rounds_only=sr_variant in {"confirmed_rounds", "gate_v2"}, confirmed_rounds_only=detector_variant in {"confirmed_rounds", "gate_v2"},
) )
zone_strength_mode = ( zone_strength_mode = (
"soft" "soft"
if sr_variant in {"soft_zones", "confirmed_rounds", "gate_v2"} if detector_variant in {"soft_zones", "confirmed_rounds", "gate_v2"}
else "sum" else "sum"
) )
@@ -326,7 +331,7 @@ def _window_setups(
targets = _prune_floor_pinned_targets(targets) targets = _prune_floor_pinned_targets(targets)
primary_min_rr = ( primary_min_rr = (
1.5 1.5
if sr_variant == "production_control" if sr_variant == "production_control" or sr_variant.endswith("_legacy_primary")
else float(activation.get("min_rr", 0.0)) else float(activation.get("min_rr", 0.0))
) )
primary = _select_primary_target( primary = _select_primary_target(
+11
View File
@@ -436,6 +436,17 @@ calls `scripts/compare_sr_variants.py` to produce the paired cohort CSV and JSON
> the test period. The simulator now treats `BACKTEST_ENTRY_END` as an inclusive > the test period. The simulator now treats `BACKTEST_ENTRY_END` as an inclusive
> entry bound and truncates the calendar after the final position can resolve. > entry bound and truncates the calendar after the final position can resolve.
The isolated `rr_aligned_control` validation also failed (Sharpe 2.78 to 1.32,
CAGR 73.3% to 33.1%, drawdown 11.7% to 18.4%). The live 1.5 primary-selection
behavior is therefore frozen: although it predates the 2.0 activation gate, it
acts as a useful selectivity mechanism. The final detector matrix holds that
behavior constant and varies only detection/zone policy:
- `rewrite_legacy_primary`
- `soft_zones_legacy_primary`
- `confirmed_rounds_legacy_primary`
- `gate_v2_legacy_primary`
The post-2024 interval has informed earlier research, so this is validation rather The post-2024 interval has informed earlier research, so this is validation rather
than a pristine holdout; do not sweep variants on it. No deployment follows than a pristine holdout; do not sweep variants on it. No deployment follows
automatically. A lower validation Sharpe or higher drawdown remains a no-ship automatically. A lower validation Sharpe or higher drawdown remains a no-ship
+2
View File
@@ -51,6 +51,8 @@ def _parse_args() -> argparse.Namespace:
choices=( choices=(
"production_control", "rr_aligned_control", "rewrite", "production_control", "rr_aligned_control", "rewrite",
"soft_zones", "confirmed_rounds", "gate_v2", "soft_zones", "confirmed_rounds", "gate_v2",
"rewrite_legacy_primary", "soft_zones_legacy_primary",
"confirmed_rounds_legacy_primary", "gate_v2_legacy_primary",
), ),
default=None, default=None,
help="Research-only S/R detector/gate arm.", help="Research-only S/R detector/gate arm.",
+5 -10
View File
@@ -17,17 +17,12 @@ RUNNER = ROOT / "scripts" / "run_backtest_snapshot.py"
COMPARE = ROOT / "scripts" / "compare_sr_variants.py" COMPARE = ROOT / "scripts" / "compare_sr_variants.py"
TRAINING_ARMS = ( TRAINING_ARMS = (
"production_control", "production_control",
"rr_aligned_control", "rewrite_legacy_primary",
"rewrite", "soft_zones_legacy_primary",
"soft_zones", "confirmed_rounds_legacy_primary",
"confirmed_rounds", "gate_v2_legacy_primary",
"gate_v2",
)
# confirmed_rounds failed the post-2024 validation decisively and must not be
# selected again merely because a corrected training curve looks attractive.
LOCKABLE_ARMS = tuple(
arm for arm in TRAINING_ARMS[1:] if arm != "confirmed_rounds"
) )
LOCKABLE_ARMS = TRAINING_ARMS[1:]
def _add_common(parser: argparse.ArgumentParser) -> None: def _add_common(parser: argparse.ArgumentParser) -> None: