Prune unused sleeve presets and trim web preset lists

main
I Luk Kim 4 months ago
parent e415743444
commit 4b1d9afde7

@ -693,7 +693,7 @@ def main() -> None:
p.add_argument("--idle-alpha", default=None, metavar="PRESET",
help="Apply idle alpha sleeve preset (e.g. micro_event_alpha). Overrides config.")
p.add_argument("--form4-sleeve", default=None, metavar="PRESET",
help="Apply Form 4 sleeve preset (e.g. reserve_form4_cluster_patient). Overrides config.")
help="Apply Form 4 sleeve preset (e.g. reserve_form4_cluster_plus_fresh_same_day). Overrides config.")
p.add_argument("--ownership-sleeve", default=None, metavar="PRESET",
help="Apply 13D/13G ownership sleeve preset (e.g. ownership_13d_raise_reserve_plus_strict). Overrides config.")
p.add_argument("--risk-off-sleeve", default=None, metavar="PRESET",

@ -113,6 +113,23 @@ def _log_dir() -> Path:
return get_runs_dir() / ".backtest_tasks"
def _snapshot_meta(snapshot_id: str) -> dict[str, Any]:
"""Read coverage_end_date and last_refresh_utc from the snapshot manifest."""
try:
from libs.backtest.snapshots import resolve_snapshot
resolution = resolve_snapshot(snapshot_id)
snap_path = Path("data/parquet") / resolution.canonical_snapshot_id / "manifest.json"
if snap_path.exists():
m = json.loads(snap_path.read_text())
return {
"snapshot_coverage_end_date": m.get("coverage_end_date"),
"snapshot_last_refresh_utc": m.get("last_refresh_utc"),
}
except Exception:
pass
return {"snapshot_coverage_end_date": None, "snapshot_last_refresh_utc": None}
def _result_summary_from_run_id(run_id: str) -> dict[str, Any] | None:
"""Load result_summary from a CLI run's metrics_summary.json."""
try:
@ -125,6 +142,15 @@ def _result_summary_from_run_id(run_id: str) -> dict[str, Any] | None:
# MetricsBundle stores win_rate as fraction 0-1; convert to percentage
if win_rate is not None:
win_rate = float(win_rate) * 100
# Read snapshot coverage info from the run manifest
snap_meta: dict[str, Any] = {"snapshot_coverage_end_date": None, "snapshot_last_refresh_utc": None}
run_manifest_path = runs_dir / run_id / "manifest.json"
if run_manifest_path.exists():
snap_id = json.loads(run_manifest_path.read_text()).get("dataset_snapshot_id")
if snap_id:
snap_meta = _snapshot_meta(snap_id)
return {
"return_pct": m.get("total_return_pct"),
"simple_return_pct": m.get("simple_return_pct"),
@ -132,6 +158,7 @@ def _result_summary_from_run_id(run_id: str) -> dict[str, Any] | None:
"sharpe": m.get("sharpe_ratio"),
"win_rate": win_rate,
"trade_count": m.get("trade_count"),
**snap_meta,
}
except Exception:
return None
@ -296,6 +323,8 @@ def _load_tasks_from_disk() -> list[tuple[str, int]]:
"sharpe": s.get("sharpe"),
"win_rate": s.get("win_rate"),
"trade_count": s.get("trade_count"),
"snapshot_coverage_end_date": result.get("snapshot_coverage_end_date"),
"snapshot_last_refresh_utc": result.get("snapshot_last_refresh_utc"),
}
else:
data["status"] = "failed"
@ -859,6 +888,8 @@ def _watch_direct_process(task_id: str, proc: subprocess.Popen[bytes]) -> None:
"sharpe": s.get("sharpe"),
"win_rate": s.get("win_rate"),
"trade_count": s.get("trade_count"),
"snapshot_coverage_end_date": result.get("snapshot_coverage_end_date"),
"snapshot_last_refresh_utc": result.get("snapshot_last_refresh_utc"),
}
else:
task["status"] = "failed"
@ -1039,6 +1070,8 @@ def list_tasks() -> dict[str, Any]:
"sharpe": s.get("sharpe"),
"win_rate": s.get("win_rate"),
"trade_count": s.get("trade_count"),
"snapshot_coverage_end_date": result.get("snapshot_coverage_end_date"),
"snapshot_last_refresh_utc": result.get("snapshot_last_refresh_utc"),
}
if summary:
task["result_summary"] = summary
@ -1057,6 +1090,21 @@ def get_task(task_id: str) -> dict[str, Any]:
task = _tasks.get(task_id)
if task is None:
raise HTTPException(status_code=404, detail=f"Task not found: {task_id}")
# Augment snapshot info on-the-fly if missing (handles old tasks stored without it)
rs = task.get("result_summary")
if rs is not None and rs.get("snapshot_coverage_end_date") is None:
exp_name = task.get("experiment_name")
if exp_name:
try:
config_path = get_configs_dir() / f"{exp_name}.json"
if config_path.exists():
exp_cfg = json.loads(config_path.read_text())
snap_id = exp_cfg.get("canonical_snapshot_id") or exp_cfg.get("dataset_snapshot_id")
if snap_id:
task = dict(task)
task["result_summary"] = dict(rs, **_snapshot_meta(snap_id))
except Exception:
pass
return task
@ -1247,9 +1295,6 @@ def get_parking_presets() -> dict[str, Any]:
"qqqm_low_dd_tqqq_active_v2_gld",
],
"TQQQ Shock Brake": [
"qqqm_low_dd_tqqq_active_v2_gld_brake",
"qqqm_low_dd_tqqq_active_v2_gld_brake_blend",
"qqqm_low_dd_tqqq_active_v2_gld_brake_dwell",
"qqqm_low_dd_tqqq_active_v2_gld_brake_v2",
],
}
@ -1266,26 +1311,49 @@ def get_parking_presets() -> dict[str, Any]:
@router.get("/idle-alpha-presets")
def get_idle_alpha_presets() -> dict[str, Any]:
"""Return named idle-alpha sleeve presets."""
groups = {"Residual Event Sleeve": list(IDLE_ALPHA_SLEEVE_PRESETS.keys())}
return {"presets": list(IDLE_ALPHA_SLEEVE_PRESETS.keys()), "groups": groups}
curated = [
"micro_event_alpha",
"micro_event_alpha_plus_event_plus",
]
presets = [name for name in curated if name in IDLE_ALPHA_SLEEVE_PRESETS]
groups = {"Residual Event Sleeve": presets}
return {"presets": presets, "groups": groups}
@router.get("/form4-capture-presets")
def get_form4_capture_presets() -> dict[str, Any]:
"""Return named Form 4 residual-cash sleeve presets."""
groups = {"Residual Insider Sleeve": list(FORM4_CAPTURE_SLEEVE_PRESETS.keys())}
return {"presets": list(FORM4_CAPTURE_SLEEVE_PRESETS.keys()), "groups": groups}
curated = [
"reserve_form4_cluster",
"reserve_form4_cluster_plus",
"reserve_form4_cluster_plus_fresh",
"reserve_form4_cluster_plus_fresh_same_day",
]
presets = [name for name in curated if name in FORM4_CAPTURE_SLEEVE_PRESETS]
groups = {"Residual Insider Sleeve": presets}
return {"presets": presets, "groups": groups}
@router.get("/ownership-capture-presets")
def get_ownership_capture_presets() -> dict[str, Any]:
"""Return named 13D/13G residual-cash sleeve presets."""
groups = {"Residual Ownership Sleeve": list(OWNERSHIP_CAPTURE_SLEEVE_PRESETS.keys())}
return {"presets": list(OWNERSHIP_CAPTURE_SLEEVE_PRESETS.keys()), "groups": groups}
curated = [
"ownership_13d_raise_reserve_plus_strict",
"ownership_13d_raise_reserve_ultra_balanced_purpose_plus_cooldown90_r95",
]
presets = [name for name in curated if name in OWNERSHIP_CAPTURE_SLEEVE_PRESETS]
groups = {"Residual Ownership Sleeve": presets}
return {"presets": presets, "groups": groups}
@router.get("/risk-off-alpha-presets")
def get_risk_off_alpha_presets() -> dict[str, Any]:
"""Return named risk-off alpha sleeve presets."""
groups = {"Risk-Off Alpha Sleeve": list(RISK_OFF_ALPHA_SLEEVE_PRESETS.keys())}
return {"presets": list(RISK_OFF_ALPHA_SLEEVE_PRESETS.keys()), "groups": groups}
curated = [
"risk_off_alpha_gld_crisis65_balanced_refined",
"risk_off_alpha_gld_crisis60",
"risk_off_alpha_gld_crisis65_heavy",
]
presets = [name for name in curated if name in RISK_OFF_ALPHA_SLEEVE_PRESETS]
groups = {"Risk-Off Alpha Sleeve": presets}
return {"presets": presets, "groups": groups}

