Add blocker research and routing rename
This commit is contained in:
107
scripts/run_current_cash_blocked_scale_exact_sweep.py
Normal file
107
scripts/run_current_cash_blocked_scale_exact_sweep.py
Normal file
@@ -0,0 +1,107 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import multiprocessing as mp
|
||||
import sys
|
||||
from concurrent.futures import ProcessPoolExecutor, as_completed
|
||||
from dataclasses import asdict
|
||||
from pathlib import Path
|
||||
|
||||
import pandas as pd
|
||||
|
||||
PACKAGE_PARENT = Path(__file__).resolve().parents[2]
|
||||
if str(PACKAGE_PARENT) not in sys.path:
|
||||
sys.path.insert(0, str(PACKAGE_PARENT))
|
||||
|
||||
from strategy32.research.soft_router import load_component_bundle, score_candidate
|
||||
from strategy32.scripts.run_current_cash_learned_blocker import LearnedBlockerCandidate
|
||||
from strategy32.scripts.run_current_cash_learned_blocker_exact import _exact_period_worker
|
||||
from strategy32.scripts.run_current_relaxed_hybrid_experiment import WINDOWS, YEAR_PERIODS, YTD_START
|
||||
|
||||
|
||||
OUT_JSON = Path("/tmp/strategy32_current_cash_blocked_scale_exact_sweep.json")
|
||||
BASELINE_JSON = Path("/tmp/strategy32_live_combo_backtest.json")
|
||||
CACHE_PATH = "/tmp/strategy32_fixed66_bundle.pkl"
|
||||
|
||||
|
||||
def _candidate_space() -> list[LearnedBlockerCandidate]:
|
||||
scales = (0.25, 0.40, 0.50, 0.60, 0.70, 0.75, 0.80, 0.90)
|
||||
return [
|
||||
LearnedBlockerCandidate(
|
||||
block_bars=42,
|
||||
train_min_blocks=12,
|
||||
lookback_blocks=24,
|
||||
ridge_alpha=1.0,
|
||||
prediction_threshold=-0.0025,
|
||||
blocked_scale=scale,
|
||||
)
|
||||
for scale in scales
|
||||
]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
_, latest_bar = load_component_bundle(CACHE_PATH)
|
||||
period_specs: list[tuple[str, str, pd.Timestamp, pd.Timestamp]] = []
|
||||
for days, label in WINDOWS:
|
||||
period_specs.append(("window", label, latest_bar - pd.Timedelta(days=days), latest_bar))
|
||||
for label, start, end_exclusive in YEAR_PERIODS:
|
||||
period_specs.append(("year", label, start, min(latest_bar, end_exclusive - pd.Timedelta(seconds=1))))
|
||||
period_specs.append(("year", "2026_YTD", YTD_START, latest_bar))
|
||||
|
||||
ctx = mp.get_context("fork")
|
||||
results: list[dict[str, object]] = []
|
||||
candidates = _candidate_space()
|
||||
for idx, candidate in enumerate(candidates, start=1):
|
||||
print(f"[candidate] {idx}/{len(candidates)} {candidate.name}", flush=True)
|
||||
window_results: dict[str, dict[str, float]] = {}
|
||||
year_results: dict[str, dict[str, float]] = {}
|
||||
with ProcessPoolExecutor(max_workers=min(6, len(period_specs)), mp_context=ctx) as executor:
|
||||
future_map = {
|
||||
executor.submit(
|
||||
_exact_period_worker,
|
||||
CACHE_PATH,
|
||||
candidate_payload=asdict(candidate),
|
||||
kind=kind,
|
||||
label=label,
|
||||
start_text=str(start),
|
||||
end_text=str(end),
|
||||
): (kind, label)
|
||||
for kind, label, start, end in period_specs
|
||||
}
|
||||
for future in as_completed(future_map):
|
||||
kind, label, metrics = future.result()
|
||||
if kind == "window":
|
||||
window_results[label] = metrics
|
||||
else:
|
||||
year_results[label] = metrics
|
||||
|
||||
score, negative_years, mdd_violations = score_candidate(
|
||||
{label: window_results[label] for _, label in WINDOWS},
|
||||
{k: year_results[k] for k, _, _ in YEAR_PERIODS},
|
||||
)
|
||||
results.append(
|
||||
{
|
||||
"candidate": asdict(candidate),
|
||||
"name": candidate.name,
|
||||
"score": score,
|
||||
"negative_years": negative_years,
|
||||
"mdd_violations": mdd_violations,
|
||||
"windows": {label: window_results[label] for _, label in WINDOWS},
|
||||
"years": year_results,
|
||||
}
|
||||
)
|
||||
|
||||
results.sort(key=lambda item: float(item["score"]), reverse=True)
|
||||
output = {
|
||||
"analysis": "current_cash_blocked_scale_exact_sweep",
|
||||
"latest_bar": str(latest_bar),
|
||||
"results": results,
|
||||
"baseline_exact": json.loads(BASELINE_JSON.read_text(encoding="utf-8")) if BASELINE_JSON.exists() else None,
|
||||
}
|
||||
OUT_JSON.write_text(json.dumps(output, indent=2), encoding="utf-8")
|
||||
print(json.dumps(output["results"], indent=2))
|
||||
print(f"[saved] {OUT_JSON}", flush=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user