SPB Git

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%
6.3 KB · 127 lines markdown
Rendered Raw Blame History
1---2project: anomaly-atlas3document: Artifact taxonomy4author: Simon-Pierre Boucher5contact: contact@spboucher.ai6data_source: hfmarketdata.io7created: 2026-08-128modified: 2026-08-129status: reviewed10---1112# Artifact taxonomy (living document)1314The catalogue of mechanisms **in this specific dataset** that manufacture15fake anomalies — a primary deliverable (Q4). Every entry: mechanism,16detection, measured magnitude on this data, neutralization. Magnitudes from17`results/expA_data_reality/20260812T054515Z/` and18`results/expB_artifact_baselines/20260812T055602Z/` (Q1 2024, RTH 1min,19pre-specified universe). Detectors validated on synthetic ground truth first20(`benchmarks/synthetic/test_synthetic_gate.py`, 11 tests).2122## T1 — Bid-ask bounce (Roll)2324* **Mechanism.** Trades alternate bid/ask; observed returns gain a negative25  lag-1 autocovariance (−s²/4) with no economics. Masquerades as26  mean-reversion (Q1).27* **Detection.** Roll implied relative spread `2·√(−autocov1)`;28  bounce-implied AC1; `excess_reversion()` (validation/artifacts.py).29* **Measured.** Median AC1 by staleness tercile: −0.009 (fresh) / −0.05130  (mid) / **−0.232 (stale)**; Roll spread 1.4 / 3.8 / 17.0 bp. Mega-caps:31  no measurable bounce (AC1 CI covers 0; Roll undefined ~half the time —32  positive autocov).33* **Neutralize.** Report reversion net of the liquidity-bucket bounce null;34  never average AC1 across liquidity buckets; treat Roll-undefined as35  "no bounce measurable", not zero spread.36* **expC amendment (measured).** A daily *effective* spread (EDGE) combined37  with pure Roll alternation predicts impossible intraday AC1 (−3 to −27):38  consecutive intraday closes do not flip sides each bar. Spread-based39  bounce nulls MUST be variance-consistent with the target series; for40  intraday scans use the MA(1)-consistent VR null41  (VR_null(q) = 1 + 2·AC1·(1−1/q)) — conservative, absorbs all lag-142  effects.4344## T2 — Stale prices / missing minutes4546* **Mechanism.** Bars exist only where trades occurred (expA: zero47  zero-volume bars; an illiquid name printed 38 bars/day). LOCF joins add a48  large mass of zero returns and depress variance-ratio statistics.49* **Detection.** `staleness_ratio` on the 390-min RTH grid.50* **Measured.** Staleness up to 0.90 (RITM.B); **VR(30) = 0.55 median for51  the stale tercile — 0.35 extreme — with zero planted economics.** 11/4252  pre-specified tickers had too little data to analyze at all.53* **Neutralize.** Explicit grids with observed-masks (never silent LOCF);54  liquidity filters pre-specified; VR/AC1 claims benchmarked against the55  staleness-matched null, not against 1.0.5657## T3 — Non-synchronous lead-lag (LOCF cross-correlation)5859* **Mechanism.** A fresh series LOCF-joined to a stale one appears to LEAD60  it: the stale print reflects old common information (classic61  non-synchronous trading bias).62* **Detection.** Lagged cross-correlation vs SPY on the LOCF grid; synthetic63  ground truth: rho=0.7 pair with 30 % observation → spurious +1 lag corr.64* **Measured.** SPY "leads" mid-staleness tickers by +0.047 at +1 min65  (Spearman vs staleness +0.43). **SPX-vs-SPY: +0.065 with SPY leading66  1 min** at 0.965 contemporaneous corr — index prints lag the ETF.67* **Neutralize.** Any Q2 lead-lag claim must exceed the staleness-predicted68  cross-correlation; test on synchronized (both-fresh) subsamples; index69  series are stale by construction.70* **expD amendments (measured).** (i) The artifact is NON-MONOTONE in71  staleness: LOCF joins inflate leads for mid-stale names (+0.047, expB) but72  DILUTE them for ultra-stale names (HTD raw +0.048 vs both-fresh +0.073) —73  naive joins can hide lead-lag as well as manufacture it. (ii) For computed74  indices, synchronizing on PRINT times removes nothing: SPY leads SPX75  +0.132 both-fresh (fresh_frac 0.996) — content staleness must be modeled,76  not print gaps.7778## T4 — Auction close vs last bar7980* **Mechanism.** Daily bars carry the official closing-auction print; 1min81  bars do not (expA: AAPL 312.41 daily close vs 312.49 last RTH 1min close).82  Mixing conventions manufactures phantom overnight/close-to-close returns.83* **Measured.** 8 bp discrepancy on a calm day for the most liquid stock.84* **Neutralize.** Pick ONE close convention per experiment and state it;85  never compute overnight returns across mixed conventions.8687## T5 — Rolling adjustment anchor8889* **Mechanism.** `adj_splitdiv` re-bases the whole history to the dataset90  build date (expA: AAPL 2020-08-31 close = 125.17 adjusted vs 129.0491  traded). Adjusted series are not point-in-time stable → silent look-ahead92  and irreproducibility if the cache is refreshed mid-study.93* **Neutralize.** Frozen local cache (hf_client never silently refetches);94  data-manifest hash in every provenance; intraday work uses within-day95  returns (adjustment-invariant) or UNADJUSTED plus explicit factors.9697## T6 — Daily vs intraday volume conventions9899* **Mechanism.** Daily volume includes auction/consolidated prints absent100  from 1min bars (expA: 46.1 M daily vs 34.7 M extended-1min sum vs 25.7 M101  RTH-1min sum for AAPL on one day — a 1.8× spread across conventions).102* **Neutralize.** Volume-based signals pick one convention; never mix daily103  and intraday volume in one feature.104105## T7 — Vendor session / timezone semantics106107* **Mechanism.** All timestamps are US/Eastern wall-clock without a marker;108  sessions differ per class (equities 04:00–19:59, SPX prints to 16:20,109  futures ≈24 h, fx ET-week, crypto 24/7). Cross-asset joins on naive110  timestamps silently compare different market states.111* **Neutralize.** One canonical calendar module (`data/calendars.py`),112  explicit session filters per asset class, DST-aware conversions.113114---115116**T1/T2 intraday profile (measured, expE/H20 — liquid 12, 1min, 2014-2015).**117Volatility is U-shaped: median |1min return| 6.6 bp at 09:30 → 2.4 bp midday118→ 2.9 bp at 15:30. The EDGE spread declines monotonically 2.8 → 1.2 bp (an119L, not a U). Consequence: intraday return claims concentrated at the open120face 2–3× the midday artifact level and double the closing spread — expE/expG121must bucket-match their nulls and costs by time of day.122123*Open items: continuous-futures splice choice (3 variants exposed by the124API) as a testable artifact for futures-based hypotheses — expD found the125ES→SPY cross-serial effect splice-INVARIANT, so the residual exposure is126futures-only level/trend work.*127