Russell 3000 · Equity Statistical Arbitrage · 2020–2025

Pairs trading research,
measured honestly.

A modular cointegration-based statistical arbitrage system — Kalman-filtered spreads, regime-adaptive position sizing, walk-forward validation — with a controlled ablation that quantifies each component's contribution to out-of-sample performance.

+0.90%
Main backtest return
Jul 2023–2025 (t+1)
+0.08%
Walk-forward OOS
per quarter
0.50
Main Sharpe vs 0.16
textbook (Gatev)
p = 0.83
OOS edge vs zero
(not significant)

Under realistic t+1 execution (fill on the bar after the signal, not the same bar), the out-of-sample edge collapses from +0.49%/qtr to +0.08%/qtr — most of the apparent edge was same-bar look-ahead. Significance testing confirms it: OOS Sharpe 0.08, t-stat 0.22, p=0.83, bootstrap CI includes zero, and zero pairs survive a Benjamini-Hochberg multiple-testing correction. The pipeline still beats a random-pair control decisively and the textbook distance method on a risk-adjusted basis. The deliverable is a rigorously validated research framework — and the discipline to prove the edge isn't significant — not a deployable alpha.

01 — Walk-forward returns

Nineteen non-overlapping quarters

Each window: 252 trading days of training, 63 days of out-of-sample testing, models retrained from scratch. W1–W9 precede the 2023 regime break; W10–W19 follow it.

Quarterly window returns, % positive negative
IN-SAMPLE OUT-OF-SAMPLE W1 · +2.97% W2 · +1.12% W3 · +1.26% W4 · +2.66% W5 · +4.28% W6 · +4.87% W7 · +3.27% W8 · +1.25% W9 · +1.00% W10 · −1.24% W11 · −0.22% W12 · +2.65% W13 · −0.78% W14 · −0.19% W15 · +0.48% W16 · −0.82% W17 · −0.69% W18 · +1.19% W19 · +0.46% W1 W5 W10 W15 W19 +4.9
02 — Methodology

System architecture

A sequential pipeline from pair selection through signal generation, regime filtering, and portfolio accounting. Each stage is independently testable and documented across 29 versions.

pair selection
Engle-Granger cointegration on all ~45,150 pairs. ADF on OLS residuals, both directions, p < 0.05. Half-life filter 4–25 days. PCA strips 5 systematic factors (~58% variance); idiosyncratic residual cointegration adds a quality bonus. CUSUM and Hurst pre-filters. Quarterly re-selection.
spread construction
1-D Kalman filter estimates a time-varying hedge ratio βt. Spread = log P₁ − βt · log P₂, with β locked at entry so β drift can't be booked as P&L. Equal-dollar legs; P&L from realized log-returns.
signal rule
Rolling z-score with half-life-adaptive lookback. Entry |z| > 1.8, exit |z| < 0.5. Dynamic maximum hold = clamp(2.5 × half-life, 10–25 trading days).
regime gate
VIX bands: >30 → 0.5×, >40 → 0.25×. 63-day cumulative sector dispersion gate — low VIX with high dispersion → 0.4×. Hard skip when >20% of trailing 63 days were reduced-scale.
validation
19 walk-forward windows, 252-day train / 63-day test, rolling by one test window. Models retrained from scratch each window. No leakage between train and test periods.
03 — Results

Walk-forward performance

v29 figures, under realistic t+1 execution (fill on the bar after the signal). The out-of-sample row is the rigorous, leak-free forward estimate and the binding constraint — and under t+1 it collapses to essentially zero (the same-bar version showed +0.49%/qtr; the difference was look-ahead).

PeriodWindowsAvg return / qtrSharpeWin rateProfitable
In-sample (W1–W9)9+2.52%5.0883.7%9/9
Out-of-sample (W10–W19)10+0.08%0.0862.1%4/10
Main backtest (Jul 2023–2025)+0.90%0.5058.5%

Is the edge real?

The pipeline doesn't just report a Sharpe — it tests whether the Sharpe is distinguishable from zero (significance.py). It is not: every t-stat is below 1, every bootstrap CI includes zero, and the Deflated Sharpe (which penalises for the number of trials) is near zero out-of-sample.

TestMain backtestOut-of-sample (stitched daily)
Annualised Sharpe0.500.14
Newey-West t-stat (Sharpe ≠ 0)0.70 (p=0.49)0.21 (p=0.83)
Probabilistic Sharpe P(SR>0)78%58%
Bootstrap 95% CI on Sharpe[−0.96, +1.93][−1.09, +1.59]
Deflated Sharpe (vs best-of-27 trials)11%3.6%

Per-window OOS test: mean +0.08%/qtr, t-stat 0.22, p=0.83, 4/10 positive, 95% CI [−0.54%, +0.79%]. Under realistic execution there is no statistically significant edge — and the project proves that to itself rather than asserting otherwise.

Does it beat the textbook?

Gatev (2006) distance method and a random-pair control, run on the same universe and out-of-sample period (benchmark.py). The pipeline crushes random selection and wins decisively on risk-adjusted return.

StrategyReturnSharpe
Cointegration + Kalman (this project)+0.90%0.50
Distance method (Gatev 2006)+1.82%0.16
Random-pair control (avg of 5 draws)−7.69%−0.35

Multiple-testing check (Benjamini-Hochberg FDR): of 37,546 pairs tested, 6,052 are "cointegrated" at raw p<0.05 — but ~1,877 of those are expected false positives by chance, and zero survive BH-FDR at q<0.05 (8 at q<0.10). The cointegration signal is far weaker than the raw p-values suggest.

04 — Controlled ablation

ML contribution: ≈ 0, confirmed by a seed-robustness check

