Most write-ups of a trading strategy show you the version that worked. This one shows you the whole thing — including the forty-five minutes where we thought we'd found a monster and were wrong. We built it live, in one sitting, on Light Water's open-source July backtester, and we left the mistakes in because the mistakes are the lesson.
The premise was a classic piece of technical-analysis folklore: RSI divergence. When price makes a lower low but the 14-period RSI makes a higher low, that's a "bullish divergence" — momentum is quietly improving even as price drops, supposedly a bottoming signal. The mirror image — price higher high, RSI lower high — is a "bearish divergence." The rule we set out to test was as simple as it gets: buy the bullish divergences, sell the bearish ones. Weekly bars, the full Nasdaq 100, an ATR-based stop loss, priced with Polygon data as far back as it would give us.
The +444% That Wasn't
The first run looked spectacular.
A profit factor of 2.5. A walk-forward test that held up out-of-sample. A Monte Carlo verdict of "Robust." If you stopped reading the report at the top table, you'd have called this a winner and moved on to position sizing.
But two numbers underneath didn't fit. The equity curve's "smoothness" score came back ROUGH — long flat stretches, a drawdown that stayed underwater for over 600 days. And the win rate was only 38%. A strategy that wins a third of the time but returns 444% is, by definition, living or dying on a handful of enormous trades. So we asked the obvious question: what happens if we remove the biggest winners?
Removing the Winners
We pulled the trade log and sorted by profit. The concentration was extreme — not "a few big winners help," but "a few big winners are the strategy":
| Trades removed | Remaining return | Share of all profit |
|---|---|---|
| Top 1 winner | +192% | 57% |
| Top 3 winners | +72% | 84% |
| Top 5 winners | +16% | 96% |
| Top 10 winners | −66% | 115% |
One trade was 57% of all the profit. Remove five, and the whole 444% collapses to 16% — worse than a savings account. Remove ten, and the strategy is a net loser. That is not a strategy; that's a lottery ticket that happened to hit.
So we looked at the two winners doing all the work. This is where it stopped being a story about strategy design and became a story about data:
The culprit was a single config setting: price_adjustment: "none". We had pulled raw, unadjusted prices. When a stock does a 20-for-1 split, the unadjusted series shows a price that looks like it fell 95% overnight — or, depending on which side of the split your bars land, a phantom 20x jump. Our divergence signal happily "bought" the artifact and the backtester dutifully booked a four-figure percentage gain. The engine wasn't broken. The data was lying, and we'd told it to.
A backtest is a measurement instrument. Before you trust what it says about your strategy, you have to trust what it says about your data. We learned that in the right order — the hard way, on camera.
Why Monte Carlo Said "Robust"
Here's the part that should bother anyone who leans on robustness statistics: the Monte Carlo test passed this strategy, artifacts and all. It scored "Robust." How?
Because of what Monte Carlo actually does. Our engine's version takes the realized set of trades and reshuffles their order a thousand times, rebuilding the equity curve from each shuffle, then asks whether the result was just luck in the sequencing. With a profitable bag of trades — and a bag containing a +2,005% trade is very profitable — almost any reshuffle stays profitable. The test passes nearly automatically.
But reshuffling the order throws away the one thing that mattered here: time and concentration. Monte Carlo can't see that the entire return came from two bars. It treats each trade as an interchangeable draw from a hat, so it is structurally blind to "all your edge is in two outliers." Walk-forward analysis "passed" for a related reason — the artifact trades happened to sit inside the out-of-sample window and inflated it.
The lesson isn't that these tests are useless. It's that they answer narrow questions. "Robust" here meant only "not undone by trade ordering." It never meant "real," "repeatable," or "not a data glitch." Robustness statistics are necessary, not sufficient — and they will confidently green-light a mirage.
The Honest Number
We flipped one setting — price_adjustment: "total_return", which uses split- and dividend-adjusted prices — cleared the cache so the fix actually took, and re-ran the identical strategy. The mirage evaporated:
| Metric | Unadjusted (fake) | Adjusted (real) |
|---|---|---|
| Total return | +444% | +14% |
| vs. Nasdaq 100 buy & hold | +351 pts | −79 pts |
| Sharpe ratio | 0.59 | 0.01 |
| Profit factor | 2.50 | 1.09 |
| Monte Carlo | Robust | Moderate Tail Risk |
The real strategy returned 14% over five years while simply holding the Nasdaq returned 93%. A profit factor of 1.09 is a coin flip that barely clears its transaction costs. This is the honest baseline: the raw idea has no edge. Which is exactly when the interesting work starts.
Trying to Build a Real Edge
The diagnosis was structural. Divergence is a mean-reversion signal — it bets on bounces. The Nasdaq 100 is a basket of momentum names that mostly grind higher. We were using a counter-trend tool to trade trend-following instruments, and then exiting on the opposite divergence, which chopped our winners off in the middle of their best runs. The tell was in the data: our best real trades were the ones that never triggered an exit at all.
So we built a second version with three changes:
1. A regime filter. Only take bullish divergences when the S&P 500 is above its 200-day average — buy dips inside uptrends, not falling knives in a crash. 2. A confirmation trigger. Don't act on the raw signal; wait for price to break back above the recent swing high first. 3. Let winners run. Stop exiting on the opposite divergence entirely; instead trail an ATR stop up behind the position and let the trend carry it.
| Metric | v1 (raw) | v2 (filtered) |
|---|---|---|
| Total return | +14% | +30% |
| Max drawdown | 37% | 12% |
| Profit factor | 1.10 | 1.66 |
| Calmar ratio | 0.07 | 0.43 |
| Trades | 290 | 88 |
Every risk metric improved, on a third of the trades. Max drawdown fell by two-thirds. The regime filter did precisely its job — the strategy took zero exposure during the high-volatility (VIX > 25) periods, sidestepping the crashes that had savaged v1. The concentration problem was gone; returns were spread across every year instead of hiding in two bars.
And it still lost to buy-and-hold. +30% versus the Nasdaq's +93%. We had built a genuinely better-behaved strategy — lower drawdown, positive expectancy, honest math — that a passive index fund still beat on raw return. That gap is the whole point, and we'll come back to it.
Then We Ran It on Daily
The natural next question on the stream was: does a faster timeframe help? We dropped from weekly to daily bars and re-ran both versions. It was clarifying — in the wrong direction for the raw idea.
| Run | Return | Max DD | Profit factor | Trades |
|---|---|---|---|---|
| Weekly — v1 raw | +14% | 37% | 1.10 | 290 |
| Weekly — v2 filtered | +30% | 12% | 1.66 | 88 |
| Daily — v1 raw | −25% | 46% | 0.89 | 1,426 |
| Daily — v2 filtered | +19% | 7% | 1.80 | 132 |
On daily bars the raw signal lost money — down 25% across 1,426 trades, a profit factor below 1. More bars didn't mean more edge; they meant more noise, more micro-signals, and more transaction costs with nothing to pay for them. The filtered v2 held up defensively — a remarkable 7% max drawdown — but it became so cautious it returned less than Treasury bills, which is why its Sharpe ratio went negative despite a positive return.
Across four clean runs, the verdict was consistent: the filters produced real risk control, and no timeframe produced a real return edge over just holding the index.
What We Learned
We didn't find a tradable strategy. We found something more durable — a checklist we'll apply to every idea that comes after this one:
Validate the data before the strategy. Always use split- and dividend-adjusted prices. A single wrong setting turned a break-even system into a phantom 444% winner. And watch your cache — ours keyed on the date range but not the adjustment setting, so the fix silently did nothing until we cleared it.
Set the benchmark bar first. The right question was never "did it make money?" It was "did it beat buying the Nasdaq?" Framed that way, every version we built failed the same test honestly — and that clarity is worth more than a flattering absolute number.
Robustness statistics answer narrow questions. Monte Carlo blessed a strategy that was 96% data artifact. It only ever tested trade ordering. Never mistake "passed the robustness check" for "is real."
Stress-test concentration on purpose. The single most revealing thing we did was delete the top winners and watch the return collapse. Do it to every backtest. If a strategy dies without its top five trades, you don't own an edge — you own a few lucky outliers.
Match the signal to the instrument. Counter-trend mean-reversion on momentum mega-caps is fighting the tape. The tool wasn't wrong; the hunting ground was.
Where does the idea go from here? If we keep pulling this thread, the honest next steps are a long-short version that trades divergence as a relative signal instead of fighting index beta, the same logic applied to market breadth rather than individual names, and a re-test on decades of history rather than the five years our data provider currently offers. v2's real talent was drawdown control — its most plausible future is as a defensive overlay, not a standalone return engine.
That's the unglamorous truth of systematic research: most ideas don't work, and the value is in finding out quickly, cheaply, and honestly. We did it live, in an afternoon, on open-source tooling anyone can download. The strategy was a dud. The process was the product.
Every run from the session, exported as a full PDF tearsheet — equity curve, drawdown, underwater plot, trade-by-trade log, and risk metrics. Nothing hidden, including the mirage.
Weekly — v1, unadjusted (the +444% mirage)The original run, before we caught the stock-split artifacts. PDF Weekly — v1, split-adjusted (the honest +14%)The same strategy on clean data — the real, break-even baseline. PDF Weekly — v2, trend-filtered (+30%, DD cut to 12%)Regime filter, breakout confirmation, and a trailing-stop exit. PDF Daily — v1, raw signal (−25%, 1,426 trades)What happens when a mean-reversion signal meets a noisier timeframe. PDF Daily — v2, trend-filtered (+19%, 7% max drawdown)The most defensive run of all — and still below buy-and-hold. PDF
Leave a comment - join the conversation
Have you caught a backtest lying to you? Share your data-quality war stories, or tell us where you'd take the divergence idea next.
Comment on LinkedIn