Files
PythagorasGoal/tests/test_harness_realism.py
T
Adriano Dal Pastro d5dd6f4b72 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>
2026-06-21 15:22:58 +00:00

84 lines
3.5 KiB
Python

"""Locks the two harness-realism gates codified from the 2026-06-21 intraday wave:
* day_boundary_robust — a calendar/session/hour signal whose marginal uplift INVERTS when
the UTC day boundary is shifted is a labeling ARTIFACT (this killed open_drive). A price
signal that ignores the calendar is INVARIANT; a genuine calendar effect is ROBUST.
* eval_weights_smallcap — at ~$600 a sub-min_order rebalance can't execute; the modeled
proportional fee on thousands of sub-dollar moves is a fiction. The realistic evaluator
skips them.
"""
import sys
from pathlib import Path
import numpy as np
import pandas as pd
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "scripts" / "research" / "alt"))
import altlib as al # noqa: E402
# --- LESSON 1: day-boundary robustness -------------------------------------------------
def test_day_boundary_invariant_for_price_signal():
"""A signal that never reads the calendar is INVARIANT to the day-boundary shift."""
def mom(df):
c = df["close"].values
return np.tanh(3 * (c / al.sma(c, 200) - 1))
r = al.day_boundary_robust(mom, offsets=(0, 6, 12, 18))
assert r["verdict"] == "INVARIANT"
assert r["spread"] == 0.0
assert r["calendar_sensitive"] is False
def test_day_boundary_flags_calendar_artifact():
"""A pure hour-of-day bias is calendar-sensitive: its uplift swings with the boundary
(the open_drive failure mode). It must be flagged, never INVARIANT."""
def hourbias(df):
h = pd.to_datetime(df["datetime"], utc=True).dt.hour.values
return np.where(h < 8, 1.0, 0.0)
r = al.day_boundary_robust(hourbias, offsets=(0, 6, 12, 18))
assert r["calendar_sensitive"] is True
assert r["spread"] > 0.05
assert r["verdict"] != "INVARIANT"
# --- LESSON 2: small-capital fill realism ----------------------------------------------
def test_smallcap_skips_subdollar_rebalances():
"""Thousands of sub-min_order wiggles (a vol-target overlay's fiction) do NOT execute."""
df = al.get("BTC", "1h")
rng = np.random.default_rng(0)
micro = 0.5 + 0.001 * rng.standard_normal(len(df)) # tiny drift around 0.5
r = al.eval_weights_smallcap(df, micro, capital=600.0, min_order=5.0)
modeled_turn = al.eval_weights(df, micro)["turnover_per_year"]
assert r["executed_turnover_per_year"] < modeled_turn * 0.2
assert r["n_executed_trades"] < len(df) * 0.05
def test_smallcap_keeps_real_trades():
"""A low-turnover signal with genuine large moves executes them, ~no Sharpe haircut."""
df = al.get("BTC", "1h")
step = np.zeros(len(df)); step[: len(df) // 2] = 0.5; step[len(df) // 2:] = -0.5
r = al.eval_weights_smallcap(df, step, capital=600.0, min_order=5.0)
assert r["n_executed_trades"] >= 2
assert abs(r["sharpe_haircut"]) < 0.2
# --- LESSON 3: look-ahead (online-consistency) guard -----------------------------------
def test_causality_passes_causal_signal():
"""A causal signal recomputed on a prefix matches the full run on its tail."""
def mom(df):
c = df["close"].values
return np.tanh(3 * (c / al.sma(c, 200) - 1))
r = al.causality_ok(mom, tf="1h")
assert r["ok"] is True
assert r["max_tail_diff"] == 0.0
def test_causality_flags_lookahead():
"""A signal that reads tomorrow's move (future peek) is disqualified."""
def leaky(df):
c = df["close"].values
f = np.zeros(len(c)); f[:-1] = np.sign(c[1:] - c[:-1]) # uses close[i+1]
return f
r = al.causality_ok(leaky, tf="1h")
assert r["ok"] is False