Survivorship bias: testing only on stocks that still exist today (ignoring delisted failures). Look-ahead bias: using data that wasn't available at the time of the decision. Both make backtests look better than reality.
1,000 funds with no skill at all, each year closing the worst 10% of those still alive. After five years 590 survive. Across all funds the average annual return is 0.26% — zero, as it should be. Across the survivors it is 2.16%. A database of today’s funds reports skill that never existed.
- Survivorship hides in index constituents, delisted stocks and closed funds; the data vendor’s history must include the dead.
- The bias is largest exactly where returns are most volatile.
- Selection on success happens in research too: only working strategies get written up.
rng = np.random.default_rng(13)
funds, years = 1_000, 5
returns = rng.normal(0.0, 0.10, (funds, years)) # no fund has any skill
alive = np.ones(funds, bool)
for t in range(years): # each year the worst 10% of survivors close
cut = np.quantile(returns[alive, t], 0.10)
alive &= ~(returns[:, t] < cut)
all_avg, survivors_avg = returns.mean(), returns[alive].mean()Assumes import numpy as np and import pandas as pd (and SciPy where imported). Each snippet simulates or makes up its own data, as the comments say.
The same idea with a library
# Checklist — is your backtest honest? # 1. Does your universe include delisted stocks? # 2. Are you using point-in-time data? # 3. Are fundamentals lagged by reporting delay? # 4. Is there any future information leaking? # 5. Did you optimise parameters on the test period? # 6. How many strategies did you test? (data snooping) # Point-in-time fundamental data # Use 'as_of' date columns, not 'period_end' df = df[df['report_date'] <= df['trade_date']]
- S. J. Brown, W. Goetzmann, R. G. Ibbotson & S. A. Ross, “Survivorship Bias in Performance Studies”, Review of Financial Studies 5(4), 1992
- E. J. Elton, M. J. Gruber & C. R. Blake, “Survivor Bias and Mutual Fund Performance”, Review of Financial Studies 9(4), 1996
Last reviewed October 2026 · How this site checks its content · Report a mistake
1. You backtest a strategy over 20 years on today’s S&P 500 members. What bias does this introduce?
Show answer
A. Today’s index is a list of winners. A fair test uses the members as they were on each date.
2. A fund database lists the average past return of funds that exist today. Why is it too high?
Show answer
A. Studies of mutual funds find that ignoring dead funds raises measured average returns noticeably — the losers are exactly the ones that disappear.
3. A backtest uses quarterly earnings dated at the quarter’s end, although they are published weeks later. The problem is:
Show answer
A. Use point-in-time data: each value stamped with the date it became known, not the period it describes.
- Pattern EssaysSurvivorship BiasWe study what survived and quietly forget everything that did not
- MLOps & Production MLData Quality GatesAutomated checks that stop bad data before it reaches your model
- MLOps & Production MLFeature StoresCentralized feature management with online/offline consistency
- MLOps & Production MLReproducibilityEnsuring any result can be replicated exactly
- The ToolkitCohort & Retention AnalysisGroup users by when they arrived, track them over time — the retention heatmap
- The ToolkitCorrelation, Causation & Simpson's ParadoxConfounders, spurious correlations, and trends that reverse when you split the data
- Timeseries EngineeringCross-Validation for TSNever shuffle time series