Fix post-cluster neutral strength ablation
This commit is contained in:
@@ -156,6 +156,28 @@ def _sr_research_variant() -> str:
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def _apply_zone_strength_variant(zone_levels: list[Any], sr_variant: str) -> list[Any]:
|
||||||
|
"""Apply post-cluster research controls without changing zone geometry."""
|
||||||
|
if sr_variant == "legacy_geometry_neutral":
|
||||||
|
# Neutrality must be enforced after the shared zone cluster: its legacy
|
||||||
|
# sum mode can otherwise turn two 50-strength constituents back into a
|
||||||
|
# 100-strength target and silently invalidate the ablation.
|
||||||
|
for level in zone_levels:
|
||||||
|
level.strength = 50
|
||||||
|
return zone_levels
|
||||||
|
|
||||||
|
|
||||||
|
def _apply_zone_strength_variant(zone_levels: list[Any], sr_variant: str) -> list[Any]:
|
||||||
|
"""Apply post-cluster research controls without changing zone geometry."""
|
||||||
|
if sr_variant == "legacy_geometry_neutral":
|
||||||
|
# Neutrality must be enforced after the shared zone cluster: its legacy
|
||||||
|
# sum mode can otherwise turn two 50-strength constituents back into a
|
||||||
|
# 100-strength target and silently invalidate the ablation.
|
||||||
|
for level in zone_levels:
|
||||||
|
level.strength = 50
|
||||||
|
return zone_levels
|
||||||
|
|
||||||
|
|
||||||
def _backtest_entry_bounds() -> tuple[date | None, date | None]:
|
def _backtest_entry_bounds() -> tuple[date | None, date | None]:
|
||||||
"""Optional research-only entry bounds used to protect validation data."""
|
"""Optional research-only entry bounds used to protect validation data."""
|
||||||
parsed: list[date | None] = []
|
parsed: list[date | None] = []
|
||||||
@@ -328,6 +350,8 @@ def _window_setups(
|
|||||||
entry,
|
entry,
|
||||||
strength_mode=zone_strength_mode,
|
strength_mode=zone_strength_mode,
|
||||||
)
|
)
|
||||||
|
zone_levels = _apply_zone_strength_variant(zone_levels, sr_variant)
|
||||||
|
zone_levels = _apply_zone_strength_variant(zone_levels, sr_variant)
|
||||||
targets = target_generator.generate_targets(direction, entry, stop, zone_levels, atr)
|
targets = target_generator.generate_targets(direction, entry, stop, zone_levels, atr)
|
||||||
if not targets:
|
if not targets:
|
||||||
fallback_k = _atr_target_fallback_k()
|
fallback_k = _atr_target_fallback_k()
|
||||||
|
|||||||
@@ -498,6 +498,29 @@ Run on macOS:
|
|||||||
Do not validate any traffic arm yet. First establish whether geometry, pivots, or
|
Do not validate any traffic arm yet. First establish whether geometry, pivots, or
|
||||||
the range-occupancy grid reproduces production on pre-2024 training data.
|
the range-occupancy grid reproduces production on pre-2024 training data.
|
||||||
|
|
||||||
|
Initial result:
|
||||||
|
|
||||||
|
| arm | Sharpe | CAGR | MaxDD | net avg R | ex-top-5% |
|
||||||
|
|---|---:|---:|---:|---:|---:|
|
||||||
|
| production control | 1.28 | 28.8% | 21.4% | 0.230 | 0.066 |
|
||||||
|
| pivots only | 1.38 | 32.9% | 25.2% | 0.236 | 0.076 |
|
||||||
|
| traffic grid only | **1.72** | **41.8%** | **16.8%** | **0.271** | **0.136** |
|
||||||
|
|
||||||
|
The traffic grid is the first research arm to beat control simultaneously on
|
||||||
|
Sharpe, CAGR, drawdown, and robust expectancy. It retains 264 production setups,
|
||||||
|
adds 240 positive-expectancy setups, and removes 412 weaker setups. This supports
|
||||||
|
the hypothesis that the useful legacy feature is the volume-weighted range-
|
||||||
|
occupancy grid, not pivots or visually meaningful S/R.
|
||||||
|
|
||||||
|
The first geometry-neutral result is not interpretable: neutral strength was set
|
||||||
|
before the shared zone cluster, which summed multiple 50-strength constituents
|
||||||
|
back to 100. Neutrality is now enforced after clustering. Rerun only that arm:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
.venv/bin/python scripts/run_sr_v2_matrix.py traffic \
|
||||||
|
--only-arm legacy_geometry_neutral --workers 14
|
||||||
|
```
|
||||||
|
|
||||||
**Next runs, if picked back up:**
|
**Next runs, if picked back up:**
|
||||||
|
|
||||||
- A **per-name target model** for clear-air setups instead of a constant k×ATR. This
|
- A **per-name target model** for clear-air setups instead of a constant k×ATR. This
|
||||||
|
|||||||
@@ -50,6 +50,12 @@ def _args() -> argparse.Namespace:
|
|||||||
help="Isolate legacy geometry, pivots, and price-traffic grid on training data.",
|
help="Isolate legacy geometry, pivots, and price-traffic grid on training data.",
|
||||||
)
|
)
|
||||||
_add_common(traffic)
|
_add_common(traffic)
|
||||||
|
traffic.add_argument(
|
||||||
|
"--only-arm",
|
||||||
|
choices=TRAFFIC_ARMS,
|
||||||
|
default=None,
|
||||||
|
help="Rerun one hidden-feature arm without repeating the full matrix.",
|
||||||
|
)
|
||||||
validate = commands.add_parser(
|
validate = commands.add_parser(
|
||||||
"validate",
|
"validate",
|
||||||
help="Run production control and one locked arm from 2024-07-01.",
|
help="Run production control and one locked arm from 2024-07-01.",
|
||||||
@@ -135,7 +141,8 @@ def main() -> None:
|
|||||||
if args.command == "train":
|
if args.command == "train":
|
||||||
_train(args, TRAINING_ARMS, "backtest-sr-v2-train")
|
_train(args, TRAINING_ARMS, "backtest-sr-v2-train")
|
||||||
elif args.command == "traffic":
|
elif args.command == "traffic":
|
||||||
_train(args, TRAFFIC_ARMS, "backtest-sr-traffic-train")
|
arms = (args.only_arm,) if args.only_arm else TRAFFIC_ARMS
|
||||||
|
_train(args, arms, "backtest-sr-traffic-train")
|
||||||
else:
|
else:
|
||||||
_validate(args)
|
_validate(args)
|
||||||
|
|
||||||
|
|||||||
@@ -766,6 +766,15 @@ def test_sr_research_variant_is_explicit_and_validated(monkeypatch):
|
|||||||
bt._sr_research_variant()
|
bt._sr_research_variant()
|
||||||
|
|
||||||
|
|
||||||
|
def test_geometry_neutral_strength_is_enforced_after_zone_clustering():
|
||||||
|
levels = [
|
||||||
|
SimpleNamespace(strength=100),
|
||||||
|
SimpleNamespace(strength=75),
|
||||||
|
]
|
||||||
|
result = bt._apply_zone_strength_variant(levels, "legacy_geometry_neutral")
|
||||||
|
assert [level.strength for level in result] == [50, 50]
|
||||||
|
|
||||||
|
|
||||||
def test_backtest_entry_bounds_validate_dates(monkeypatch):
|
def test_backtest_entry_bounds_validate_dates(monkeypatch):
|
||||||
monkeypatch.setenv("BACKTEST_ENTRY_START", "2024-07-01")
|
monkeypatch.setenv("BACKTEST_ENTRY_START", "2024-07-01")
|
||||||
monkeypatch.setenv("BACKTEST_ENTRY_END", "2024-12-31")
|
monkeypatch.setenv("BACKTEST_ENTRY_END", "2024-12-31")
|
||||||
|
|||||||
Reference in New Issue
Block a user