# ============================================================================= # Project : anomaly-atlas # File : experiments/micro/expH_oos_stability/benchmark.py # Purpose : Out-of-sample stability on the untouched validation split # Author : Simon-Pierre Boucher # Contact : contact@spboucher.ai # Data src : hfmarketdata.io (sole data source) # Created : 2026-08-12 # Modified : 2026-08-12 # Platform : macOS / Apple Silicon (arm64) # License : All rights reserved (research code) # ============================================================================= """Experiment H — the validation split (2016-2021), opened for the first time. Re-evaluates, with machinery identical to expC/expD/expG (imported from their committed benchmarks, not re-implemented): the expG pool net of costs, the ES->SPY basis effect, and the daily reversal family. The sealed HOLDOUT (2022->) is not touched. """ from __future__ import annotations import importlib.util import json import sys from datetime import UTC, datetime from pathlib import Path import numpy as np REPO_ROOT = Path(__file__).resolve().parents[3] sys.path.insert(0, str(REPO_ROOT / "benchmarks")) sys.path.insert(0, str(REPO_ROOT / "src")) from hardware_manifest import collect_manifest # noqa: E402 from anomaly_atlas.data.cleaning import rth_day_grids # noqa: E402 from anomaly_atlas.data.hf_client import HFMarketDataClient # noqa: E402 from anomaly_atlas.data.universe import LIQUID_ETF, LIQUID_STOCK, VALIDATION # noqa: E402 from anomaly_atlas.stats.bootstrap import moving_block_bootstrap, percentile_ci # noqa: E402 from anomaly_atlas.stats.multiple_testing import bootstrap_pvalue # noqa: E402 from anomaly_atlas.stats.reversion import ac1, variance_ratio # noqa: E402 from anomaly_atlas.validation.artifacts import edge_spread # noqa: E402 def load_module(name: str, rel: str): spec = importlib.util.spec_from_file_location(name, REPO_ROOT / rel) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return mod expg = load_module("expg_bench", "experiments/micro/expG_cost_frontier/benchmark.py") expd = load_module("expd_bench", "experiments/micro/expD_leadlag_scan/benchmark.py") ADJ = "adj_split" VAL_SUBS = {"2016-2018": ("2016-01-01", "2019-01-01"), "2019-2021": ("2019-01-01", "2022-01-01")} KAPPA_CHECK = ("0.25", "1.0") def eval_pool_on(client, rev_pool, ll_pool, start, end, label) -> list[dict]: items = [] for r in rev_pool: bars = client.get_bars(r["asset"], r["ticker"], r["timeframe"], ADJ, start, end) stream = expg.contrarian_stream(bars, r["timeframe"]) hs = expg.half_spread(client, r["asset"], r["ticker"], ADJ, start, end) if len(stream) < 150: continue item = {"rule": f"R:{r['ticker']}:{r['timeframe']}", "family": "reversion", "window": label} | expg.sweep(stream, hs) items.append(item) needed = {"SPY"} | {p["leader"] for p in ll_pool} | {p["follower"] for p in ll_pool} grids = {} for name in sorted(needed): if name == "ES": g = rth_day_grids(client.get_bars("futures", "ES", "1min", "contin_adj_ratio", start, end)) else: asset = ("etf" if name in ("SPY", "QQQ") or name.startswith("XL") else "stock") g = rth_day_grids(client.get_bars(asset, name, "1min", ADJ, start, end)) grids[name] = g day_list = sorted(grids["SPY"].keys()) for p in ll_pool: if p["leader"] not in grids or p["follower"] not in grids: continue stream = expg.leadlag_stream(grids[p["leader"]], grids[p["follower"]], day_list, p["sign"]) if len(stream) < 150: continue traded = p["follower"] asset = ("futures" if traded == "ES" else "etf" if traded in ("SPY", "QQQ") or traded.startswith("XL") else "stock") adj = "contin_adj_ratio" if traded == "ES" else ADJ hs = expg.half_spread(client, asset, traded, adj, start, end) item = {"rule": f"L:{p['pair']}:{'+' if p['sign'] > 0 else '-'}", "family": "leadlag", "window": label} | expg.sweep(stream, hs) items.append(item) return items, grids, day_list def main() -> None: run_utc = datetime.now(UTC) client = HFMarketDataClient() rev_pool, ll_pool = expg.pool_from_committed_results() s, e = VALIDATION # (a,b) pool on validation items, grids, day_list = eval_pool_on(client, rev_pool, ll_pool, s, e, "validation") for it in items: print(it["rule"], "kappa* =", it.get("kappa_star")) # CKX sub-period check (Q-a robustness clause) ckx_subs = {} for sub, (ss, ee) in VAL_SUBS.items(): bars = client.get_bars("stock", "CKX", "1day", ADJ, ss, ee) stream = expg.contrarian_stream(bars, "1day") hs = expg.half_spread(client, "stock", "CKX", ADJ, ss, ee) ckx_subs[sub] = expg.sweep(stream, hs) if len(stream) >= 100 else {"n_days": len(stream)} # (c) ES->SPY and SPX->SPY fresh xcorr on validation xcorr_out = {} spy_mat = expd.day_matrix(grids["SPY"], day_list) for name in ("ES", "SPX"): if name == "SPX": g = rth_day_grids(client.get_bars("index", "SPX", "1min", None, s, e)) else: g = grids.get("ES") or rth_day_grids( client.get_bars("futures", "ES", "1min", "contin_adj_ratio", s, e)) mat = expd.day_matrix(g, day_list) m = expd.analyze_pair(mat[0], mat[1], spy_mat[0], spy_mat[1]) if m: xcorr_out[f"{name}->SPY"] = {k: m[k] for k in ("fresh_xcorr", "raw_xcorr", "p_fresh_+1", "p_fresh_-1", "n_fresh_pairs")} # ES splice invariance for adj in ("contin_adj_absolute", "contin_UNadj"): g = rth_day_grids(client.get_bars("futures", "ES", "1min", adj, s, e)) mat = expd.day_matrix(g, day_list) m = expd.analyze_pair(mat[0], mat[1], spy_mat[0], spy_mat[1]) if m: xcorr_out[f"ES[{adj}]->SPY"] = {"fresh_-1": m["fresh_xcorr"]["-1"], "fresh_+1": m["fresh_xcorr"]["1"]} # (d) daily reversal family on validation vs train values rc = expg.latest(str(REPO_ROOT / "results/expC_reversion_scan/*/results.json")) train_daily = {c["ticker"]: c for c in rc["cells"] if c["timeframe"] == "1day" and c["period"] == "2008-2015"} family = [] for asset, ticker in [("stock", t) for t in LIQUID_STOCK] + \ [("etf", t) for t in LIQUID_ETF]: bars = client.get_bars(asset, ticker, "1day", ADJ, s, e) if len(bars) < 500: continue closes = np.array([b["close"] for b in bars]) r = np.diff(np.log(closes)) a = ac1(r) vr30 = variance_ratio(r, 30) o = np.array([b["open"] for b in bars]) h = np.array([b["high"] for b in bars]) lo = np.array([b["low"] for b in bars]) c = closes sp = edge_spread(o, h, lo, c) var = r.var() bounce = -(sp**2) / 4 / var if np.isfinite(sp) and var > 0 else 0.0 boot = moving_block_bootstrap(r, ac1, block=21, n_boot=300, seed=42) lo_ci, hi_ci = percentile_ci(boot - bounce) tr = train_daily.get(ticker, {}) family.append({ "ticker": ticker, "val_ac1": round(a, 5), "val_excess_ac1": round(a - bounce, 5), "val_excess_ci95": [round(lo_ci, 5), round(hi_ci, 5)], "val_p_excess": bootstrap_pvalue(boot - bounce, 0.0), "val_vr30_excess": round(vr30 - (1 + 2 * a * (1 - 1 / 30)), 4), "train_excess_ac1": tr.get("excess_ac1"), "train_vr30_excess": round(tr["vr30"] - (1 + 2 * tr["ac1"] * (1 - 1 / 30)), 4) if tr else None, }) ck = {str(k): [i["rule"] for i in items if i["net"].get(str(k), {}).get("positive") and i["net"].get(str(k), {}).get("ci95_bp", [1])[0] > 0] for k in (0.25, 1.0)} med_val = float(np.median([f["val_vr30_excess"] for f in family])) med_train = float(np.median([f["train_vr30_excess"] for f in family if f["train_vr30_excess"] is not None])) summary = { "pool_evaluated": len(items), "net_pos_ci_at": ck, "ckx_validation": next((i for i in items if i["rule"].startswith("R:CKX")), None), "ckx_subperiods": ckx_subs, "es_spy_val_fresh_-1": xcorr_out.get("ES->SPY", {}).get("fresh_xcorr", {}).get("-1"), "es_spy_val_p_-1": xcorr_out.get("ES->SPY", {}).get("p_fresh_-1"), "spx_spy_val_fresh_-1": xcorr_out.get("SPX->SPY", {}).get("fresh_xcorr", {}).get("-1"), "daily_family_median_vr30_excess": {"train_2008_2015": round(med_train, 4), "validation": round(med_val, 4)}, } results = { "experiment": "expH_oos_stability", "run_utc": run_utc.isoformat(), "author": "Simon-Pierre Boucher", "contact": "contact@spboucher.ai", "data_source": "hfmarketdata.io", "confidence_level": "evaluates Level-1/2 claims on the validation split", "protocol": {"validation": VALIDATION, "subs": VAL_SUBS, "holdout_untouched": True}, "pool_items": items, "xcorr": xcorr_out, "daily_family": family, "summary": summary, "client_stats": vars(client.stats) | {"refreshes": list(client.stats.refreshes)}, "manifest": collect_manifest(), } out_dir = REPO_ROOT / "results" / "expH_oos_stability" / run_utc.strftime("%Y%m%dT%H%M%SZ") out_dir.mkdir(parents=True) (out_dir / "results.json").write_text( json.dumps(expg.sanitize(results), indent=2, allow_nan=False) + "\n") print(f"\nwrote {out_dir.relative_to(REPO_ROOT)}/results.json") print(json.dumps(expg.sanitize(summary), indent=1)) if __name__ == "__main__": main()