What it measures
The opening range is the high and low of the first few minutes of a trading session, such as the first 30 minutes of the New York stock market. An opening range breakout is a close above that high or below that low later in the day. The idea is that the first part of the session sets the day's initial balance, and a decisive move out of it can mark the day's direction.
Toby Crabel's 1990 book on opening range breakouts made the approach widely known. It remains a common intraday framework for stocks and index futures, and for other markets with a session you define.
The formula in words
- Choose the opening range window, for example 09:30–10:00 exchange time.
- Track the range high and range low of all bars inside the window.
- Once the window has ended, a bullish breakout is the first close above the range high; a bearish breakout is the first close below the range low.
- An optional target: a common reference is one range height beyond the breakout level, range high + (range high − range low).
- Reset everything at the next session's opening range.
Breakouts are usually limited to the regular session, and many traders count only the first breakout each way per day. The script does both by default.
How traders read it
- Direction for the day. A clean close above the range high early in the session is read as buyers in control; repeated failures back into the range point to a choppy, two-sided day.
- Stops. Common stop placements are the opposite side of the range or its midpoint. A wide range means a wide stop, so size the position from the stop distance; the position size calculator does that.
- Targets. One range height is a common first target, with the rest managed by a trailing stop or an exit at the session's end.
- Range size as a filter. A very wide range leaves less room for follow-through; a very narrow one breaks easily but also fails easily. Some traders compare the range with the ATR before trading it.
Common settings
| Setting | Typical value | Notes |
|---|---|---|
| Range length | 5, 15, 30 or 60 minutes | Shorter ranges break earlier and more often. |
| Session | 09:30–16:00 New York for US stocks | Set your market's regular hours. |
| Signals | First breakout each way | All breakouts gives many more signals in choppy sessions. |
| Chart timeframe | 1 to 5 minutes | Bars must be shorter than the range. |
Pine Script v6 code
The complete, self-contained script is below. Copy it into a new indicator in TradingView's Pine Editor, or download the .pine file.
//@version=6
indicator("Opening range breakout", shorttitle = "ORB", overlay = true)
orSess = input.session("0930-1000", "Opening range", group = "Sessions")
daySess = input.session("0930-1600", "Signals allowed during", group = "Sessions")
tzInput = input.string("Exchange", "Time zone", options = ["Exchange", "UTC", "America/New_York", "America/Chicago", "Europe/London", "Europe/Berlin", "Asia/Tokyo"], group = "Sessions")
firstOnly = input.bool(true, "Only the first breakout each way per day", group = "Signals")
showTargets = input.bool(true, "Show 1x range targets", group = "Display")
if timeframe.isdwm
runtime.error("The opening range needs an intraday chart, with bars shorter than the range itself.")
tz = tzInput == "Exchange" ? syminfo.timezone : tzInput
inRange = not na(time(timeframe.period, orSess, tz))
inDay = not na(time(timeframe.period, daySess, tz))
rangeStarts = inRange and not inRange[1]
rangeEnds = not inRange and inRange[1]
var float orHigh = na
var float orLow = na
var bool ready = false
var bool longDone = false
var bool shortDone = false
if rangeStarts
orHigh := high
orLow := low
ready := false
longDone := false
shortDone := false
else if inRange
orHigh := math.max(orHigh, high)
orLow := math.min(orLow, low)
if rangeEnds
ready := true
// A breakout is a close beyond the finished range, after the previous close was inside it.
breakUp = ready and inDay and close > orHigh and close[1] <= orHigh and not (firstOnly and longDone)
breakDown = ready and inDay and close < orLow and close[1] >= orLow and not (firstOnly and shortDone)
if breakUp
longDone := true
if breakDown
shortDone := true
showLines = ready and inDay
rangeSize = orHigh - orLow
hiPlot = plot(showLines ? orHigh : na, "Range high", color = color.new(color.teal, 0), linewidth = 2, style = plot.style_linebr)
loPlot = plot(showLines ? orLow : na, "Range low", color = color.new(color.red, 0), linewidth = 2, style = plot.style_linebr)
fill(hiPlot, loPlot, color = color.new(color.blue, 93), title = "Range fill")
plot(showLines and showTargets ? orHigh + rangeSize : na, "Target above (1x range)", color = color.new(color.teal, 50), style = plot.style_linebr)
plot(showLines and showTargets ? orLow - rangeSize : na, "Target below (1x range)", color = color.new(color.red, 50), style = plot.style_linebr)
plot(rangeSize, "Range size", display = display.data_window)
bgcolor(inRange ? color.new(color.blue, 90) : na, title = "Opening range")
plotshape(breakUp, "Breakout up", shape.triangleup, location.belowbar, color.new(color.teal, 0), size = size.small)
plotshape(breakDown, "Breakout down", shape.triangledown, location.abovebar, color.new(color.red, 0), size = size.small)
alertcondition(breakUp, "ORB breakout up", "{{ticker}} closed above the opening range high ({{interval}}) at {{close}}")
alertcondition(breakDown, "ORB breakout down", "{{ticker}} closed below the opening range low ({{interval}}) at {{close}}")The opening range is shaded while it forms. Once it's complete, its high and low are drawn for the rest of the session with optional 1× range targets, and triangles mark breakouts. The range size is in the data window.
The time zone defaults to the exchange's own, so 09:30–10:00 means the US cash open on US stocks; for futures, forex or crypto, set the session times and time zone yourself. The script stops with a message on daily or higher timeframes, where an opening range doesn't exist. Two alert conditions fire on breakouts; use Once per bar close.
Add it to your chart
- Open any chart on TradingView and open the Pine Editor.
- Create a new indicator, delete the template code and paste the script.
- Click Save, then Add to chart. Change lengths and levels from the indicator's settings.
Stuck on an error? See how to add a Pine Script indicator to TradingView.
Pitfalls
- Wrong time zone. 09:30–10:00 means different moments in exchange time, UTC and London time. Check that the shaded window lands where you expect.
- Bars too large. On a 30-minute chart a 30-minute range is a single bar. Use bars well below the range length.
- False breakouts. Many breakouts fail and reverse. Test with costs and slippage, which matter more around the open, when spreads are often wider.
- 24-hour markets. Forex and crypto have no single open. The range only means something relative to the session you choose, such as the London or New York open.
Related reading
- Pine Script strategy.exit(): stop loss and take profit that behave as you expect
- 8 backtesting mistakes that make a strategy look better than it is
- Position Size Calculator (free tool)
- Forex Market Hours (free tool)
- Risk/Reward Calculator (free tool)
The script is an educational example: test it on your own markets before relying on it. Indicators describe the past; they don't predict the future. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.