Edgoro
Volatility indicator

Opening range breakout (ORB): rules, settings and Pine Script v6 code

How the opening range breakout uses the first minutes of the session, how traders set ranges, targets and stops, the pitfalls, and a free ORB script.

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

  1. Choose the opening range window, for example 09:30–10:00 exchange time.
  2. Track the range high and range low of all bars inside the window.
  3. 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.
  4. An optional target: a common reference is one range height beyond the breakout level, range high + (range high − range low).
  5. 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

SettingTypical valueNotes
Range length5, 15, 30 or 60 minutesShorter ranges break earlier and more often.
Session09:30–16:00 New York for US stocksSet your market's regular hours.
SignalsFirst breakout each wayAll breakouts gives many more signals in choppy sessions.
Chart timeframe1 to 5 minutesBars 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.

Pine Script v6
//@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

  1. Open any chart on TradingView and open the Pine Editor.
  2. Create a new indicator, delete the template code and paste the script.
  3. 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.

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.

Make it yours with Edgoro

Describe the change in plain English and Edgoro writes the Pine Script v6 for you, ready to paste. For example:

“Plot a 15-minute opening range from 09:30 New York time, alert on the first close above the range high, and mark a target at 1× the range height.”

Build your ORB indicator