Markets › Futures · ES futures
The RSI(2) Dip Buyer
Buys sharp dips in an uptrend, sells when price snaps back.
Buried · FragileSix years of buying dips. The luck was real; the edge never was proven.
Variants tried: 4 (2 original + 2 in Round 2) · Passed every gate: 0 · Holdout opened: yes (before the protocol existed)
Short answer: not in this test. We backtested The RSI(2) Dip Buyer on ES futures in 4 variants, net of costs, and 0 passed every gate. The best result, B, made +$26,102 over 412 trades but failed the validation profit factor, the development t-statistic and the random-entry control. “No proven edge” means a convincing edge was not demonstrated, not that none exists.How much costs took here, compared across all 54 of our tests →Did the same rules work on other markets? The cross-market scoreboard →
00The verdict in three lines
- The RSI(2) Dip Buyer is our name for the classic RSI(2) pullback idea: in an uptrend, a sharp short-term dip tends to bounce, so buy it and sell when price recovers.
- On 6.7 years of ES hourly bars, net of costs, the long-only version made +$26,102 on 412 trades, but the 95% range for the average trade runs from -$25 to +$153, so luck is still a live explanation. Take away its ten best trades and +$26,102 shrinks to +$2,872.
- It failed 3 of 6 gates: the validation period (PF 0.84), the t-statistic on development (1.26) and the random-entry control (91.6th percentile, needed 95th). Cause of death: Fragile
- Round 2 (added later): replacing the exit with a fixed 1.5 × ATR stop and 3 × ATR target did not help. It made both versions worse (+$25,243 fell to +$3,625, and +$26,102 fell to +$16,239), and neither passes.
01The claim
The RSI(2) pullback is a classic mean-reversion idea, popularised by Larry Connors and Cesar Alvarez in Short Term Trading Strategies That Work (2008): trade in the direction of the long-term trend, enter on an extreme two-period RSI, exit when price recovers. The original is for daily bars on stocks and indices.
We call our version The RSI(2) Dip Buyer: it buys sharp dips, measured by the two-period RSI, while the market is in an uptrend, and in one variant also sells sharp rallies in a downtrend. (Its internal code name is ESH1Rsi2Pullback, which is how it appears in the source files.) We test our own adaptation to 60-minute ES bars, not the book's daily rules. Nothing here says the original daily version fails. We test rules, not people. Discretionary parts: none, the rules are fully mechanical.
02The rules we tested (frozen 27 Sep 2026, protocol spec 7 Oct 2026)
- Entry: long when the close is above SMA(200) and RSI(2) is below 10. Short when the close is below SMA(200) and RSI(2) is above 90. Only on bars that close between 10:00 and 16:00 New York time. One position at a time.
- Exit: first of: close crosses SMA(5) against the trade; 24 bars after the entry bar; Friday 16:00 (no weekend holds); emergency stop at 3 × ATR(14) from the entry fill.
- Sizing: 1 ES contract.
- Variants declared up front: A = long and short. B = long only. Nothing was optimised or fitted.
The full dated specification is in the files at the bottom.
03Data and costs
| Period | Dates | Trades A | Trades B |
|---|---|---|---|
| Development | 2020-01-01 to 2023-12-31 | 416 | 249 |
| Validation | 2024-01-01 to 2025-03-31 | 115 | 65 |
| Holdout (already used) | 2025-04-01 to 2026-09-25 | 143 | 98 |
Costs: $5.76 commission per round trip and 1 tick ($12.50) slippage on every fill, including stops, on 1 contract.
Honest caveat on the holdout: the 2025-26 data was looked at in September 2026, before this protocol existed. It is reported, but it can't count as a clean holdout. The 2020-2024 data was run once, after the rules were fixed.
Engine check: we ported the NinjaTrader strategy to a custom engine so we could run the random-entry control. It reproduces the earlier NinjaTrader results: 499 of 499 trades on 2020 to 2024 (variant A) and 301 of 301 (variant B). On the 2025-26 windows it matches once the indicators are restarted at the window start, as NinjaTrader does.
Data: ES 1-minute, back-adjusted, 2020-01-01 to 2026-09-25. Gaps are holiday early closes and a handful of thin-market minutes. No raw vendor data is published.
04Results: every variant, net of costs
| Variant | Net, all | PF dev | t (dev) | PF val | PF holdout* | vs random | Top 10 removed |
|---|---|---|---|---|---|---|---|
| A: long + short | +$25,243 | 1.06 | 0.40 | 0.98 | 1.26 | 96.8th pct | -$12,825 |
| B: long only | +$26,102 | 1.24 | 1.26 | 0.84 | 1.36 | 91.6th pct | +$2,872 |
* Holdout already used before the protocol. PF = profit factor. "vs random" = percentile of the strategy's average net $/trade among 500 random-entry runs.
- Gross vs net: B gross +$38,775, net +$26,102. Costs took about a third, but it was still positive, so this is not a costs death.
- Longs vs shorts: in A, longs made +$26,102 (PF 1.20) and shorts lost $859 (PF 0.99). Shorts added nothing.
- Pain: B's worst drawdown on closed trades was -$9,921 (losses open inside a trade are not counted) and the equity curve spent up to 621 days below a previous high. A's longest stretch was 1,666 days.
- Confidence: B's average trade was +$63, with a bootstrap 95% range of -$25 to +$153, and an 8.0% chance that the true average is zero or negative. A's chance was 20.0%.
- By year (B): 2020 PF 1.39, 2021 1.37, 2022 1.10, 2023 1.14, 2024 1.04, 2025 1.43, 2026 (to September) 0.89. Positive in six of seven years, but the 2022-2024 stretch was thin.
- On a micro contract (MES): B's total result would be roughly a tenth, about +$2,600 over 6.7 years, or about $30 a month before tax.
05The curve
The strategy line stays inside the grey band in 77 of 81 months and pokes above its upper edge in only 4. It finishes at +$26,102, just under the top of the random range (the 95th percentile of random total net result is +$29,789, the median is -$2,046). The band is wide because a few dozen trades can swing the total by tens of thousands of dollars either way. A good-looking curve that stays inside the random band is what "can't beat the dice" looks like.
06The gates
Variant B (the better of the two):
- Profit factor ≥ 1.2 in validation (PF 0.84)fail
- ≥ 50 trades in each period (249 / 65 / 98)pass
- t ≥ 2.0 on development (1.26)fail
- Above the 95th percentile of random entries (91.6th)fail
- Positive without the 10 best trades (+$2,872)pass
- Holdout net positive, flagged as used (+$13,061)pass
Variant A failed gates 1, 3 and 5 (validation PF 0.98, development t 0.40, and -$12,825 without its top 10 trades). It passed gates 2, 4 and 6. It cleared the random-entry gate (96.8th percentile) because random long-and-short entries lose money with these exits, so it only beat a weak control: against a control that also matches the trend and dip state it sits at the 85th percentile (see the control check below).
Control check after review (added 8 Oct 2026)
An outside review asked whether our random control matches the signal. The frozen control enters at any eligible bar, on a random side, but the RSI(2) signal needs an uptrend (the close above its 200-bar average) and a dip (RSI(2) below 10, which in practice means the close is below its 5-bar average), and its exit, the close back above the 5-bar average, is already met on a random bar. We re-ran the comparison with two controls that keep the same exits and the same trade count: trend-matched (long only above the 200-bar average, short only below it) and trend and dip matched (also requiring the close to be below its 5-bar average for longs, above it for shorts: the signal's own state without the RSI(2) extreme).
| Variant | Frozen control (as published) | Trend-matched | Trend and dip matched |
|---|---|---|---|
| A | 96.8th | 95.8th | 85.4th |
| B | 91.6th | 98.6th | 90.2th |
| A2 | 76.8th | 81.4th | 85.0th |
| B2 | 71.6th | 82.6th | 94.8th |
Percentile of the average net per trade among 500 random runs, 95 needed. Percentiles move by a point or two between runs because the random trade count is calibrated to the real count. Code and output: rsi2_control_check.js, rsi2_control_check.txt.
What this changes. The random-entry result depends on the control, and not in one direction. Variant B (long only) is at the 91.6th percentile of the frozen control, the 98.6th of the trend-matched one and the 90.2th of the trend-and-dip one. Variant A (long and short) is at the 96.8th, 95.8th and 85.4th. Each version clears the 95th percentile only against a control that ignores the dip (A against the frozen and the trend-matched control, B against the trend-matched one), and neither clears it against the control that sits in the same kind of dip. Reading it carefully: being in a dip inside an uptrend explains a good part of the result, and the RSI(2) extreme itself has not been shown to add the rest. The Round 2 versions tell the same story: A2 and B2 are at the 85.0th and 94.8th percentile of the dip-matched control, both under the 95th.
What it does not change. The frozen gate results (including variant A's pass of the random-entry gate against the frozen control, which we had already called a weak control), the verdict and the cause of death. Both versions still fail the validation and the development t-statistic gates.
R2Round 2: a fixed stop and target (added after the first result)
Honest label: these variants were added after we saw the original results, so they are not pre-registered in the way the originals were. They are reported in full, counted in the total (4 variants tried: 2 original, 2 in Round 2), and judged by the same six gates. The original numbers above are unchanged.
After the first result we added one more way to exit. Instead of waiting for the price to recover to its 5-bar average (with a wide 3 × ATR emergency stop), Round 2 uses a fixed stop of 1.5 × ATR(14) and a fixed profit target of 3 × ATR(14), with the same 24-bar limit and no weekend holds. Two variants: A2 (long and short) and B2 (long only). The levels are conventional round numbers, declared in advance and never adjusted.
| Variant | Original net | Round 2 net | Trades | PF dev | t (dev) | PF val | PF holdout* | vs random | Top 10 removed |
|---|---|---|---|---|---|---|---|---|---|
| A2 | +$25,243 | +$3,625 | 746 | 1.05 | 0.40 | 0.93 | 0.97 | 76.8th | -$54,057 |
| B2 | +$26,102 | +$16,239 | 453 | 1.08 | 0.53 | 0.82 | 1.20 | 71.6th | -$20,221 |
Results in dollars, net of costs. * Holdout already used before this test. "Original net" is the net result of the matching original variant shown above.
Both got worse: net +$25,243 became +$3,625 for the long-and-short version, and +$26,102 became +$16,239 for long only. With a 2-to-1 reward-to-risk the win rate falls to about 36%, and 60% of A2 trades ended at the stop against 28% at the target. Both fail the validation gate and the random-entry gate, and B2 loses -$20,221 once its ten best trades are removed.
| Gate | A2 | B2 |
|---|---|---|
| PF ≥ 1.2 in validation | fail | fail |
| ≥ 50 trades per period | pass | pass |
| t ≥ 2.0 on development | fail | fail |
| Above 95th pct of random runs | fail | fail |
| Positive without top-10 trades | fail | fail |
| Holdout net positive (used) | fail | pass |
| Gates passed (all 6 needed) | 1 / 6 | 2 / 6 |
With 4 variants tried in total, the base development t-statistic bar of 2.0 still applies.
What this tells us: the stop and target combination tested here did not produce a variant that passed the protocol, and after costs it made every version we tried worse. A stop and target reshape the wins and losses of a trade rather than the entry signal. We tested one stop and target distance per strategy and did not test other distances or other exit types, so this does not show that no exit could help. The cause of death above stands.
FXOther markets: the same rules on four currency pairs (added 8 Oct 2026)
We ran this strategy's four variants, with the same rules and default parameters, on EURUSD, GBPUSD, USDJPY and AUDUSD (spot FX, 60-minute bars, 2004 to September 2026) under a specification dated before any result. Costs are about 1 pip per round trip (1.2 on USDJPY). The table shows each result in pips after costs and how many of the six gates it failed. This strategy is one of six in the full FX study.
| Variant | EURUSD | GBPUSD | USDJPY | AUDUSD | Pairs net positive | Pairs passing every gate |
|---|---|---|---|---|---|---|
| A (long and short) | +1,748 · 1 of 6 failed | -675 · 5 of 6 failed | -101 · 4 of 6 failed | -1,098 · 5 of 6 failed | 1 of 4 | 0 of 4 |
| B (long only) | +513 · 4 of 6 failed | -994 · 5 of 6 failed | +212 · 4 of 6 failed | -721 · 5 of 6 failed | 2 of 4 | 0 of 4 |
| A2 (long and short, stop and target) | -2,266 · 5 of 6 failed | -3,344 · 5 of 6 failed | -6,018 · 5 of 6 failed | -3,127 · 5 of 6 failed | 0 of 4 | 0 of 4 |
| B2 (long only, stop and target) | -317 · 5 of 6 failed | -2,908 · 5 of 6 failed | -3,312 · 5 of 6 failed | -514 · 5 of 6 failed | 0 of 4 | 0 of 4 |
16 variant-pair results, 0 passed every gate. 3 finished net positive after costs and 9 were positive before costs, so costs turned 6 of them into losses. The highest development t-statistic was 1.36 against the 2.5 required. The closest call was EURUSD A, which failed 1 of 6 gates (net +1,748 pips). On ES the verdict for this strategy was Buried · Fragile, and nothing here changes it.
07Cause of death
Fragile The long side has made money in most years, but not enough, and not consistently enough, to separate it from luck. The result leans on a small number of large winners. Remove the ten best trades and variant B is nearly flat; do the same to variant A and it turns clearly negative. The validation period, January 2024 to March 2025, lost money.
What we did not test: the original daily-bar version, other instruments, other RSI thresholds or trend filters (we deliberately didn't tune anything), a regime filter, and live execution quality. Stops use 1-minute bars, so intrabar order is approximated.
What would change our mind: a forward sample. 100 or more new trades on data we haven't seen, with a positive result and a track record above the random-entry band, would justify a re-test. This one has not yet earned real money. If you want to follow it, a simulator is the place.
TWhat this shows, and what to take into your own tests
What the results show
- The long-only version made $26,102 on 412 trades and was profitable in six of the seven years, so the idea is not obviously wrong.
- But the support is thin: the 95% range for the average trade runs from -$25 to +$153, the development t-statistic is 1.26, and without its ten best trades the profit falls from $26,102 to $2,872.
- Adding a fixed stop and target (Round 2) made both versions worse.
- The random-entry result is sensitive to the control. The long-only version ranks at the 92nd percentile against our frozen control, the 99th against a control that matches the uptrend, and the 90th against one that also matches the dip state (close below its 5-bar average).
What remains unknown
- Whether the original daily-bar version, which we did not test, behaves differently.
- Other markets, and other RSI thresholds or stops. We deliberately did not tune them.
- Live fills, which are usually worse than a backtest.
Why it failed
The edge, if there is one, is small next to the noise. The strategy trades only about 60 times a year, an average trade earns about $63 against about $31 of costs, and roughly nine tenths of the profit sits in ten trades. The 2024 to early 2025 stretch lost money, and the signal beat random entries only at the 91.6th percentile of our frozen control, below the 95th we require, and between the 90th and the 99th against controls matched on the trend and dip state of the signal.
What you can apply to your own tests
- Compare your signal with random entries that use the same exits. A profit number alone can come from the market rising.
- Remove your ten best trades and see what is left. If almost nothing is, the result is fragile.
- Split results by year and by period, not just in total.
- Put your average profit per trade next to your cost per trade before you trust it.
A note on the numbers: drawdown figures are measured on closed trades unless a table says it includes open losses. Open losses inside a trade are not counted in a closed-trade drawdown, so real account risk is higher, especially for systems with no stop. Backtests are not live trading.
FAQCommon questions
Does the RSI(2) pullback strategy work?
Not in this test. We backtested The RSI(2) Dip Buyer on ES futures in 4 variants, net of costs, and 0 passed every gate. The best result, B, made +$26,102 over 412 trades but failed the validation profit factor, the development t-statistic and the random-entry control. The random-entry gate is the control frozen before the run; each post's control check shows matched alternatives. “No proven edge” means a convincing edge was not demonstrated, not that none exists.
Does the RSI(2) pullback strategy work on forex?
We ran the same rules and default settings on EURUSD, GBPUSD, USDJPY and AUDUSD under a pre-registered specification. Of the 16 results, 3 finished above zero after costs and 0 passed every gate. Read the full forex study.
How much do trading costs matter for the RSI(2) pullback strategy?
We charged about $31 per round trip on ES. Across all 4 variants (2,285 trades) the strategy made +$141,496 before costs and +$71,209 after.
How was the RSI(2) pullback strategy tested?
On ES futures, with rules written and dated before the data was run, costs included on every trade, results split into development, validation and holdout periods, a random-entry control as the benchmark, and every variant reported. Read the protocol.
08Check our arithmetic
Round 2 files: round2_spec.md (dated before the run) · code: round2_rsi2.js, hourly_lib.js · r2_rsi2_results.txt · trade logs: A2, B2
Code provenance: our own code, written from the public rules. No third-party source code is used or published.
Full console output: rsi2_results.txt and rsi2_control_check.txt (control check, added 8 Oct 2026).
09Corrections
7 Oct 2026: renamed from "The Rubber Band" to "The RSI(2) Dip Buyer", because "rubber band" is also the name of a Bollinger Band or Keltner Channel setup that we did not test, and the old title could mislead. The attribution of the RSI(2) pullback idea to Connors and Alvarez (2008) was checked against published descriptions of their rules. No result or rule changed. Also 7 Oct 2026: added the "What this shows, and what to take into your own tests" section and a note that drawdown is measured on closed trades. No result changed. Also 7 Oct 2026: drawdown and worst-loss figures are now labelled as closed-trade or including open losses. No result changed. 8 Oct 2026, after a second outside review: the Round 2 sentence saying a stop and a target “can't create an edge” was replaced with a statement limited to the combination tested here, which did not produce a variant that passed the protocol; other distances and exits were not tested. No result changed. Also 8 Oct 2026, control audit: the random control was not matched to the signal (it enters at any bar, while the signal needs an uptrend and a dip). A control check with two matched alternatives is added under “The gates”: the random-entry result depends on the control, and neither version clears the 95th percentile against the control that matches the dip state. The frozen gate results, the verdict and the cause of death did not change. 8 Oct 2026, search and navigation: added an answer-first line, a FAQ and links to related tests and guides. No result changed. 22 Oct 2026, navigation: added a link to the new guide comparing trading costs across all our tests. No result changed. 22 Oct 2026, navigation: added a link to the new cross-market scoreboard, which includes this test. No result changed. 22 Oct 2026, navigation: added a link to the new guide comparing trend following and mean reversion across all our tests. No result changed.
+More tests and guides
- Rsi divergence strategy backtest
- Bollinger bands strategy backtest
- Forex strategy backtest
- Trend following vs mean reversion: this test next to the others of its style
- Free prop firm challenge calculator
- What all the backtests found so far
- The backtesting protocol
- How to backtest a trading strategy without fooling yourself
- Backtesting glossary