Separate S/R detector tests from primary R:R policy
This commit is contained in:
@@ -137,6 +137,10 @@ SR_RESEARCH_VARIANTS = {
|
||||
"soft_zones",
|
||||
"confirmed_rounds",
|
||||
"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 []
|
||||
|
||||
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)
|
||||
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(
|
||||
highs, lows, closes, volumes, max_levels=detector_cap
|
||||
)
|
||||
@@ -281,11 +286,11 @@ def _window_setups(
|
||||
|
||||
gate_levels = _gate_eligible_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 = (
|
||||
"soft"
|
||||
if sr_variant in {"soft_zones", "confirmed_rounds", "gate_v2"}
|
||||
if detector_variant in {"soft_zones", "confirmed_rounds", "gate_v2"}
|
||||
else "sum"
|
||||
)
|
||||
|
||||
@@ -326,7 +331,7 @@ def _window_setups(
|
||||
targets = _prune_floor_pinned_targets(targets)
|
||||
primary_min_rr = (
|
||||
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))
|
||||
)
|
||||
primary = _select_primary_target(
|
||||
|
||||
@@ -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
|
||||
> 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
|
||||
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
|
||||
|
||||
@@ -51,6 +51,8 @@ def _parse_args() -> argparse.Namespace:
|
||||
choices=(
|
||||
"production_control", "rr_aligned_control", "rewrite",
|
||||
"soft_zones", "confirmed_rounds", "gate_v2",
|
||||
"rewrite_legacy_primary", "soft_zones_legacy_primary",
|
||||
"confirmed_rounds_legacy_primary", "gate_v2_legacy_primary",
|
||||
),
|
||||
default=None,
|
||||
help="Research-only S/R detector/gate arm.",
|
||||
|
||||
@@ -17,17 +17,12 @@ RUNNER = ROOT / "scripts" / "run_backtest_snapshot.py"
|
||||
COMPARE = ROOT / "scripts" / "compare_sr_variants.py"
|
||||
TRAINING_ARMS = (
|
||||
"production_control",
|
||||
"rr_aligned_control",
|
||||
"rewrite",
|
||||
"soft_zones",
|
||||
"confirmed_rounds",
|
||||
"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"
|
||||
"rewrite_legacy_primary",
|
||||
"soft_zones_legacy_primary",
|
||||
"confirmed_rounds_legacy_primary",
|
||||
"gate_v2_legacy_primary",
|
||||
)
|
||||
LOCKABLE_ARMS = TRAINING_ARMS[1:]
|
||||
|
||||
|
||||
def _add_common(parser: argparse.ArgumentParser) -> None:
|
||||
|
||||
Reference in New Issue
Block a user