⚠️ For Educational Purposes Only — Nothing on this website constitutes financial or investment advice. Always do your own research.
2026-07-27 · 9 min read

15-Minute Divergence — The 1-Year Refresh on 5,073 Trades

Two months after the first intraday backtest, the same strategy re-run on a 4.5× larger sample: 5,073 trades across 144 symbols. The noise-stop fix worked, the profit factor held at 1.50× — and the data says this is not a day-trading strategy at all.


Why Re-Run It

The first 15-minute divergence backtest covered 1,116 trades and ended with a specific diagnosis: 41.3% of trades were stopped out on the very first bar after entry. The structural stop — placed at the divergence pivot candle’s low minus a cent — was routinely tighter than the natural range of a 15-minute bar. The trade thesis was fine. The stop was inside the noise.

The proposed fix was an ATR stop floor: never place a stop closer than a fixed fraction of ATR14, regardless of where the pivot sits.

That fix has been in the config since late May. This post re-runs the strategy over a fresh full year of 15-minute IBKR bars and asks three questions:

  1. Did the stop floor actually reduce first-bar stop-outs?
  2. Does the edge survive on a sample 4.5× larger?
  3. What does the bigger sample say that the smaller one could not?

The short version: yes, yes, and something uncomfortable about what this strategy actually is.


The Sample

Backtest Scope
Period
24 Jul 2025 → 23 Jul 2026
251 trading days
Bar Size
15 minutes
IBKR historical data
Universe
144 symbols
NASDAQ 100 + liquid large caps
Trades
5,073
5,015 BUY · 58 SELL

That BUY/SELL split is the first thing worth staring at. 98.9% of trades were long. The SPY regime filter suppresses short entries while SPY trades above its 200-day EMA, and over this particular twelve months SPY was above it almost continuously. So this is not a test of a long/short divergence system. It is a test of a long-only divergence system during a bull market, and every number below carries that asterisk.


Headline Results

Profit Factor
1.50×
was 1.42× on 1,116 trades
Win Rate
31.4%
1,594 winners / 5,073
Average Trade
+0.22R
+$37 per trade
Net P&L
$187,830
gross, before costs
Max Drawdown
$12,613
peak-to-trough on closed trades
Winning Days
59.4%
149 of 251 sessions

A profit factor of 1.50× on 5,073 trades is a more trustworthy number than 1.42× on 1,116. Sample size matters more than the headline value: at n=5,073 a profit factor of 1.50 is unlikely to be an artefact of a handful of lucky trades. It is, however, still thin. Every dollar of profit is accompanied by two dollars of loss.

A note on the Sharpe ratio I published last time

The previous post led with a Sharpe of 2.99 and compared it to institutional benchmarks. That framing was wrong, and this larger dataset makes the reason obvious.

The backtest engine opens a position for every valid signal. Over this run it held up to 30 positions simultaneously, with a median of 4 open at any time. The live configuration caps concurrent positions at 3. A Sharpe ratio computed on daily P&L from an unconstrained-concurrency simulation measures the smoothness of a portfolio nobody could actually hold — it flatters itself by diversifying across more simultaneous bets than the risk rules permit. Run the same daily-return calculation on this dataset and it produces a Sharpe above 5, which should be read as a red flag about the methodology rather than a discovery about the strategy.

Trade-level statistics — profit factor, expectancy in R, drawdown in R — do not have this problem. Those are what this post leads with.


Did the Stop Floor Work?

First-Bar Stop-Outs
41.3%
Before — pure pivot stop
29.2%
After — 0.5×ATR14 stop floor
1,479 of 5,073 trades still exit on the first bar. The floor cut the rate by roughly a quarter — a real improvement, not a solved problem.

The fix helped and it did not finish the job. A 0.5× ATR14 floor is half of what the original analysis recommended (1.0× ATR14). Nearly three trades in ten still die inside the first fifteen minutes, which suggests the floor is still calibrated below the noise band it is supposed to clear.

Widening the floor is not free, though. A wider stop means fewer shares for the same dollar risk, which shrinks every winner proportionally. The open question — and the next thing worth testing — is whether the trades rescued by a 1.0× floor pay for the size that all the other trades give up.


Where the Money Comes From

Exit Breakdown — 5,073 trades
🛑 Stop Loss3,065 trades (60.4%) — avg –0.64R — $–331,094
🎯 Full Target410 trades (8.1%) — avg +4.62R — $+320,093
📈 Trailing Stop793 trades (15.6%) — avg +1.40R — $+183,741
🌙 EOD Flat755 trades (14.9%) — avg +0.11R — $+13,057
⏱ Time Stop50 trades (1.0%) — avg +0.23R — $+2,033
1,203 target and trailing-stop exits (23.7% of trades) produce $503,834. Everything else nets $–316,004.

