--- project: anomaly-atlas document: Artifact taxonomy author: Simon-Pierre Boucher contact: contact@spboucher.ai data_source: hfmarketdata.io created: 2026-08-12 modified: 2026-08-12 status: reviewed --- # Artifact taxonomy (living document) The catalogue of mechanisms **in this specific dataset** that manufacture fake anomalies — a primary deliverable (Q4). Every entry: mechanism, detection, measured magnitude on this data, neutralization. Magnitudes from `results/expA_data_reality/20260812T054515Z/` and `results/expB_artifact_baselines/20260812T055602Z/` (Q1 2024, RTH 1min, pre-specified universe). Detectors validated on synthetic ground truth first (`benchmarks/synthetic/test_synthetic_gate.py`, 11 tests). ## T1 — Bid-ask bounce (Roll) * **Mechanism.** Trades alternate bid/ask; observed returns gain a negative lag-1 autocovariance (−s²/4) with no economics. Masquerades as mean-reversion (Q1). * **Detection.** Roll implied relative spread `2·√(−autocov1)`; bounce-implied AC1; `excess_reversion()` (validation/artifacts.py). * **Measured.** Median AC1 by staleness tercile: −0.009 (fresh) / −0.051 (mid) / **−0.232 (stale)**; Roll spread 1.4 / 3.8 / 17.0 bp. Mega-caps: no measurable bounce (AC1 CI covers 0; Roll undefined ~half the time — positive autocov). * **Neutralize.** Report reversion net of the liquidity-bucket bounce null; never average AC1 across liquidity buckets; treat Roll-undefined as "no bounce measurable", not zero spread. * **expC amendment (measured).** A daily *effective* spread (EDGE) combined with pure Roll alternation predicts impossible intraday AC1 (−3 to −27): consecutive intraday closes do not flip sides each bar. Spread-based bounce nulls MUST be variance-consistent with the target series; for intraday scans use the MA(1)-consistent VR null (VR_null(q) = 1 + 2·AC1·(1−1/q)) — conservative, absorbs all lag-1 effects. ## T2 — Stale prices / missing minutes * **Mechanism.** Bars exist only where trades occurred (expA: zero zero-volume bars; an illiquid name printed 38 bars/day). LOCF joins add a large mass of zero returns and depress variance-ratio statistics. * **Detection.** `staleness_ratio` on the 390-min RTH grid. * **Measured.** Staleness up to 0.90 (RITM.B); **VR(30) = 0.55 median for the stale tercile — 0.35 extreme — with zero planted economics.** 11/42 pre-specified tickers had too little data to analyze at all. * **Neutralize.** Explicit grids with observed-masks (never silent LOCF); liquidity filters pre-specified; VR/AC1 claims benchmarked against the staleness-matched null, not against 1.0. ## T3 — Non-synchronous lead-lag (LOCF cross-correlation) * **Mechanism.** A fresh series LOCF-joined to a stale one appears to LEAD it: the stale print reflects old common information (classic non-synchronous trading bias). * **Detection.** Lagged cross-correlation vs SPY on the LOCF grid; synthetic ground truth: rho=0.7 pair with 30 % observation → spurious +1 lag corr. * **Measured.** SPY "leads" mid-staleness tickers by +0.047 at +1 min (Spearman vs staleness +0.43). **SPX-vs-SPY: +0.065 with SPY leading 1 min** at 0.965 contemporaneous corr — index prints lag the ETF. * **Neutralize.** Any Q2 lead-lag claim must exceed the staleness-predicted cross-correlation; test on synchronized (both-fresh) subsamples; index series are stale by construction. * **expD amendments (measured).** (i) The artifact is NON-MONOTONE in staleness: LOCF joins inflate leads for mid-stale names (+0.047, expB) but DILUTE them for ultra-stale names (HTD raw +0.048 vs both-fresh +0.073) — naive joins can hide lead-lag as well as manufacture it. (ii) For computed indices, synchronizing on PRINT times removes nothing: SPY leads SPX +0.132 both-fresh (fresh_frac 0.996) — content staleness must be modeled, not print gaps. ## T4 — Auction close vs last bar * **Mechanism.** Daily bars carry the official closing-auction print; 1min bars do not (expA: AAPL 312.41 daily close vs 312.49 last RTH 1min close). Mixing conventions manufactures phantom overnight/close-to-close returns. * **Measured.** 8 bp discrepancy on a calm day for the most liquid stock. * **Neutralize.** Pick ONE close convention per experiment and state it; never compute overnight returns across mixed conventions. ## T5 — Rolling adjustment anchor * **Mechanism.** `adj_splitdiv` re-bases the whole history to the dataset build date (expA: AAPL 2020-08-31 close = 125.17 adjusted vs 129.04 traded). Adjusted series are not point-in-time stable → silent look-ahead and irreproducibility if the cache is refreshed mid-study. * **Neutralize.** Frozen local cache (hf_client never silently refetches); data-manifest hash in every provenance; intraday work uses within-day returns (adjustment-invariant) or UNADJUSTED plus explicit factors. ## T6 — Daily vs intraday volume conventions * **Mechanism.** Daily volume includes auction/consolidated prints absent from 1min bars (expA: 46.1 M daily vs 34.7 M extended-1min sum vs 25.7 M RTH-1min sum for AAPL on one day — a 1.8× spread across conventions). * **Neutralize.** Volume-based signals pick one convention; never mix daily and intraday volume in one feature. ## T7 — Vendor session / timezone semantics * **Mechanism.** All timestamps are US/Eastern wall-clock without a marker; sessions differ per class (equities 04:00–19:59, SPX prints to 16:20, futures ≈24 h, fx ET-week, crypto 24/7). Cross-asset joins on naive timestamps silently compare different market states. * **Neutralize.** One canonical calendar module (`data/calendars.py`), explicit session filters per asset class, DST-aware conversions. --- **T1/T2 intraday profile (measured, expE/H20 — liquid 12, 1min, 2014-2015).** Volatility is U-shaped: median |1min return| 6.6 bp at 09:30 → 2.4 bp midday → 2.9 bp at 15:30. The EDGE spread declines monotonically 2.8 → 1.2 bp (an L, not a U). Consequence: intraday return claims concentrated at the open face 2–3× the midday artifact level and double the closing spread — expE/expG must bucket-match their nulls and costs by time of day. *Open items: continuous-futures splice choice (3 variants exposed by the API) as a testable artifact for futures-based hypotheses — expD found the ES→SPY cross-serial effect splice-INVARIANT, so the residual exposure is futures-only level/trend work.*