Backtest framework
The empirical engine. Rigorous, conservative, and designed to avoid the classic backtesting traps.
Point-in-time membership where possible; survivorship-bias minimised.
19 years covering GFC, EU debt crisis, COVID, AI rally.
Month-end signals, daily P&L tracking until next rebalance.
Fundamental data only used after the 10-K publication date.
Concentrated enough for conviction, diversified enough for stability.
Higher-quality stocks get larger weights.
A note on the backtest universe (and why we can't replay the Russell 3000)
The +13.7% annualized return, 0.73 Sharpe, −31% max drawdown come from the historical backtest 2007-2026, run on a point-in-time US equity sample (~5,000 firm-years) sourced from SimFin. This sample includes delisted and bankrupt tickers (no survivorship bias) and is broader than the S&P 500 (which is the comparison benchmark, not the investable universe) yet narrower than the strict Russell 3000.
Why not the strict Russell 3000 backtest? Reproducing the exact Russell 3000 historically would require the point-in-time index constituents list — i.e. who was in the index on every single rebalance date going back to 2007. That dataset is proprietary (FTSE Russell, ~$10k+/year). Free sources only give the current membership, which would bake in survivorship bias. We accepted SimFin's slightly different sample as the closest bias-free alternative.
The live forward portfolio (visible on /live) runs on the Russell 3000 from today onward, fed by free SEC EDGAR fundamentals (which reach back to 1993 via XBRL, so the forward will be reproducible). Its track record starts now and will accumulate month by month.
Why monthly, not weekly?
Three reasons, all academic:
- Data frequency. Fundamental data (revenue, earnings, balance sheet) is published quarterly or annually. Reshuffling weekly does not gain new fundamental information — it just adds noise.
- QMJ paper convention. Asness, Frazzini & Pedersen (2019) — and the broader Fama-French / Carhart factor literature — use monthly rebalancing. Sticking to this makes results directly comparable with published research.
- Transaction costs. A weekly turnover would multiply the number of trades by 4-5×. For a retail implementation (5-15 bps per round-trip), this would eat 50-100 bps of annual return — wiping out a chunk of the alpha.
Daily or intraday rebalancing would be even worse: momentum signals are slow-moving by design (12-month window minus the last month). Quality signals are even slower (annual fundamentals). The monthly cadence matches the data, not the news cycle.
Bias prevention
- ✓Look-ahead bias: fundamentals used with a 2-month publication lag; momentum uses prices strictly before the signal date.
- ✓Survivorship bias: delisted tickers retained in the universe where data is available.
- ✓Data-snooping: parameters fixed ex-ante from the QMJ paper; no walk-forward optimization.
- ✓Outliers: cross-sectional rank z-scores rather than raw values—robust to fat tails.
- !Transaction costs: not modelled. The reader should subtract ~10-25 bps/year for a retail implementation, less for institutional.