TradingView Indicators & Pine Script v6

TradingView Opening Range Breakout Indicator

A TradingView ORB indicator records the highest high and lowest low during a chosen opening window, then marks breaks of those fixed levels. Define the market open, timezone, range duration, and signal rule first. A 15-minute US stock example measures 09:30 to 09:45 New York time; futures can use that cash-open reference or a separately defined electronic-session open. An indicator displays levels and alerts, while a strategy is needed to simulate trades.

Build a Custom ORB Script

Choose the opening window

The opening range is a time-bounded measurement, not a rolling lookback. For a 15-minute window starting at 09:30, include bars from 09:30 through 09:44 on a one-minute chart, then hold the high and low fixed. The 09:45 bar is the first eligible breakout bar. A longer window includes more observations and delays eligibility; it does not establish a lower false-breakout rate.

DurationNew York exampleWhat changes
5 minutes09:30 to 09:35Signals can begin earlier; fewer bars define the boundaries.
15 minutes09:30 to 09:45A later starting point for the same entry rule.
30 minutes09:30 to 10:00Includes more opening price action before signals begin.
60 minutes09:30 to 10:30Delays trading eligibility by one hour.

Stocks and futures: distinguish the cash open from the session open

NYSE core trading normally runs from 09:30 to 16:00 Eastern Time, with holiday closures and scheduled early closes. CME equity index futures also trade outside that window. Applying a 09:30 ORB to ES measures the US equity cash-open period within the futures session; it does not measure the start of the full electronic session. Check the specific contract schedule before choosing another anchor.

  • IANA identifiers such as America/New_York follow regional DST rules. A fixed UTC-5 offset does not follow New York summer time.
  • The chart display timezone does not change an explicit timezone argument in Pine. Compare the clock labels with the script settings before diagnosing a misplaced range.
  • Custom session strings define time filters; they do not supply missing chart data or an exchange holiday calendar. On futures, TradingView session.regular can refer to the longer electronic session.
  • The sample uses weekdays and a fixed 16:00 cutoff. Skip or separately configure holiday and early-close sessions, especially when extended-hours bars are visible.
ReferenceNew York timeChicago timeScript timezone
NYSE core open / chosen ES cash-open reference09:3008:30America/New_York or America/Chicago with matching hours
15-minute cash-open range ends09:4508:45Use the same timezone as the start
Example active-window cutoff16:0015:00A strategy choice for futures, not their full trading schedule

Breakout, close confirmation, and retest rules

A wick crossing the boundary and a completed bar closing beyond it are different events. Close confirmation excludes touches that reverse before that close, but it also changes timing and entry price. Volume and VWAP filters cannot identify who traded or prove that a breakout will continue. Measure their effect on your own dataset.

RulePrecise definitionTradeoff
Close breakoutAfter range completion, close exceeds the high and the previous close was at or below it; reverse for shorts.Waits for the signal bar to finish.
Optional volume filterSignal volume exceeds a chosen multiple of the previous 20 bars' average volume.Can exclude signals and needs available volume history; this is not same-time-of-day relative volume.
Optional VWAP filterLong close is above a VWAP explicitly reset at the selected cash open; short close is below it.Requires volume and a defined anchor; not implemented in the sample.
Retest variantAfter a confirmed long breakout, a later bar touches the high and closes back above it within a preset number of bars.May never trigger; define tolerance, timeout, invalidation, and one-signal limits. Not implemented in the sample.

Pine Script v6: cash-open ORB with confirmed alerts

Paste this complete indicator into Pine Editor, save it, and add it to a standard one-minute candlestick chart. It measures a weekday 09:30 New York opening range, draws its box, then plots fixed levels and one confirmed breakout per direction per day. The volume filter is off by default. This is an educational indicator, not a backtested trading system.

  • The script requires every one-minute bar in the opening window. If loaded history begins mid-window or opening bars are missing, it skips that day instead of using a partial range.
  • The box changes while the range forms. Signal markers require barstate.isconfirmed; the script does not use future bars to confirm them.
  • Create an alert in TradingView, choose ORB Long or ORB Short, and select Once Per Bar Close. Recreate the alert after changing inputs because existing alerts keep their saved configuration.
  • A missing or zero volume average prevents a signal when the optional volume filter is enabled. Range levels still work without volume.
US cash-open example for standard one-minute charts; no orders or retest entriespinescript
//@version=6
indicator("Pineify Cash-Open ORB", overlay = true, max_boxes_count = 50)

int duration = input.int(15, "Opening range minutes", options = [5, 15, 30, 60])
bool useVolume = input.bool(false, "Require volume filter")
float volumeMultiple = input.float(1.2, "Volume multiplier", minval = 0.1, step = 0.1)
string tz = "America/New_York"

if not timeframe.isminutes or timeframe.multiplier != 1 or not chart.is_standard
    runtime.error("Use a standard one-minute candlestick chart.")

int localYear = year(time, tz)
int localMonth = month(time, tz)
int localDay = dayofmonth(time, tz)
int dateKey = localYear * 10000 + localMonth * 100 + localDay
bool newDate = na(dateKey[1]) or dateKey != dateKey[1]
int rangeStart = timestamp(tz, localYear, localMonth, localDay, 9, 30)
int rangeEnd = rangeStart + duration * 60 * 1000
bool inCash = not na(time(timeframe.period, "0930-1600:23456", tz))
bool inRange = inCash and time >= rangeStart and time < rangeEnd

