5 sweep YAMLs updated to reference the new checkpoint filename:
- config/ml/sweep_smoke.yaml: trunk_best_h6000.bin → trunk_best_h1000.bin
- config/ml/sweep_perhoriz_diag.yaml: same
- config/ml/sweep_threshold_tuning.yaml: same
- config/ml/sweep_deployability.yaml: same
- config/ml/sweep_smoke_perhoriz_cfc.yaml: same + 3 comment updates
(WIN-gate criteria, header doc, best-checkpoint annotation)
scripts/generate_sweep_variants.py:61 updated atomically — without this
the next regeneration of sweep_deployability.yaml would silently
re-introduce trunk_best_h6000.bin.
Argo workflow templates (alpha-perception, alpha-cv, lob-backtest-sweep)
did NOT need text changes — they're already horizon-agnostic:
- They forward CLI flags via {{workflow.parameters.*}} to binaries
- Don't grep alpha_train_summary.json inline
- Don't reference per-horizon field names
- early-stop-metric default is "mean_auc" (horizon-agnostic)
Intentionally left:
- alpha-cv-template.yaml stacker-horizon: "6000" (unrelated TFT lookback)
- alpha-cv-template.yaml horizon: "1200" (DQN execution horizon in bars)
- lob-backtest-sweep-template.yaml ci-training-h100 (GPU pool name)
NOTE: kubectl apply of workflow templates is deferred to Task 10 (push
+ dispatch). Verified all 5 sweep YAMLs parse with python3 yaml.safe_load.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
76 lines
3.4 KiB
Python
Executable File
76 lines
3.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""P6 helper: emit the 140 sim_variants for the deployability sweep.
|
||
|
||
Cross-product: 7 costs × 4 latencies × 5 thresholds = 140 variants.
|
||
|
||
Threshold values are placeholders — the actual values come from
|
||
config/ml/v2_prod_thresholds.json after the threshold-tuning step.
|
||
Re-run this script post-tuning to refresh sweep_deployability.yaml with
|
||
calibrated thresholds.
|
||
|
||
Usage:
|
||
scripts/generate_sweep_variants.py > config/ml/sweep_deployability.yaml
|
||
"""
|
||
from __future__ import annotations
|
||
import json, sys
|
||
from pathlib import Path
|
||
|
||
# 7 costs (price-units / lot / side). 0.125 = 1 tick (ES), 0.0625 = 0.5 tick (best-case),
|
||
# stepping through realistic retail (0.25, 0.375 = 2-3 ticks), and worst-case (1.0 = 8 ticks).
|
||
COSTS = [0.0625, 0.125, 0.1875, 0.25, 0.375, 0.5, 1.0]
|
||
|
||
# 4 latencies (ns). 100M = 100ms (best), 200M = realistic anchor, 300M = degraded,
|
||
# 400M = stress anchor.
|
||
LATENCIES_NS = [100_000_000, 200_000_000, 300_000_000, 400_000_000]
|
||
|
||
# 5 thresholds — REPLACE THESE WITH THE OUTPUT OF THE THRESHOLD-TUNING PASS.
|
||
# Read from config/ml/v2_prod_thresholds.json if it exists; otherwise use
|
||
# the canonical p60-p95 placeholder (5 steps spanning the range).
|
||
THRESH_JSON = Path(__file__).resolve().parent.parent / "config" / "ml" / "v2_prod_thresholds.json"
|
||
if THRESH_JSON.exists():
|
||
blob = json.loads(THRESH_JSON.read_text())
|
||
THRESHOLDS = blob["thresholds_absolute"] # e.g. {"p60": 0.42, "p70": 0.55, ...}
|
||
THRESHOLD_NAMES = list(THRESHOLDS.keys())
|
||
THRESHOLD_VALUES = list(THRESHOLDS.values())
|
||
assert len(THRESHOLD_VALUES) == 5, f"expected 5 thresholds; got {len(THRESHOLD_VALUES)}"
|
||
else:
|
||
print("# WARNING: v2_prod_thresholds.json missing — using p60-p95 placeholder thresholds",
|
||
file=sys.stderr)
|
||
THRESHOLD_NAMES = ["p60", "p70", "p80", "p90", "p95"]
|
||
THRESHOLD_VALUES = [0.40, 0.55, 0.70, 0.85, 0.95]
|
||
|
||
assert len(COSTS) == 7
|
||
assert len(LATENCIES_NS) == 4
|
||
|
||
print("# P6 deployability sweep — 4 windows × 140 sim_variants (7 cost × 4 latency × 5 threshold).")
|
||
print("# Generated by scripts/generate_sweep_variants.py — do NOT hand-edit.")
|
||
print("# Re-run after threshold-tuning to refresh threshold absolute values.")
|
||
print()
|
||
print("base:")
|
||
print(" data_template: /mnt/training-data/futures-baseline-mbp10/ES.FUT/ES.FUT_{window}.dbn.zst")
|
||
print(" predecoded_dir: /feature-cache/predecoded")
|
||
print(" n_parallel: 1 # batched flow overrides with variants.len()=140")
|
||
print(" decision_stride: 4")
|
||
print(" latency_ns: 200000000 # default (overridden per variant)")
|
||
print(" target_annual_vol_units: 50.0")
|
||
print(" annualisation_factor: 825.0")
|
||
print(" max_lots: 5")
|
||
print(" max_events: 0")
|
||
print(" seed: 12648430")
|
||
print(" # __SHA__ replaced by submitter with post-trunk-grows training short-SHA.")
|
||
print(" checkpoint: /feature-cache/alpha-perception-runs/__SHA__/trunk_best_h1000.bin")
|
||
print(" sim_variants:")
|
||
|
||
for ci, cost in enumerate(COSTS):
|
||
for li, latency in enumerate(LATENCIES_NS):
|
||
for ti, (tname, tval) in enumerate(zip(THRESHOLD_NAMES, THRESHOLD_VALUES)):
|
||
name = f"c{ci}_l{li}_{tname}"
|
||
print(f" - {{ name: {name}, threshold: {tval}, cost_per_lot_per_side: {cost}, latency_ns: {latency} }}")
|
||
|
||
print()
|
||
print("cells:")
|
||
print(" - { name: W1, window: 2025-Q2 }")
|
||
print(" - { name: W2, window: 2025-Q3 }")
|
||
print(" - { name: W3, window: 2025-Q4 }")
|
||
print(" - { name: W4, window: 2026-Q1 }")
|