harness(causality): guardia look-ahead + calendar-artifact self-policing nel lab intraday
- altlib.causality_ok(target_fn, tf): online-consistency guard (ricalcola il target su un prefisso, la coda deve combaciare col full). eval_weights shifta la posizione ma non vede una feature non-causale (finestra centrata/shift(-k)/stat full-sample) -> questa sì. - intra_score integra DUE gate prima/dopo lo scoring: causality (leak -> LEAK, squalificato) e day_boundary_robust (ARTIFACT-RISK -> fuori dagli slot). Effetto sul leaderboard intraday: open_drive + weekly_seasonality + overnight -> CAL-ARTIFACT (da soli, niente skeptic); prevday_range_breakout resta (ROBUST). earns_slot 10 -> 8. - +2 test (causal-ok / leak), suite intera verde. Il lab intraday ora auto-becca leak e artefatti-calendario che ieri richiedevano 3 scettici. Chiude la 3a lezione harness dell'onda intraday. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,15 @@ def score(path: Path, tf: str) -> dict:
|
||||
target = _target(path)
|
||||
except Exception as e:
|
||||
return {**rec, "error": f"import: {e}", "earns_slot": False}
|
||||
# LOOK-AHEAD guard first: eval_weights' shift can't catch a non-causal FEATURE (centered
|
||||
# window / shift(-k) / full-sample stat). A leak is disqualified no matter its Sharpe.
|
||||
try:
|
||||
caus = al.causality_ok(target, tf=tf)
|
||||
rec["causal"] = bool(caus["ok"])
|
||||
if not caus["ok"]:
|
||||
return {**rec, "causality": caus, "marginal_verdict": "LEAK", "earns_slot": False}
|
||||
except Exception as e:
|
||||
return {**rec, "error": f"causality: {e}", "causal": False, "earns_slot": False}
|
||||
try:
|
||||
rep = al.study_marginal(path.stem, target, tf=tf)
|
||||
except Exception as e:
|
||||
@@ -64,6 +73,17 @@ def score(path: Path, tf: str) -> dict:
|
||||
turnover_per_year=round(turn, 1), fee020_full_sharpe=round(fee020, 3),
|
||||
fee_survives=cell.get("fee_survives"),
|
||||
)
|
||||
# calendar-artifact guard: a signal whose marginal uplift INVERTS under a UTC day-boundary
|
||||
# shift is a labeling artifact (open_drive), not an intraday effect. INVARIANT (price
|
||||
# signal) and ROBUST (genuine calendar effect, e.g. prevday breakout) pass.
|
||||
try:
|
||||
db = al.day_boundary_robust(target, tf=tf)
|
||||
rec["boundary_verdict"] = db["verdict"]
|
||||
rec["boundary_spread"] = db["spread"]
|
||||
if db["verdict"] == "ARTIFACT-RISK":
|
||||
rec["earns_slot"] = False
|
||||
except Exception as e:
|
||||
rec["boundary_verdict"] = f"err:{e}"
|
||||
return rec
|
||||
|
||||
|
||||
@@ -85,10 +105,14 @@ def main():
|
||||
for r in rows:
|
||||
if "error" in r:
|
||||
print(f" {r['name'][:26]:<26}{r['tf']:>4} ERROR {r['error'][:40]}"); continue
|
||||
if r.get("causal") is False:
|
||||
print(f" {r['name'][:26]:<26}{r['tf']:>4} LEAK (look-ahead, disqualified) "
|
||||
f"max_tail_diff={r.get('causality', {}).get('max_tail_diff')}"); continue
|
||||
bflag = " CAL-ARTIFACT" if r.get("boundary_verdict") == "ARTIFACT-RISK" else ""
|
||||
print(f" {r['name'][:26]:<26}{r['tf']:>4} {str(r['marginal_verdict']):<9}"
|
||||
f"{str(r['abs_grade']):>5}{str(r.get('corr_hold')):>6}{str(r.get('uplift_hold')):>6}"
|
||||
f"{str(r.get('cand_insample_sharpe')):>6}{str(r.get('turnover_per_year')):>6}"
|
||||
f"{str(r.get('fee020_full_sharpe')):>7} {'<<<' if r.get('earns_slot') else ''}")
|
||||
f"{str(r.get('fee020_full_sharpe')):>7} {'<<<' if r.get('earns_slot') else bflag}")
|
||||
slots = [r["name"] for r in rows if r.get("earns_slot")]
|
||||
print(f"\n EARNS SLOT: {slots or 'NONE'}")
|
||||
(HERE / "intra_leaderboard.json").write_text(json.dumps(rows, indent=2, default=str))
|
||||
|
||||
Reference in New Issue
Block a user