@ -728,110 +728,6 @@ PARKING_PRESETS: dict[str, dict] = {
"cash_parking_defensive_relay_risk_score_max": 100.0,
"cash_parking_defensive_momentum_min": 0.05,
},
# ── TQQQ Overlay Shock Brake / Dwell Cap / Blend variants ───────────────
"qqqm_low_dd_tqqq_active_v2_gld_brake": {
"cash_parking_enabled": True,
"cash_parking_symbol": "qqqm",
"cash_parking_gate_mode": "volatility",
"cash_parking_gate_vol_lookback": 20,
"cash_parking_gate_vol_threshold": 0.35,
"cash_parking_temperature_threshold": 1.2,
"cash_parking_entropy_lookback": 20,
"cash_parking_entropy_threshold": 1.45,
"cash_parking_require_trend": True,
"cash_parking_trend_mode": "momentum",
"cash_parking_trend_sma_period": 20,
"cash_parking_trend_reentry_pct": 0.001,
"cash_parking_autocorr_threshold": 0.0,
"cash_parking_topup_max_peak_drawdown_pct": 0.02,
"cash_parking_reserve_pct": 0.0,
"cash_parking_low_vol_overlay_symbol": "tqqq",
"cash_parking_low_vol_overlay_vol_threshold": 0.22,
"cash_parking_low_vol_overlay_temperature_max": 1.05,
"cash_parking_low_vol_overlay_entropy_max": 1.45,
"cash_parking_defensive_symbol": "gld",
"cash_parking_defensive_relay_enabled": True,
"cash_parking_defensive_relay_trigger_mode": "always",
"cash_parking_defensive_relay_risk_score_max": 100.0,
"cash_parking_defensive_momentum_min": 0.05,
# Shock brake
"cash_parking_overlay_shock_brake_enabled": True,
"cash_parking_overlay_shock_brake_rv_ratio": 1.35,
"cash_parking_overlay_shock_brake_dd5_pct": 0.0225,
"cash_parking_overlay_shock_brake_sma_cross": True,
"cash_parking_overlay_shock_brake_cooldown_days": 2,
},
"qqqm_low_dd_tqqq_active_v2_gld_brake_blend": {
"cash_parking_enabled": True,
"cash_parking_symbol": "qqqm",
"cash_parking_gate_mode": "volatility",
"cash_parking_gate_vol_lookback": 20,
"cash_parking_gate_vol_threshold": 0.35,
"cash_parking_temperature_threshold": 1.2,
"cash_parking_entropy_lookback": 20,
"cash_parking_entropy_threshold": 1.45,
"cash_parking_require_trend": True,
"cash_parking_trend_mode": "momentum",
"cash_parking_trend_sma_period": 20,
"cash_parking_trend_reentry_pct": 0.001,
"cash_parking_autocorr_threshold": 0.0,
"cash_parking_topup_max_peak_drawdown_pct": 0.02,
"cash_parking_reserve_pct": 0.0,
"cash_parking_low_vol_overlay_symbol": "tqqq",
"cash_parking_low_vol_overlay_vol_threshold": 0.22,
"cash_parking_low_vol_overlay_temperature_max": 1.05,
"cash_parking_low_vol_overlay_entropy_max": 1.45,
"cash_parking_defensive_symbol": "gld",
"cash_parking_defensive_relay_enabled": True,
"cash_parking_defensive_relay_trigger_mode": "always",
"cash_parking_defensive_relay_risk_score_max": 100.0,
"cash_parking_defensive_momentum_min": 0.05,
# Shock brake
"cash_parking_overlay_shock_brake_enabled": True,
"cash_parking_overlay_shock_brake_rv_ratio": 1.35,
"cash_parking_overlay_shock_brake_dd5_pct": 0.0225,
"cash_parking_overlay_shock_brake_sma_cross": True,
"cash_parking_overlay_shock_brake_cooldown_days": 2,
# Continuous leverage blend
"cash_parking_overlay_blend_enabled": True,
"cash_parking_overlay_blend_target_vol": 0.30,
"cash_parking_overlay_blend_max_leverage": 2.3,
},
"qqqm_low_dd_tqqq_active_v2_gld_brake_dwell": {
"cash_parking_enabled": True,
"cash_parking_symbol": "qqqm",
"cash_parking_gate_mode": "volatility",
"cash_parking_gate_vol_lookback": 20,
"cash_parking_gate_vol_threshold": 0.35,
"cash_parking_temperature_threshold": 1.2,
"cash_parking_entropy_lookback": 20,
"cash_parking_entropy_threshold": 1.45,
"cash_parking_require_trend": True,
"cash_parking_trend_mode": "momentum",
"cash_parking_trend_sma_period": 20,
"cash_parking_trend_reentry_pct": 0.001,
"cash_parking_autocorr_threshold": 0.0,
"cash_parking_topup_max_peak_drawdown_pct": 0.02,
"cash_parking_reserve_pct": 0.0,
"cash_parking_low_vol_overlay_symbol": "tqqq",
"cash_parking_low_vol_overlay_vol_threshold": 0.22,
"cash_parking_low_vol_overlay_temperature_max": 1.05,
"cash_parking_low_vol_overlay_entropy_max": 1.45,
"cash_parking_defensive_symbol": "gld",
"cash_parking_defensive_relay_enabled": True,
"cash_parking_defensive_relay_trigger_mode": "always",
"cash_parking_defensive_relay_risk_score_max": 100.0,
"cash_parking_defensive_momentum_min": 0.05,
# Shock brake
"cash_parking_overlay_shock_brake_enabled": True,
"cash_parking_overlay_shock_brake_rv_ratio": 1.35,
"cash_parking_overlay_shock_brake_dd5_pct": 0.0225,
"cash_parking_overlay_shock_brake_sma_cross": True,
"cash_parking_overlay_shock_brake_cooldown_days": 2,
# Dwell cap
"cash_parking_overlay_max_hold_days": 5,
"cash_parking_overlay_revalidation_days": 3,
},
"qqqm_low_dd_tqqq_active_v2_gld_brake_v2": {
"cash_parking_enabled": True,
"cash_parking_symbol": "qqqm",
@ -857,17 +753,21 @@ PARKING_PRESETS: dict[str, dict] = {
"cash_parking_defensive_relay_trigger_mode": "always",
"cash_parking_defensive_relay_risk_score_max": 100.0,
"cash_parking_defensive_momentum_min": 0.05,
# Shock brake (base)
# Shock brake: Signal 4 (near-SMA buffer) ONLY — Signals 1-3 disabled
# Signals 1-3 (rv_ratio, dd5_pct, sma_cross) over-trigger 2023-2024, compounding equity loss
# Signal 4 correctly fires Dec 11 (SmaGap=0.37%, vol5/vol20=0.284>0.25) without false alarms
"cash_parking_overlay_shock_brake_enabled": True,
"cash_parking_overlay_shock_brake_rv_ratio": 1.35,
"cash_parking_overlay_shock_brake_dd5_pct": 0.0225,
"cash_parking_overlay_shock_brake_sma_cross": True,
"cash_parking_overlay_shock_brake_rv_ratio": 99.0, # Signal 1: effectively disabled
"cash_parking_overlay_shock_brake_dd5_pct": 1.0, # Signal 3: effectively disabled
"cash_parking_overlay_shock_brake_sma_cross": False, # Signal 2: disabled
"cash_parking_overlay_shock_brake_cooldown_days": 2,
# Near-SMA buffer: exit TQQQ when QQQ within 0.5% above SMA10 (pre-emptive)
# Signal 4: exit TQQQ when QQQ within 0.5% above SMA10 + vol5/vol20 ∈ (0.25, 0.45)
# Upper bound 0.45 filters out high-vol days (regular gate handles those) and false alarms.
# Targets "barely elevated" pre-crash vol signature; fires Dec 11 (0.284) not May 21 (0.529).
# Same-day re-buy is skipped after brake fires; next day gate decides (SGOV on crash days)
"cash_parking_overlay_shock_brake_sma_buffer": 0.005,
# Tighter dwell cap: force TQQQ exit after 4 days
"cash_parking_overlay_max_hold_days": 4,
"cash_parking_overlay_revalidation_days": 3,
"cash_parking_overlay_shock_brake_rv_ratio_upper": 0.45,
# Dwell cap: disabled (max_hold=4 caused Sep-26 bottom-exit; default 0 = unlimited)
},
# ── Bearish Parking (SH inverse ETF) ────────────────────────────────────
# Two-stage: normal→QQQ, mild stress→SGOV, deep stress→SH
@ -1220,46 +1120,17 @@ FORM4_CAPTURE_SLEEVE_PRESETS: dict[str, dict[str, Any]] = {
"max_positions": 6,
"max_new_per_day": 2,
},
"reserve_form4_cluster_plus_fresh_balanced": {
"enabled": True,
"pit_events_path": "data/reference/form4_daily_events_pit.parquet",
"reserve_pct": 0.05,
"min_owner_count": 2,
"min_total_value": 5_000_000.0,
"min_purchase_pct": 0.0,
"min_transaction_count": 2,
"max_lag_days": 2,
"max_min_lag_days": 1,
"hold_days": 20,
"max_positions": 6,
"max_new_per_day": 2,
},
"reserve_form4_cluster_plus_fresh_strict": {
"reserve_form4_cluster_plus_fresh_same_day": {
"enabled": True,
"pit_events_path": "data/reference/form4_daily_events_pit.parquet",
"reserve_pct": 0.06,
"min_owner_count": 2,
"min_total_value": 5_000_000.0,
"min_purchase_pct": 0.0,
"min_transaction_count": 3,
"min_transaction_count": 2,
"max_lag_days": 2,
"max_min_lag_days": 1,
"hold_days": 20,
"max_positions": 6,
"max_new_per_day": 2,
},
"reserve_form4_cluster_patient": {
"enabled": True,
"pit_events_path": "data/reference/form4_daily_events_pit.parquet",
"reserve_pct": 0.125,
"min_owner_count": 2,
"min_total_value": 5_000_000.0,
"min_purchase_pct": 0.0,
"max_lag_days": None,
"disable_day1_early_failure": True,
"no_progress_days_override": 3,
"no_progress_r_override": 0.15,
"no_progress_fraction_override": 1.0,
"max_transaction_span_days": 0,
"hold_days": 20,
"max_positions": 6,
"max_new_per_day": 2,
@ -1307,30 +1178,6 @@ OWNERSHIP_CAPTURE_SLEEVE_PRESETS: dict[str, dict[str, Any]] = {
"min_cash_ratio_for_overlay": 0.25,
"max_idle_deploy_pct": 0.0,
},
"ownership_13d_raise_reserve_ultra_balanced_purpose_plus_cooldown90_saturation4_fullidle": {
"enabled": True,
"pit_events_path": "data/reference/ownership_13d13g_events_pit.parquet",
"reserve_pct": 0.49,
"form_groups": ["13D"],
"min_percent_owned": 5.0,
"min_percent_delta_points": 2.0,
"exclude_housekeeping_purpose": True,
"exclude_structural_exchange_purpose": True,
"require_amendment": True,
"require_initial": False,
"require_activist": False,
"require_13g_to_13d_transition": False,
"symbol_cooldown_days_after_loss": 90,
"symbol_max_entries_in_lookback": 4,
"symbol_entry_lookback_days": 540,
"hold_days": 30,
"min_avg_dollar_volume": 10_000_000.0,
"max_positions": 6,
"max_new_per_day": 2,
"min_cash_ratio_for_overlay": 0.25,
"max_idle_deploy_pct": 0.0,
"extra_idle_deploy_pct_above_reserve": 1.0,
},
}
RISK_OFF_ALPHA_SLEEVE_PRESETS: dict[str, dict[str, Any]] = {
@ -1546,6 +1393,7 @@ class RiskConfig(BaseModel):
cash_parking_overlay_shock_brake_sma_cross: bool = True # QQQ < SMA10 AND smh_mom_5 < 0 → brake
cash_parking_overlay_shock_brake_cooldown_days: int = 2 # days before TQQQ re-entry
cash_parking_overlay_shock_brake_sma_buffer: float = 0.0 # 0=disabled; 0.005=exit when QQQ within 0.5% ABOVE SMA10 (pre-emptive)
cash_parking_overlay_shock_brake_rv_ratio_upper: float = 0.0 # Signal 4 upper vol bound; 0=disabled; 0.45=only fire when vol5/vol20 in (0.25,0.45)
# TQQQ overlay dwell cap: limit consecutive hold days and periodic revalidation
cash_parking_overlay_max_hold_days: int = 0 # max overlay days (0=unlimited)
cash_parking_overlay_revalidation_days: int = 0 # re-check every N days (0=disabled)
@ -1940,11 +1788,15 @@ class Form4CaptureConfig(BaseModel):
reserve_pct: float = 0.0
min_owner_count: int = 2
min_transaction_count: int = 1
min_c_suite_count: int = 0
min_cfo_count: int = 0
min_role_weight_score: float = 0.0
min_total_value: float = 5_000_000.0
min_purchase_pct: float = 0.0
min_event_day_count: int = 1
max_lag_days: int | None = None
max_min_lag_days: int | None = None
max_transaction_span_days: int | None = None
require_officer_or_director: bool = False
disable_day1_early_failure: bool = False
no_progress_days_override: int | None = None

Loading…
Cancel
Save