The shape is the same as the smaller sample, with one improvement worth naming: the stop-loss bucket fell from 72.1% of trades to 60.4%, and trailing-stop exits rose from 10.3% to 15.6%. More trades are surviving long enough to trail. That is exactly what a wider stop floor is supposed to do.

The distribution remains brutally fat-tailed. The best 5% of trades generate 49.5% of all gross profit. Miss those 254 trades — through a platform outage, a position cap, a day off, a hesitation — and the strategy is a losing system. 11.4% of trades close above +2R; the median trade closes at exactly 0.00R.


The Uncomfortable Finding

The strategy is configured as a day-trading system. flat_by_eod: true, no entries after 15:30 ET, everything closed by 15:45 ET. That is the stated design.

Split the results by whether the trade actually closed on the day it opened:

Same-Day vs Multi-Day Hold
–$129,370
3,474 same-day trades · 22.7% WR
Average –0.22R per trade
+$317,201
1,599 held past the close · 50.5% WR
Average +1.18R per trade
Every dollar of profit in this backtest comes from positions that were still open when the session ended. The intraday portion of the strategy loses money.

This reproduces, on a 4.5× larger sample, the single most important finding from the first run. It is no longer plausibly noise.

The honest reading is that the divergence signal on 15-minute bars is not an intraday mean-reversion signal. It is a swing-entry timing tool that happens to be computed on intraday data. The 15-minute chart is good at identifying where momentum has failed. It is not good at telling you that the resulting move will complete within the same session — and the six-and-a-half hour window is simply too short for a 4×ATR target to fill.

That creates a direct conflict with the strategy’s own risk design. Holding overnight means gap risk, which is precisely what the flat_by_eod rule exists to eliminate, and what the earnings-blackout filter exists to control. The version of this strategy that makes money in backtest is the version that carries exactly the risk the configuration was written to avoid.

There is no clean resolution here. Either the strategy accepts overnight gap exposure and is honestly relabelled as a swing system with intraday entries, or it stays flat-by-EOD and the backtest says it loses money. Choosing the first option means re-testing everything with an overnight gap model and a much smaller position size. Choosing the second means the signal needs a different exit framework entirely.


What Position Limits Do to the Numbers

The $187,830 headline assumes every signal gets taken. It does not survive contact with a real risk cap.

Re-running the same trade list under a first-come, maximum 5 concurrent positions rule — closer to the playbook’s 3–5 limit — gives:

3,455
trades taken (68% of signals)
$109,428
net P&L (58% of unconstrained)
1.42×
profit factor
Capping concurrency removes a third of the signals and 42% of the profit. Which specific signals get dropped is arbitrary — first-come is one rule among many, and a different tie-break would give a different number.

This is the gap between a backtest and a tradeable system, and it is worth stating plainly: a position cap is not a minor haircut on backtest results. In a fat-tailed strategy where 5% of trades carry half the profit, any rule that arbitrarily drops a third of signals is a coin flip on whether the surviving set still contains the tail.

⚠️ These are gross backtest figures. They exclude commission, exchange fees, bid-ask spread, slippage, and partial fills. At 5,073 round-trip trades, even $2 per round trip removes roughly $10,000. The strategy is in research, not paper trading and not live. Nothing here is a recommendation.

What Changes Next

1. Raise the ATR stop floor to 1.0× and re-measure. 29.2% first-bar stops is still too high. Test whether the rescued trades outweigh the size given up across the whole book.

2. Stop reporting Sharpe on unconstrained-concurrency runs. Position-capped equity curves, or nothing. The metric was doing more harm than good.

3. Decide what this strategy is. The same-day / overnight split has now appeared twice on independent samples. Continuing to describe a system as intraday when 100% of its profit comes from overnight holds is not a modelling choice, it is a labelling error.

4. Re-test on a bear or sideways regime. 5,015 of 5,073 trades were long, during twelve months of SPY above its 200-day EMA. This backtest contains essentially no information about how the strategy behaves when that changes — and a long-only signal validated only in a bull market is the most common way a backtest lies.

5. Model the position cap inside the backtest engine, not afterwards. Post-hoc filtering of a completed trade list is an approximation. The engine should refuse signals when the book is full, so sizing and equity compound correctly.

The edge appears to be real — a 1.50× profit factor across 5,073 trades and 144 symbols is not nothing. But it is a swing edge wearing an intraday costume, it depends on tails that a position cap may well remove, and it has never been tested outside a bull market. That is three unanswered questions, and none of them get resolved by running the same backtest again.