The one-sentence version
Academia and industry have "discovered" hundreds of factors, a phenomenon jokingly referred to as the Factor Zoo. The problem is: when everyone repeatedly searches for patterns in the same historical data, using the conventional standard of "t-statistic greater than 2 is significant," a large number of "significant" factors will emerge purely by chance. The solution is to acknowledge how many attempts were made and raise the threshold accordingly: Harvey, Liu, and Zhu (2016) suggest that the t-statistic for a new factor should be at least greater than 3; the Deflated Sharpe Ratio proposed by Bailey and López de Prado incorporates "the number of attempts" directly into the significance testing of the Sharpe Ratio.
Disclaimer
This article is for technical popularization only and does not constitute any investment advice. The code in this article uses simulated data.
Layer 1: The Intuition
1.1 The Coin-Tossing Champion
Have 1,000 people each flip a coin 10 times and record the number of heads. Almost certainly, someone will flip 9 or 10 heads. Are they a "coin-tossing genius"? Clearly not; it is simply a matter of having enough people so that someone will eventually get an extreme result by chance.
In quantitative research:
- A researcher tests 100 factors, each using a 5% significance level;
- Even if all factors are useless, there will be an average of 5 "significant" ones;
- If only these 5 are reported, 5 false discoveries have been created.
1.2 The Factor Zoo
| Phenomenon | Description |
|---|---|
| Quantity Explosion | Harvey, Liu, and Zhu compiled over three hundred published factors in their 2016 paper, and the number continues to grow |
| Replication Crisis | Subsequent large-scale replication studies found that a significant portion of published factors cannot be replicated under stricter testing, longer samples, or updated data |
| Publication Bias | Significant results are easier to publish, while non-significant results are "put in a drawer," and no one knows how many times the world has actually tested them |
| Post-publication Decay | Research shows that factor returns significantly decline after publication, partly because the original results contained luck, and partly because they are being arbitrated by the market |
Layer 2: Correction Methods
2.1 Raising the t-statistic Threshold
| Method | Approach | Characteristics |
|---|---|---|
| Bonferroni | Conducted tests, significance level changed to | Most conservative; controls the probability of "at least one false positive" |
| Holm | A stepwise improvement of Bonferroni | Slightly more relaxed, but also controls false positives |
| BHY / FDR | Controls "the proportion of false discoveries among all results declared significant" | More suitable for exploratory research |
| Harvey–Liu–Zhu Threshold | Considers the total number of tests in the entire field | Suggests t > 3.0 for new factors |
Increasing the t-statistic from 2 to 3 might not sound like much, but the corresponding p-value drops from approximately 0.05 to approximately 0.003, making the requirement over ten times stricter.
2.2 Deflated Sharpe Ratio (DSR)
Significance testing for the Sharpe Ratio needs to consider three things:
- Number of attempts: The more attempts made, the higher the maximum Sharpe Ratio found within the noise;
- Sample length: The shorter the sample, the less reliable the Sharpe estimate;
- Shape of the return distribution: Strategies with negative skewness or fat tails have overestimated Sharpe Ratios.
The logic of DSR is: first calculate "what the expected maximum Sharpe Ratio is among pure noise attempts" (), and then test whether the observed Sharpe is significantly higher than :
Where is the variance of the Sharpe Ratios across the attempts, is Euler's constant, is the skewness and kurtosis of the returns, and is the sample length. DSR can be understood as "the probability that this strategy's true Sharpe Ratio is greater than zero."
Layer 3: Code Implementation
import numpy as np
from scipy.stats import norm, skew, kurtosis
EULER = 0.5772156649
def expected_max_sharpe(n_trials, var_sr):
"""Expected maximum Sharpe ratio under pure noise in n independent trials (Bailey & López de Prado)"""
return np.sqrt(var_sr) * ((1 - EULER) * norm.ppf(1 - 1 / n_trials)
+ EULER * norm.ppf(1 - 1 / (n_trials * np.e)))
def deflated_sharpe(returns, n_trials, var_sr):
T = len(returns)
sr = returns.mean() / returns.std() # Non-annualized (per-period) Sharpe
sr0 = expected_max_sharpe(n_trials, var_sr)
g3, g4 = skew(returns), kurtosis(returns, fisher=False)
z = (sr - sr0) * np.sqrt(T - 1) / np.sqrt(1 - g3 * sr + (g4 - 1) / 4 * sr ** 2)
return sr, sr0, norm.cdf(z)
rng = np.random.default_rng(3)
T = 252 * 3
r = rng.normal(0.0008, 0.01, T) # A "looks good" strategy
print("Annualized Sharpe:", round(r.mean() / r.std() * np.sqrt(252), 2))
for n in [2, 10, 100, 1000]:
sr, sr0, dsr = deflated_sharpe(r, n, var_sr=1 / T)
print(f"Trials {n:>5}: Max Sharpe from noise (annualized)={sr0*np.sqrt(252):.2f} DSR={dsr:.3f}")
Output:
Annualized Sharpe: 2.1
Number of trials 2: Max noise Sharpe (annualized)=0.30 DSR=0.999
Number of trials 10: Max noise Sharpe (annualized)=0.91 DSR=0.979
Number of trials 100: Max noise Sharpe (annualized)=1.46 DSR=0.862
Number of trials 1000: Max noise Sharpe (annualized)=1.88 DSR=0.645
(Here var_sr = 1/T is a simplified assumption: that the variance of the Sharpe estimates for each attempt is only the sampling error variance. In actual use, you should use the sample variance of the Sharpe Ratios of the actual strategies you have tested.)
3.1 Interpretation
Consider the same strategy with a three-year annualized Sharpe Ratio of 2.1:
| If it is... | Conclusion |
|---|---|
| The only attempt | Almost certainly real (DSR ≈ 1) |
| The best of 100 attempts | Still likely real, but pure noise can produce a maximum Sharpe of 1.46 |
| The best of 1,000 attempts | The expected maximum for noise has reached 1.88, DSR is only 0.65, highly suspicious |
The credibility of the same number depends on the process used to find it. This is why serious quantitative teams require recording every single attempt.
3.2 Engineering details
| Suggestion | Description |
|---|---|
| Record the number of attempts | Include all parameter combinations and all discarded ideas |
| Pre-registration | Write down the hypothesis, testing method, and passing criteria before looking at the data |
| Raise the threshold | New factor t > 3; use DSR instead of the raw Sharpe Ratio for decision-making |
| Require economic logic | Factors with a reasonable explanation are more likely to persist than those found through pure data mining |
| Test with new data | Check if it remains effective in new markets, new time periods, or new asset classes |
| Beware of automated mining | Machines and AI Agents can attempt tens of thousands of times overnight, magnifying the problem a thousandfold (see "Agent Factor Mining") |
Summary
| Layer | Key points |
|---|---|
| Problem | With too many attempts, "significant" factors can be found within the noise |
| Phenomenon | Factor Zoo: hundreds of factors, many unreplicable, post-publication decay |
| Correction | Bonferroni / Holm / FDR; t > 3; Deflated Sharpe Ratio |
| Principle | The credibility of the same number depends on the process used to find it; record every attempt |