BACKTEST STUDY

NQ opening range breakout backtest results

One opening range breakout script, run 24 ways on CME's MNQ and MES futures from 23 October 2024 to 22 October 2026, costs charged. 21 of 24 versions made money over the two years. Only 2 of 24 made money in the last eight months, which the tester holds back, and the version that did best before them lost 7.8% in them.

24 versions · MNQ and MES · 5-minute candles · 517 sessions
Made money over two years
21 of 24
23 October 2024 → 22 October 2026
Made money held out
2 of 24
24 February 2026 → 22 October 2026 · 8 months
Best before, held out
-7.8%
MNQ 15-minute range, 1.5R, +52.2% before
Costs left out
-8.3%
the same MNQ version held out, no costs at all
  • Checked 3 November 2026
  • CME data, 23 October 2024 → 22 October 2026 · 2 years · 517 sessions
  • $0.75 a contract each side + 1 tick of slippage
  • $50,000 account, 1% risk, one trade a day
  • held out: 24 February 2026 → 22 October 2026 · 8 months
  • Updated 3 November 2026

The short answer

The opening range breakout made money on NQ and ES futures through 2025 and stopped in 2026. Of 24 versions, 22 were up over the first 16 months (23 October 2024 → 24 February 2026 · 16 months) and 21 over the whole two years, but only 2 made money in the last eight months, which the tester holds back from the start.

Picking the version that did best first would have hurt. On MNQ that was the 15-minute range, 1.5R at +52.2%; held out it made -7.8%. On MES it was the 15-minute range, 1.5R at +46.6%, then -5.9%. The longer 30-minute range on MNQ lost least and had the smallest drawdowns, between 7.6% and 10.6%.

Two years of one setup on two markets, with the rules fixed before the runs and no setting tuned on the held-out months. Price results after modelled costs, not a forecast.

The rules

The same script in every run; only the range length and the target change.

  1. The range: the high and low from 9:30 New York to 9:35, 9:45 or 10:00.
  2. The entry: the first 5-minute close outside the range, before 12:00 New York, long above and short below.
  3. The stop: the other side of the range. The target: 1, 1.5, 2 or 3 times the risk.
  4. The size: contracts from a 1% risk over the stop's dollars, with two ticks of slippage counted, at most 10.
  5. One trade a day, and flat on the session's last candle.

All 24 versions

Net return on the $50,000 account after costs. The held-out column is 24 February 2026 → 22 October 2026 · 8 months.

MarketOpening rangeTargetTradesWonProfit factorTwo yearsFirst 16 monthsHeld-out 8 months
MNQ1!9:30 → 9:351R49751.5%1.04+8.1%+20.5%-10.3%
MNQ1!9:30 → 9:351.5R47443.9%1.02+5.7%+21.6%-13.1%
MNQ1!9:30 → 9:352R45040.4%1.05+13.0%+37.0%-17.5%
MNQ1!9:30 → 9:353R40138.2%1.06+14.3%+47.2%-22.3%
MNQ1!9:30 → 9:451R45753.0%1.14+24.8%+32.3%-5.6%
MNQ1!9:30 → 9:451.5R41349.4%1.21+40.4%+52.2%-7.8%
MNQ1!9:30 → 9:452R38146.2%1.11+18.7%+29.3%-8.2%
MNQ1!9:30 → 9:453R35646.3%1.11+16.7%+39.8%-16.5%
MNQ1!9:30 → 10:001R36452.2%1.14+15.3%+14.1%+1.1%
MNQ1!9:30 → 10:001.5R32850.9%1.17+17.3%+18.9%-1.3%
MNQ1!9:30 → 10:002R31350.5%1.17+17.3%+18.7%-1.2%
MNQ1!9:30 → 10:003R30750.2%1.22+21.4%+18.2%+2.7%
MES1!9:30 → 9:351R50951.1%0.96-9.3%-3.8%-5.7%
MES1!9:30 → 9:351.5R49442.9%1.01+1.5%+4.1%-2.5%
MES1!9:30 → 9:352R47338.5%1.00+0.2%+9.0%-8.0%
MES1!9:30 → 9:353R43534.3%1.00+0.4%+32.8%-24.4%
MES1!9:30 → 9:451R48453.9%1.11+22.9%+27.6%-3.7%
MES1!9:30 → 9:451.5R45347.2%1.15+37.9%+46.6%-5.9%
MES1!9:30 → 9:452R42642.3%1.05+12.3%+28.0%-12.3%
MES1!9:30 → 9:453R38241.6%1.06+12.1%+32.3%-15.3%
MES1!9:30 → 10:001R43349.7%0.95-7.4%-1.1%-6.3%
MES1!9:30 → 10:001.5R40244.5%0.95-7.0%+0.7%-7.7%
MES1!9:30 → 10:002R37145.0%1.02+2.7%+13.0%-9.1%
MES1!9:30 → 10:003R35046.3%1.12+18.9%+28.0%-7.1%

