spb/anomaly-atlas Public License
Systematic discovery & rigorous validation of statistical anomalies in open HF market data (hfmarketdata.io) — pre-registered, artifact-null-driven, fully reproducible. Live atlas: www.anomaly-atlas.io
Python 61.4%
JavaScript 28.7%
CSS 8.6%
Shell 0.7%
Makefile 0.5%
1# =============================================================================2# Project : anomaly-atlas3# File : benchmarks/synthetic/test_gate_expf.py4# Purpose : §8.1 gate for expF: Reality Check, SPA, Deflated Sharpe5# Author : Simon-Pierre Boucher6# Contact : contact@spboucher.ai7# Data src : hfmarketdata.io (sole data source)8# Created : 2026-08-129# Modified : 2026-08-1210# Platform : macOS / Apple Silicon (arm64)11# License : All rights reserved (research code)12# =============================================================================13"""Gate the correction battery before it touches real scan output:1415 * a universe of PURE-NOISE rules must not survive RC/SPA (p not small),16 and its best Sharpe must be fully explained by selection (DSR ~ 0);17 * a planted genuinely profitable rule must survive all three;18 * the bootstrap must respect serial dependence (block structure).19"""2021from __future__ import annotations2223import numpy as np2425from anomaly_atlas.stats.spa import deflated_sharpe, reality_check, spa_test2627T, N = 1500, 60 # ~6 years of days, 60 searched rules282930def noise_matrix(seed: int) -> np.ndarray:31 rng = np.random.default_rng(seed)32 return rng.normal(0.0, 0.01, (T, N))333435def test_pure_noise_universe_does_not_survive():36 ps_rc, ps_spa = [], []37 for seed in (1, 2, 3, 4, 5):38 x = noise_matrix(seed)39 ps_rc.append(reality_check(x, n_boot=300, seed=seed)["p"])40 ps_spa.append(spa_test(x, n_boot=300, seed=seed)["p"])41 # under H0 the p-values should look uniform: none should be tiny,42 # and on average they must be comfortably away from 043 assert min(ps_rc) > 0.01 and np.mean(ps_rc) > 0.244 assert min(ps_spa) > 0.01 and np.mean(ps_spa) > 0.2454647def test_planted_profitable_rule_survives_rc_and_spa():48 for seed in (1, 2, 3):49 x = noise_matrix(seed)50 rng = np.random.default_rng(seed + 100)51 x[:, 7] = rng.normal(0.0015, 0.01, T) # daily SR ~ 0.15 (t ~ 5.8)52 rc = reality_check(x, n_boot=300, seed=seed)53 sp = spa_test(x, n_boot=300, seed=seed)54 assert rc["p"] < 0.02 and rc["best_rule"] == 755 assert sp["p"] < 0.02 and sp["best_rule"] == 7565758def test_dsr_kills_noise_best_and_keeps_planted():59 rng = np.random.default_rng(9)60 x = noise_matrix(9)61 srs = x.mean(axis=0) / x.std(axis=0, ddof=1)62 best = int(np.argmax(srs))63 r = x[:, best]64 d_noise = deflated_sharpe(65 sr=float(srs[best]), t_len=T,66 skew=float(((r - r.mean()) ** 3).mean() / r.std() ** 3),67 kurt=float(((r - r.mean()) ** 4).mean() / r.std() ** 4),68 n_trials=N, sr_variance=float(srs.var(ddof=1)),69 )70 assert d_noise["dsr"] < 0.6 # selection explains the best noise Sharpe71 # planted strong rule72 x[:, 3] = rng.normal(0.002, 0.01, T)73 srs2 = x.mean(axis=0) / x.std(axis=0, ddof=1)74 r2 = x[:, 3]75 d_real = deflated_sharpe(76 sr=float(srs2[3]), t_len=T,77 skew=float(((r2 - r2.mean()) ** 3).mean() / r2.std() ** 3),78 kurt=float(((r2 - r2.mean()) ** 4).mean() / r2.std() ** 4),79 n_trials=N, sr_variance=float(srs2.var(ddof=1)),80 )81 assert d_real["dsr"] > 0.9582 assert d_noise["dsr"] < d_real["dsr"]838485def test_stationary_bootstrap_preserves_dependence():86 from anomaly_atlas.stats.spa import stationary_bootstrap_indices8788 idx = stationary_bootstrap_indices(1000, mean_block=20, n_boot=50, seed=3)89 # consecutive indices should usually be consecutive (inside a block)90 consecutive = np.mean((np.diff(idx, axis=1) % 1000) == 1)91 assert consecutive > 0.9 # mean block 20 -> ~95% of steps are within-block92 assert idx.min() >= 0 and idx.max() < 100093