A transformer-based signal-quality scorer is trained (leak-free, per window) on whether an entry reaches its exit band, and used for opportunity ranking. It trains correctly — BCE falls below the coin-flip entropy, so it genuinely discriminates. Yet the main backtest and all five cost profiles do not depend on it by construction: the score only reorders same-day opportunities, and the sparse main backtest never has enough competing pairs on one day for the ordering to matter. The definitive ML-contribution test is the four-seed robustness check below (run on the v26.1 codebase): one training seed showed an OOS gain (+0.74%/qtr), but across seeds {42,1,2,7} it dissolved into noise — the OOS spread (0.30–0.74%/qtr) is larger than the mean effect, with one seed below the classical baseline. The v27 audit fixes touch neither the transformer training nor the ranking mechanism, so that conclusion stands.

MetricClassical only+ TransformerΔ
Main backtest return / Sharpe (v29)+0.90% / 0.50+0.90% / 0.500
Walk-forward OOS, 4-seed mean / range (v26.1)+0.36%/qtr+0.53%/qtr (0.30–0.74)noise
Institutional cost profiles (5)independent of the scorer by construction0

PAIRS_USE_TRANSFORMER=0 disables the scorer · seeds {42,1,2,7} · reproducible on any machine

05 — Research notes

Selected documentation

The engineering log records every version, bug, and failed hypothesis from v6 to v29. Selected research notes below.

06 — Disclosure

Honest assessment

Negative results are reported in full.

Where the effort actually went: training the model was maybe 2% of this project. The other 98% was evaluation and data — the significance tests, the leakage audit, and a survivorship-bias hunt that mattered more than any architecture. No model lowers the noise floor set by the information in the data (the Bayes limit; in markets, the efficient-market wall), and the evaluation here showed the signal sits at that floor. The job is to measure the ceiling honestly, not to pretend an architecture can raise it.

What the data shows
The honest bottom line (v29): under realistic t+1 execution there is no statistically significant edge. Filling on the bar after the signal (instead of the same close that generated it) collapses the out-of-sample return from +0.49%/qtr to +0.08%/qtr — most of the apparent edge was same-bar look-ahead. Significance testing confirms it: OOS Sharpe 0.08, Newey-West t-stat 0.21 (p=0.83), bootstrap 95% CI [−1.09, +1.59] (includes zero), Deflated Sharpe 3.6%; the per-window OOS test gives p=0.83 with 4 of 10 windows positive. The conclusion is robust to the fill convention — under the standard t+1-open fill the OOS is actually −0.28%/qtr (slightly worse), so it isn't an artifact of one pessimistic choice. A Benjamini-Hochberg multiple-testing correction is just as blunt: of 37,546 pairs tested, ~1,877 of the 6,052 "cointegrated" at raw p<0.05 are expected false positives, and zero survive at q<0.05. The methodology is nonetheless sound: the pipeline beats a random-pair control decisively (−7.7%) and the textbook Gatev (2006) distance method on a risk-adjusted basis (Sharpe 0.50 vs 0.16). Earlier audits corrected bugs in both directions (a v26 sign error that understated the cost comparison; nine v27 fixes including a half-enforced concentration limit). The transformer contributes ≈0 (four-seed check). Known limitations, all of which bias upward on an already-null result: the universe is sourced from ~current Russell 3000 membership (survivorship bias — of 36 names that delisted/failed/were acquired in 2020–2025, only 1 is present), and the walk-forward's in-sample windows trade a universe selected with look-ahead (so their high Sharpe is diagnostic only; the leak-free windows are the ~0 result). Both push the true edge at or below what is reported, so the negative conclusion is conservative. The value here is a rigorously validated research framework — one disciplined enough to prove the edge isn't significant — not a deployable alpha. Every claim is derived from logged, reproducible runs.
07 — Research roadmap

What I'd test next, with data and capital

None of these is promised to produce alpha. Each is the specific, falsifiable experiment that would either confirm the null is real or locate an edge the free-tier study could not reach — and each maps one-to-one onto a limitation disclosed above. This is the difference between "give me resources and I'll figure it out" and knowing exactly what the next experiment is and why.

survivorship-free data
Re-run the entire study on a point-in-time, delisting-inclusive universe (CRSP / Compustat) to eliminate the survivorship bias documented above. Because every known bias points up on a null, the first falsifiable question is whether the edge is genuinely zero or merely masked by a clean-sample artifact. Cost: a data licence, not new modelling.
breadth at scale
Trade hundreds of cointegrated pairs simultaneously under portfolio-level optimisation (risk-parity / constrained mean-variance) instead of ~40 near-sequential bets. By Grinold's law, IR = IC · √breadth — a small information coefficient only becomes a book at scale, and the risk controls that keep this backtest honest also cap breadth far below what a deployable strategy needs.
more forecastable targets
Point the same significance + walk-forward + leakage-audit machinery at volatility and covariance forecasting, where genuine out-of-sample predictability exists (Gu, Kelly & Xiu, RFS 2020), rather than decayed price-spread mean reversion. The infrastructure transfers directly; only the target changes.
execution & capacity
Add a market-impact and borrow-availability model plus forward paper-trading, to estimate real capacity at size and confirm out-of-sample behaviour in live time before a dollar of capital is risked.
08 — Engineering

Stack and reproduction

Versions
v6 → v29
29 iterations · every bug documented
Stack
Python 3.12 · PyTorch 2.7
statsmodels · scikit-learn · yfinance
Universe
Russell 3000
2,542 symbols · 2020–2025 · NY tz
Reproduce
python3.12 -m pairs_trading.main
PAIRS_USE_TRANSFORMER=0 python3.12 -m pairs_trading.main
PAIRS_FILL=open python3.12 -m pairs_trading.main