Random signals can look great
Each grey line is ten years of a strategy with zero true edge: random scores, real-looking volatility.
The orange one is simply the best of 25. Shown alone, it would pass for a decent strategy.
Signal research for alpha · Page 5 of 6
Every number so far came from one history. Monte Carlo builds thousands of histories that could have happened, so you can see where yours falls among them: what luck looks like, how wide the uncertainty is, what a normal bad year looks like, and whether your pipeline can be trusted.
The null
Simulate strategies that have no edge by construction. Their spread is the yardstick for yours.
Each grey line is ten years of a strategy with zero true edge: random scores, real-looking volatility.
The orange one is simply the best of 25. Shown alone, it would pass for a decent strategy.
Simulate 1,000 no-edge strategies and plot their Sharpe ratios. This is the null distribution: what ten years of pure luck produces.
Most land near zero, but the tails reach further than intuition suggests.
Residual momentum's Sharpe of 0.9 sits far in the right tail. The share of null runs at or above it is the p-value.
Judged as a single test, it's very unlikely to be luck.
The best of those 1,000 random strategies is marked too. It's close to the real signal, and can beat it.
This is page 4's multiple-testing problem, seen directly. Searching enough noise finds something as good as your discovery.
The bootstrap
A Sharpe ratio is an estimate from one sample. Resampling that sample shows how far the true value could be from it.
Take the 120 monthly returns and draw 120 of them at random, with replacement. Compute the Sharpe. Repeat 2,000 times.
Each draw is a history that's just as consistent with the data as the one you saw.
The middle 95% of those resampled Sharpes is the confidence interval. Here, ten years of a 0.9 Sharpe gives about 0.25 to 1.65.
The interval excludes zero, but it's wide. "Sharpe 0.9" really means "probably somewhere between a quarter and one and a half."
The interval shrinks with the square root of time. Slide the track record down to three years and zero is back inside it.
A plain bootstrap assumes each month is a fresh draw. Momentum returns cluster in regimes and crashes, so that assumption understates the uncertainty.
The cone
Simulate many futures for a signal whose edge is real. The spread tells you which drawdowns are normal and which mean it's broken.
Here is five years of a strategy with a true Sharpe of 1.0 and 10% annual volatility. Its edge is real by construction.
It still has stretches that look like failure.
Simulate 500 futures with the same edge. The shaded bands hold the middle 50% and 90% of outcomes at each month.
Even a real Sharpe of 1.0 can be flat after two years. Losing roughly one calendar year in six is normal.
Drag the true Sharpe and watch the cone and the drawdown statistics move.
The orange line is a live track record after launch. It's down for most of its first year and alarming on its own.
Against the cone it sits inside the 90% band, so it's consistent with the backtest. Turning it off here would be selling at the bottom of a normal drawdown.
The calibration
Build fake data where you know the answer, run your real pipeline on it, and check that it finds exactly what you planted.
Simulate 300 stocks for 60 months where scores predict returns with a planted IC of 0.03. Run the exact code you use on real data.
Each dot is one run. If the pipeline is sound, the dots scatter around the diagonal: what you recover matches what you planted.
Now plant an IC of zero. A sound pipeline should find nothing, and the dots should center on zero.
This is the false-positive check. It catches more bugs than any amount of staring at code.
Switch on a common bug: the score accidentally includes part of the month it's predicting, as when the skip month is dropped.
With nothing planted, the pipeline "finds" an IC far above anything real. Page 3's rule of thumb, that an IC of 0.20 usually means a bug, is this.
Change the planted IC and toggle the bug. Each change runs fresh simulations in the page.