Opening Range Breakout
The strategy trades breakouts from the first N minutes of a trading session, entering long when price closes above the opening range high or short when price closes below the opening range low. The mechanism assumes the opening range represents an initial consolidation zone; when price clears this zone with conviction, the directional bias signals a tradeable move.
Why this might work
The opening period of a trading session exhibits specific microstructure characteristics. At market open, volume surges as overnight orders and gap traders execute; the resulting price discovery typically occurs within the first 30 to 60 minutes, after which the market often establishes a defined range. This is not a speculative claim but a structural observation: spreads tighten, order book depth increases, and market participants have a clearer picture of the session's sentiment once this initial period concludes [1].
Breakouts from consolidation zones are central to classical price-action analysis. When price has balanced supply and demand within a tight range and then breaks decisively outside that range, practitioners interpret the breakout as evidence that one side has overwhelmed the other [2]. This is practitioner convention, though momentum-factor research shows that prior price strength predicts near-term outperformance, lending some academic support to momentum-based entry signals [3].
The opening range breakout strategy explicitly anchors entries to a defined structural level. Unlike arbitrary breakout signals, the opening range high and low are created by the market itself during the session's most liquid minutes, reducing the risk of false breaks on thin volume. Position sizing and stop placement become mechanical: the range height defines both the profit target measurement and the natural stop level, aligning risk-reward in a systematic way.
However, the edge of this strategy is highly regime-dependent. The opening range has no universal optimal length; 30 minutes may work for S&P 500 futures, while crude oil or foreign exchange may require 60 minutes or more. More critically, the edge varies across market types: liquid index futures show breakout follow-through; individual stocks face higher slippage; volatile pre-market or after-hours sessions exhibit wider and more unreliable ranges. The strategy works best in trending, directional markets and degrades sharply when price ranges and reversals dominate. Costs, specifically commission and slippage, erode the edge aggressively, as the profit target and stop distance are often just 20-50 basis points from entry.
The rules
Instrument: S&P 500 futures (ES on micro-contract or standard lot), or any liquid equity index futures contract. The strategy may be adapted to individual stocks or other asset classes, but liquidity and cost structure vary materially; parameters should be re-optimized per instrument.
Timeframe: 5-minute bars.
Opening range definition: The high and low of the first 30 minutes of the regular trading session, calculated from bars 1 through 6 (starting at 09:30 ET for US equity futures). The range is fixed at the end of the 30-minute period and remains unchanged for the remainder of the session.
Entry trigger:: Long: Place a buy order at market if the close of any bar after the opening-range close bar is at or above the opening range high. Execute the order at the close of that bar.
- Short: Place a sell order at market if the close of any bar after the opening-range close bar is at or below the opening range low. Execute the order at the close of that bar.
Initial stop loss:: Long: Set stop 5 ticks (or user-defined) below the opening range low.
- Short: Set stop 5 ticks (or user-defined) above the opening range high.
Profit target:: Measure the opening range height (high minus low). Place profit target at entry price plus 1.5 times the range height for longs, and entry price minus 1.5 times the range height for shorts.
- Alternatively, use a fixed point profit target (e.g., 20 points on ES).
Position sizing: Fixed 1 contract per signal, or risk-based sizing to risk 0.5%-1% of account equity per trade.
Session and time filters:: Trade only during regular trading hours (09:30-16:00 ET for US equity futures).
- Do not enter signals after 15:30 ET (30 minutes before close) to avoid overnight holding risk.
- Close all open positions by 16:00 ET if not already closed.
Trade frequency: The strategy should generate approximately 100-200 signals per year on ES (roughly 50 cents to 1 signal per trading day), providing a statistically meaningful sample for evaluation within a reasonable backtest window.
Code
//@version=6
strategy("Opening Range Breakout", overlay=true,
commission_type=strategy.commission.percent,
commission_value=0.001,
slippage=2)
// Inputs
rangeLength = input(30, title="Opening Range Minutes", tooltip="Duration in minutes for the opening range")
stopTicks = input(5, title="Stop Loss (ticks)", tooltip="Ticks below/above range for stop loss")
targetMultiplier = input(1.5, title="Target Multiplier", tooltip="Profit target as multiple of range height")
sessionStartHour = input(9, title="Session Start Hour (ET)", tooltip="Opening hour")
sessionStartMin = input(30, title="Session Start Minute", tooltip="Opening minute")
sessionEndHour = input(16, title="Session End Hour (ET)", tooltip="Closing hour")
sessionEndMin = input(0, title="Session End Minute", tooltip="Closing minute")
noEntryAfterHour = input(15, title="No Entry After Hour (ET)", tooltip="Stop taking entries N minutes before close")
noEntryAfterMin = input(30, title="No Entry After Minute", tooltip="Stop taking entries minute")
// Calculate bars in opening range
barsInRange = math.round(rangeLength / 5)
// Variables to hold opening range high/low
var float orHigh = na
var float orLow = na
var bool rangeFixed = false
var int barsSinceRangeClose = 0
// Detect session start
isSessionStart = (hour == sessionStartHour and minute == sessionStartMin)
isSessionEnd = (hour == sessionEndHour and minute == sessionEndMin)
isNoEntryTime = (hour > noEntryAfterHour or (hour == noEntryAfterHour and minute >= noEntryAfterMin))
// Reset at session start
if isSessionStart
orHigh := high
orLow := low
rangeFixed := false
barsSinceRangeClose := 0
// Build opening range for barsInRange
if not rangeFixed and barsSinceRangeClose < barsInRange
orHigh := math.max(orHigh, high)
orLow := math.min(orLow, low)
barsSinceRangeClose += 1
if barsSinceRangeClose == barsInRange
rangeFixed := true
barsSinceRangeClose := 0
// Calculate range height and targets
rangeHeight = orHigh - orLow
longTarget = orHigh + (rangeHeight * targetMultiplier)
shortTarget = orLow - (rangeHeight * targetMultiplier)
// Entry conditions (only after range is fixed, not in no-entry window)
canEnter = rangeFixed and not isNoEntryTime
longBreakout = canEnter and close > orHigh and strategy.position_size == 0
shortBreakout = canEnter and close < orLow and strategy.position_size == 0
// Stop placement in ticks (assuming 1 tick = 0.25 for ES)
tickSize = 0.25
stopDistance = stopTicks * tickSize
longStop = orLow - stopDistance
shortStop = orHigh + stopDistance
// Execute trades
if longBreakout
strategy.entry("Long", strategy.long, stop=longStop, limit=longTarget)
if shortBreakout
strategy.entry("Short", strategy.short, stop=shortStop, limit=shortTarget)
// Close at session end
if isSessionEnd
strategy.close_all()
// Plot opening range
plot(orHigh, color=color.blue, linewidth=2, title="OR High")
plot(orLow, color=color.red, linewidth=2, title="OR Low")
plot(strategy.position_size > 0 ? longTarget : na, color=color.green, style=plot.style_linebr, title="Long Target")
plot(strategy.position_size < 0 ? shortTarget : na, color=color.orange, style=plot.style_linebr, title="Short Target")
How the code works
The script initializes the opening range high and low at the session start (09:30 ET) and accumulates the high and low of successive bars until barsInRange bars have closed (typically 6 bars for a 30-minute range on 5-minute timeframes). Once the range is fixed, the code waits for a breakout: a close above orHigh for a long entry or a close below orLow for a short entry.
At entry, the stop loss is placed stopTicks ticks below the opening range low for longs (or above it for shorts). The profit target is calculated as the entry price plus targetMultiplier times the range height. The script prevents new entries after 15:30 ET (noEntryAfterHour and noEntryAfterMin) to avoid holding positions overnight. All positions close at 16:00 ET. Commission is set to 0.1% (typical for ES) and slippage to 2 ticks, reflecting realistic market conditions.
Testing it honestly
Backtest this strategy on TradingView using at least two years of ES 5-minute data. Divide the data into an in-sample period (first 12-18 months) and an out-of-sample period (remaining months). Run the strategy on both periods; a strategy that performs well in-sample but poorly out-of-sample is overfit and should not be traded.
Ensure realistic costs: 0.1% commission per side and 2-3 ticks of slippage are conservative for ES during liquid hours. If the strategy shows profit with these costs, the edge is genuine. If it breaks even or loses money after costs, the mechanical edge does not exist.
Test on at least 50-100 trades (roughly 2-6 months of data) before drawing conclusions; a handful of trades proves nothing. A 55% win rate on 50 trades could be random, but a 55% win rate on 500 trades is statistically meaningful.
Separately, test the strategy on other instruments (QQQ, crude, gold) and other timeframes (3-minute or 15-minute bars). If the strategy fails on other instruments or timeframes, it is likely overfit to ES 5-minute data and should not be traded in other contexts.
Limitations
Range definition is arbitrary. No standard rule governs the optimal opening range length; 30 minutes is practitioner convention, but the strategy may work better or worse with 20, 45, or 60 minutes. Changing this parameter mid-backtest to optimize results is a form of overfitting.
Costs are severe relative to edge. The profit target is typically only 1.5-2.0 times the range height, often 15-30 points on ES. After slippage, commission, and adverse price movement, the net edge shrinks below the breakeven threshold for many trade samples.
Session and instrument dependence. The opening range on ES at 09:30 ET is fundamentally different from the opening range on crude oil (which trades nearly 24/7), on individual stocks (which face higher slippage and wider spreads), or on premarket sessions (which are thinner and less reliable). Parameters must be re-optimized for each instrument, and the strategy may not generalize.
Opening gaps defeat the strategy. If the market gaps through the opening range at open, common after overnight news, the range becomes a poor reference for intraday direction, and the strategy breaks down.
Market regime matters critically. The strategy works best in trending markets, where breakouts lead to follow-through, and worst in choppy, mean-reverting markets, where the opening range breaks false and price reverts. A market that switches between regimes will show inconsistent results.
Overfitting risk. The temptation to optimize range length, target multiplier, and stop distance to past data is high, and backtest results can be misleading. Walk-forward testing (optimizing on in-sample, testing on out-of-sample) is essential but often skipped.
No independent published evidence of profitability. While many traders report success with ORB strategies, peer-reviewed studies documenting consistent, cost-adjusted profitability across large sample sizes and multiple instruments are limited. Backtest results published by software vendors are typically biased toward favorable results.
Key definitions
Opening range: The high and low price established during a defined period (usually the first 30-60 minutes) after a trading session begins. It serves as a reference zone for breakout entry signals.
Breakout: A close above a prior resistance level (or below a prior support level) that signals potential continuation of a directional move.
Price action: Analysis of price movement and structure (highs, lows, ranges, breakouts) without reliance on indicators, used to identify entry and exit levels.
Slippage: The difference between the expected execution price and the actual price received, often due to market movement between order placement and execution.
Profit target: A predefined price level at which a position is automatically closed to capture profit.
Stop loss: A predefined price level at which a position is automatically closed to limit losses.
Regime: A market condition (e.g., trending, mean-reverting, volatile, calm) in which price behavior and strategy performance change materially.
Figures
References
[1] CME Group, "E-mini S&P 500 Futures Contract Specifications," CME.com. Https://www.cmegroup.com/trading/equity-index/us-index/e-mini-sandp-500.html
[2] Investopedia, "Price Action Trading," Investopedia.com. Https://www.investopedia.com/terms/p/price-action.asp
[3] Jegadeesh, N. And Titman, S., "Returns to Buying Winners and Selling Losers: Implications for Stock Market Efficiency," The Journal of Finance, Vol. 48, No. 1 (1993). Https://doi.org/10.2307/2328882
[4] Nasdaq, "U.S. Equity Trading Hours and Holidays," Nasdaq.com. Https://www.nasdaq.com/services/trading-hours.html
[5] SEC, "Regulation SHO," U.S. Securities and Exchange Commission. Https://www.sec.gov/cgi-bin/browse-edgar
[6] Investopedia, "Opening Range Breakout (ORB)," Investopedia.com. (General trading education)
Educational research on historical data only. Not investment advice, not a signal, and never a performance promise. Past results do not predict future performance. Every reference is link-verified before publication and every paper is re-audited weekly against the library's editorial standard.
Last reviewed by the PropLedger research pipeline: 2026-09-20. Educational research on historical data, not financial advice.
Keep reading
Fair Value Gap Retracement Strategy
A complete, testable trading strategy: an ICT fair-value-gap strategy traded on the retracement: gap definition, the displacement requirement, entry, stop placement and expectancy caveats. Exact rules, full Pine Script code, and an honest reading of the evidence.
Time-of-Day Drift: A Null Benchmark
A complete, testable trading strategy: a time-of-day drift strategy as a null benchmark: what a strategy with no price structure earns, and why every other idea must beat it. Exact rules, full Pine Script code, and an honest reading of the evidence.
RSI Divergence Mechanical Strategy with Null Testing
A complete, testable trading strategy: an RSI divergence strategy subjected to an honest test: defining divergence mechanically, then measuring it against a matched null. Exact rules, full Pine Script code, and an honest reading of the evidence.