var float rangeHigh = na
var float rangeLow = na
var int rangeBars = 0
var bool sawStart = false
var bool longFired = false
var bool shortFired = false
var box rangeBox = na

if newDate
    rangeHigh := na
    rangeLow := na
    rangeBars := 0
    sawStart := false
    longFired := false
    shortFired := false
    rangeBox := na

if inRange
    if time == rangeStart
        sawStart := true
        rangeHigh := high
        rangeLow := low
        rangeBox := box.new(bar_index, high, bar_index, low, border_color = color.blue, bgcolor = color.new(color.blue, 88))
    if sawStart
        rangeBars += 1
        rangeHigh := math.max(rangeHigh, high)
        rangeLow := math.min(rangeLow, low)
        box.set_top(rangeBox, rangeHigh)
        box.set_bottom(rangeBox, rangeLow)
        box.set_right(rangeBox, bar_index)

bool rangeReady = sawStart and rangeBars == duration and time >= rangeEnd
float priorVolumeAverage = ta.sma(volume, 20)[1]
bool volumeOk = not useVolume or (not na(volume) and priorVolumeAverage > 0 and volume > priorVolumeAverage * volumeMultiple)
bool eligible = rangeReady and inCash and barstate.isconfirmed and volumeOk
bool longSignal = eligible and not longFired and close > rangeHigh and close[1] <= rangeHigh
bool shortSignal = eligible and not shortFired and close < rangeLow and close[1] >= rangeLow

if longSignal
    longFired := true
if shortSignal
    shortFired := true

bool showLevels = rangeReady and inCash
plot(showLevels ? rangeHigh : na, "ORB High", color.green, 2, plot.style_linebr)
plot(showLevels ? rangeLow : na, "ORB Low", color.red, 2, plot.style_linebr)
plot(showLevels ? (rangeHigh + rangeLow) / 2 : na, "ORB Midpoint", color.gray, 1, plot.style_linebr)
plotshape(longSignal, "ORB Long", shape.triangleup, location.belowbar, color.green, text = "Long", size = size.small)
plotshape(shortSignal, "ORB Short", shape.triangledown, location.abovebar, color.red, text = "Short", size = size.small)
alertcondition(longSignal, "ORB Long", "Confirmed close above the opening range on {{ticker}}")
alertcondition(shortSignal, "ORB Short", "Confirmed close below the opening range on {{ticker}}")

Turn the indicator into a testable ORB strategy

Strategy Tester needs a strategy script with order rules. Before converting this indicator, write down the entry timing, permitted directions, position size, stop, target, maximum entries, and session exit. The following is a proposed test protocol, not measured performance or a recommended trading setup.

  • Baseline: simulate a market entry after the confirmed breakout, one position at a time, with no reversal. Decide whether the daily limit is one total trade or one per direction; the indicator signals once per direction.
  • Execution: under default strategy settings, a market order created at bar close fills on the next available tick, typically the next bar open. Do not assume a fill at the range boundary or the signal close.
  • Exits: compare an opposite-boundary stop with a midpoint stop, set a target in multiples of initial entry-to-stop risk, and define a timed exit. Reject trades with zero or invalid stop distance.
  • Costs and data: include commission, slippage, and position sizing. Use standard candles; record symbol, contract or continuous-futures settings, chart session, date range, and how ambiguous same-bar stop/target fills are handled.
  • Stability: preselect a small duration grid and volume thresholds, keep later dates outside the tuning period, and compare trade count, drawdown, and net results after costs. Neighboring results are a sensitivity check, not proof of future profitability.
  • Pineify workflow: use the AI Coding Agent to draft explicit session and order rules. The Visual Pine Script Editor is an alternative for supported blocks; verify custom ORB session requirements before choosing it. Use Strategy Optimizer after the strategy exposes suitable numeric or Boolean inputs.

Check the range and signal timing before using alerts

Use the following manual checks in TradingView. Syntax validation cannot establish correct chart behavior, fill realism, or profitability. This page does not claim that these chart checks or a performance study have been completed.

  • Compare the plotted high and low with all one-minute bars in the selected opening window. Confirm no breakout marker appears before the window ends.
  • Compare dates on either side of a US DST transition. The opening anchor should remain 09:30 New York time even if your chart displays another timezone.
  • Check the next day, a missing-opening-bar day, an early close, and an extended-hours chart. Ensure no stale range is used and exclude sessions the fixed schedule does not represent.
  • Inspect a wick-only break, a close outside, a return inside, and a second break. Confirm the first qualifying signal per direction is the only one marked that day.
  • Enable the volume filter and compare signals. A crossover rejected by volume is not accepted on a later bar unless price returns across the boundary and crosses again.
Where Pineify fits

Pine Script AI Coding Agent

Describe your opening session, breakout or retest rules, and exits to draft a custom Pine Script indicator or strategy. Review the generated logic and test it on TradingView.

Also useful: Strategy Optimizer. Compare exposed strategy input combinations and TradingView backtest results. Parameter searches require a strategy with defined orders; they do not establish future returns.

Build a Custom ORB Script

Frequently asked questions

Educational programming material, not investment advice. Examples are not performance results or trade recommendations. Historical backtests do not guarantee future results, and trading can lose money.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.