#!/usr/bin/env python3 from __future__ import annotations import argparse import json from pathlib import Path ROOT = Path(__file__).resolve().parents[1] DEFAULT_IN = ROOT / "Temp" / "late_chase_attribution_v1.json" DEFAULT_OUT = ROOT / "Temp" / "anti_late_chase_v6.json" def _load(path: Path) -> dict: if not path.exists(): return {} try: obj = json.loads(path.read_text(encoding="utf-8")) return obj if isinstance(obj, dict) else {} except Exception: return {} def main() -> int: ap = argparse.ArgumentParser() ap.add_argument("--late", default=str(DEFAULT_IN)) ap.add_argument("--out", default=str(DEFAULT_OUT)) args = ap.parse_args() late = _load(Path(args.late)) metrics = late.get("metrics") if isinstance(late.get("metrics"), dict) else {} threshold_ledger = late.get("threshold_ledger") if isinstance(late.get("threshold_ledger"), list) else [] threshold = (late.get("velocity_decile_thresholds") or {}).get("recommended_block_threshold", 70) false_positive_rate = float(metrics.get("late_chase_proxy_false_positive_rate_pct") or 0.0) sample_n = int((late.get("operational_samples") or late.get("samples") or 0)) avg_loss = None if threshold_ledger: vals = [float(row.get("avg_t5_return_pct")) for row in threshold_ledger if isinstance(row, dict) and row.get("avg_t5_return_pct") is not None] if vals: avg_loss = round(abs(sum(vals) / len(vals)), 2) result = { "formula_id": "ANTI_LATE_CHASE_V6", "gate": "PASS" if sample_n > 0 else "INSUFFICIENT_DATA", "late_entry_false_positive_rate": round(false_positive_rate, 2), "chase_block_reason": "late_chase_risk_score>=threshold", "opportunity_loss_pct": avg_loss, "sample_count": sample_n, "threshold": threshold, "threshold_source": "late_chase_attribution_v1", "source_path": str(Path(args.late)), } out = Path(args.out) out.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8") print(json.dumps(result, ensure_ascii=False, indent=2)) return 0 if __name__ == "__main__": raise SystemExit(main())