Year by year

The MNQ 15-minute range with a 2R target, in dollars from its trade list.

YearTradesResult
2024 (from 23 Oct)36+$1,748
2025191+$9,264
2026 (to 22 Oct)154−$1,639

Costs are not why it fails

The same MNQ version, held out, at three cost levels.

CostsTwo yearsHeld-out 8 months
No commission, no slippage+22.4%-8.3%
$0.75 a contract each side, one tick of slippage (this page)+18.7%-8.2%
$2.50 a contract each side, one tick of slippage (the tester's default)+17.8%-7.0%

The script

MNQ opening range breakout, 15-minute range, 2R

The script every run used, with the 15-minute range and the 2R target. Change the two inputs at the top to run any other row of the table.

Trades
381
Won
46.2%
Profit factor
1.11
Net
+18.7%
Worst drawdown
−17.1%
Worst trade
−$1,063

MNQ1! · 5-minute · 23 October 2024 → 22 October 2026 · 2 years · 517 sessions · $0.75 a contract each side, one tick of slippage, $50,000 account, 1% risk

The Pine Script, if you want to read it (79 lines)
Pine Script v6 · 79 lines
//@version=6
// Suggested timeframe: 5-minute
strategy("MNQ Opening Range Breakout", overlay=true, initial_capital=50000, default_qty_type=strategy.fixed, default_qty_value=1,
     commission_type=strategy.commission.cash_per_contract, commission_value=0.75, slippage=1, margin_long=0, margin_short=0)

// Inputs
orSess       = input.session("0930-0945", "Opening range (New York)")
tradeSess    = input.session("0945-1200", "Entry window (New York)")
riskPct      = input.float(1.0, "Risk % per trade", minval=0.1, step=0.1)
rMult        = input.float(2.0, "Target (R)", minval=0.5, step=0.5)
maxContracts = input.int(10, "Max contracts", minval=1)
maxTrades    = input.int(1, "Max trades per day", minval=1)

// The clock is New York's; a future's day starts at the 18:00 New York reopen
inOR    = not na(time(timeframe.period, orSess, "America/New_York"))
inTrade = not na(time(timeframe.period, tradeSess, "America/New_York"))

// The day's state: every level, flag and count the setup keeps, declared here and set back on the day's first bar
var float orHigh      = na
var float orLow       = na
var int   tradesToday = 0
var bool  doneToday   = false
var float stopLevel   = na
var float targetLevel = na
if session.isfirstbar
    orHigh      := na
    orLow       := na
    tradesToday := 0
    doneToday   := false

// The setup: the first close outside the 15-minute opening range
if inOR
    orHigh := na(orHigh) ? high : math.max(orHigh, high)
    orLow  := na(orLow) ? low : math.min(orLow, low)
rangeSet   = not inOR and not na(orHigh)
longSetup  = rangeSet and close > orHigh and close[1] <= orHigh
shortSetup = rangeSet and close < orLow and close[1] >= orLow
longStop   = orLow
shortStop  = orHigh

// Entries: inside the window, flat, under the day's caps; the qty from the risk (a stop too wide skips the
// trade), the stop and target placed with the entry
canTrade = inTrade and strategy.position_size == 0 and tradesToday < maxTrades and not doneToday and barstate.isconfirmed
riskCash = math.max(strategy.equity, 0) * riskPct / 100
if canTrade and longSetup and not na(longStop) and longStop < close
    stopPts = close - longStop
    qty = math.min(maxContracts, math.floor(riskCash / ((stopPts + 2 * syminfo.mintick) * syminfo.pointvalue)))
    if qty >= 1
        stopLevel   := longStop
        targetLevel := close + stopPts * rMult
        strategy.entry("Long", strategy.long, qty=qty)
        strategy.exit("Long exit", from_entry="Long", stop=stopLevel, limit=targetLevel)
        tradesToday := tradesToday + 1
if canTrade and shortSetup and not na(shortStop) and shortStop > close
    stopPts = shortStop - close
    qty = math.min(maxContracts, math.floor(riskCash / ((stopPts + 2 * syminfo.mintick) * syminfo.pointvalue)))
    if qty >= 1
        stopLevel   := shortStop
        targetLevel := close - stopPts * rMult
        strategy.entry("Short", strategy.short, qty=qty)
        strategy.exit("Short exit", from_entry="Short", stop=stopLevel, limit=targetLevel)
        tradesToday := tradesToday + 1

// The same stop and target on every bar of the trade; flat on the session's last bar
if strategy.position_size > 0
    strategy.exit("Long exit", from_entry="Long", stop=stopLevel, limit=targetLevel)
if strategy.position_size < 0
    strategy.exit("Short exit", from_entry="Short", stop=stopLevel, limit=targetLevel)
if session.islastbar
    strategy.close_all("Session end", immediately=true)

// A win ends the day
if strategy.closedtrades > strategy.closedtrades[1] and strategy.closedtrades.profit(strategy.closedtrades - 1) > 0
    doneToday := true

plot(rangeSet ? orHigh : na, "Range high", color=color.new(#16A56A, 0), style=plot.style_linebr)
plot(rangeSet ? orLow : na, "Range low", color=color.new(#E5484D, 0), style=plot.style_linebr)
plotshape(canTrade and longSetup, "Long", style=shape.triangleup, location=location.belowbar, color=color.new(#16A56A, 0), size=size.tiny)
plotshape(canTrade and shortSetup, "Short", style=shape.triangledown, location=location.abovebar, color=color.new(#E5484D, 0), size=size.tiny)

Test your own version, free

Paste your ORB script or describe it in your own words. The free NQ futures backtester runs it on the same CME data with per-contract costs and the same held-out months, and shows every trade on the chart. No card.

Trading a prop challenge

The same setup judged by a challenge's daily loss limit and trailing drawdown, kept in the script's own books, is on the prop firm page.

Questions

Does the opening range breakout work on NQ?

In this test it made money over two years and then stopped. 21 of 24 versions on MNQ and MES were up from 23 October 2024 to 22 October 2026 after costs, but only 2 of 24 made money from 24 February 2026 on. On MNQ the 15-minute range with a 2R target made +$9,264 in 2025 and lost $1,639 in 2026 to 22 October.

What is the best opening range length for NQ, 5, 15 or 30 minutes?

Before the held-out months the 15-minute range did best on MNQ (15-minute range, 1.5R: +52.2% in 16 months). In the eight months after it lost 7.8%. The 30-minute range was the only one that held up on MNQ, +2.7% at 3R, with smaller drawdowns, but two small positives out of four are not an edge.

What target should an ORB use, 1R, 2R or 3R?

No target fixed it. Wider targets won less often and made more before the held-out months, then lost more in them: on MNQ with the 5-minute range, 1R lost 10.3% held out and 3R lost 22.3%.

Is it the commission that makes it lose?

No. With no commission and no slippage at all, the MNQ 15-minute 2R version still lost 8.3% in the held-out months. At $2.50 a contract each side it lost 7.0%: one micro contract sized from a 1% risk trades few contracts, so costs move the result by a few points, not its sign.

Which data and costs were used?

CME's minutes for the continuous MNQ and MES contracts, built into 5-minute candles, 23 October 2024 to 22 October 2026, 517 sessions. $0.75 a contract each side and one tick of slippage, a $50,000 account, 1% risk a trade, one trade a day, flat at the session's end.

Can I run this on my own settings?

Yes. The script is on this page; Run it opens the free NQ futures backtester with it in the box, where you change the inputs and see every trade on the chart. A free account runs as many tests as you like, no card.

Every number here is the output of the Alpha Charts backtest engine on 3 November 2026, on CME futures data. Past results are not a forecast and nothing here is investment advice. TradingView and Pine Script belong to TradingView, Inc.; Alpha Charts is not affiliated with it.