Indicator · Pine Script v6 · On the chart

Patrick 15m Opening Range

by spice2807· code credited to Backtest the Hype

Visualises a 15-minute opening range breakout routine for the cash session open.

View on GitHub

GitHub stars1on the repository
Pine versionv6current
Lines of code420
Settings21inputs
LicenceNone statedfile: MPL-2.0
Last update2 weeks ago13 Oct 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

420 lines of Pine Script v6 from BTH_Patrick_15m_ORB (1).pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

BTH_Patrick_15m_ORB (1).pine
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Backtest the Hype
//
// ─────────────────────────────────────────────────────────────────────────────
//  Patrick Wieland — "Simple Day Trading Strategy for Market Open! 15 MINUTE RANGE!"
//  coded by Backtest the Hype · v2.3
//  VISUALIZER (draws every setup and simulates the trades on the loaded history).
//  The MT5 EA will be the real backtest engine. Use the 1-MINUTE chart of
//  NASDAQ (NQ / NAS100 / QQQ) or the S&P 500 (ES / US500 / SPY).
// ─────────────────────────────────────────────────────────────────────────────
//
//  HIS RULES (stated in the video)
//   1. Opening range = the FIRST 15-MINUTE CANDLE of the cash session, 9:30-9:45 New York.
//      Mark its high and its low.
//   2. Nothing to do inside the range. No trade until that 15-minute candle has closed,
//      and no trade while price is still inside it ("there's nothing to do in there").
//   3. Break above the high  -> look only for LONGS.
//      Break below the low   -> look only for SHORTS.
//      Once it breaks one side he stays with that side ("all day I'm looking for those shorts").
//   4. Entry on the 1/3/5-minute chart in the break direction.
//   5. Stop = the high of the candle he shorts on (low of the candle for longs).
//      Size the position to that stop.
//   6. No fixed target: ride the move and keep moving the stop to each new
//      lower high (shorts) / higher low (longs). "20-30 points a day, risking 10."
//   7. If economic numbers come out at 9:45 or 10:00, wait for them before trading.
//
//  OUR DEFINITIONS — our mechanical reading of his idea, NOT rules he stated. All are settings.
//   - A break = a candle CLOSES beyond the range (default: 1-minute candle).
//     A wick through the level is not a break.
//   - Entry = the OPEN of the candle after the breakout candle closes, plus slippage
//     (option: the breakout candle's close, which is optimistic).
//     Stop = the breakout candle's opposite extreme.
//     Option: stop on the other side of the range, or at the range midpoint (classic ORB).
//   - Trailing stop = each new confirmed swing (2 bars each side, ties don't count). A swing is only
//     known when its last bar closes, so the new stop is live from the NEXT candle.
//     The stop only ever moves in the trade's favour.
//   - Exit styles: TRAIL (his description) · FIXED R:R · TRAIL + R:R cap.
//   - Entries allowed from 9:45 to 12:00 New York. Every trade is closed by 15:55.
//   - One trade at a time. Max trades per day is a setting (default 1).
//     A re-entry needs price to close back inside the range and break out again.
//   - Direction is locked by the first break after the range closes (default), even if
//     entries are delayed to 10:00 for news. Option: either side, each break.
//   - Entry = a FRESH break only: the previous candle closed inside the range and this one
//     closes outside. If price is already outside when entries open (e.g. news delay), we
//     wait for it to come back inside and break again. Option: any close beyond the range.
//   - News: Pine can't read an economic calendar. "Wait until 10:00" is a manual switch.
//   - Same-candle stop and target: we count the STOP (worst case).
//   - Costs: slippage on every market fill (entry, stop, close-out), commission per trade.
//     Targets are limit orders, so no slippage on them.
//   - A trade that closes at exactly 0R is a break-even: not a win, not a loss.
//   - 1-MINUTE CHART ONLY. The 5m/15m confirmation is built from 1-minute candles.
// ─────────────────────────────────────────────────────────────────────────────

//@version=6
indicator("Backtest the Hype — Patrick 15m Opening Range", shorttitle = "BTH 15m ORB", overlay = true, max_lines_count = 500, max_labels_count = 500, max_boxes_count = 500)

// ───────────── Inputs ─────────────
grpT = "Session (New York time)"
tz         = input.string("America/New_York", "Timezone", options = ["America/New_York", "Africa/Lagos", "Europe/London", "UTC"], group = grpT, tooltip = "Leave on America/New_York so the times never need changing (it handles the US clock change).")
openHHMM   = input.int(930, "Session open (HHMM)", minval = 0, maxval = 2359, group = grpT)
orMinutes  = input.int(15, "Opening range length (minutes)", minval = 1, maxval = 120, group = grpT, tooltip = "His video: the first 15-minute candle (9:30-9:45).")
startHHMM  = input.int(945, "Earliest entry (HHMM)", minval = 0, maxval = 2359, group = grpT, tooltip = "9:45 = right after the range candle closes. Set 1000 on days with 10:00 news (his rule: wait for the numbers).")
lastHHMM   = input.int(1200, "Last entry (HHMM)", minval = 0, maxval = 2359, group = grpT)
flatHHMM   = input.int(1555, "Close every trade by (HHMM)", minval = 0, maxval = 2359, group = grpT)

grpE = "Entry"
confirmTF  = input.string("Chart candle (1-minute)", "Break confirmed by", options = ["Chart candle (1-minute)", "5-minute candle close", "15-minute candle close"], group = grpE, tooltip = "A break only counts when a candle of this size CLOSES beyond the range.")
dirMode    = input.string("Locked by the first break", "Direction for the day", options = ["Locked by the first break", "Either side (each break)"], group = grpE)
dirFrom    = input.string("First break after the range", "First break counted from", options = ["First break after the range", "First break after earliest entry"], group = grpE, tooltip = "After the range (default): a 9:50 break sets the direction even if you wait until 10:00 to trade. After earliest entry: breaks before your entry time are ignored.")
freshOnly  = input.string("Fresh break only", "Entry candle", options = ["Fresh break only", "Any close beyond the range"], group = grpE, tooltip = "Fresh break: the previous candle closed inside the range and this one closes outside. Matters when entries are delayed (news) and price is already outside the range at the entry time.")
maxTradesI = input.int(1, "Max trades per day", minval = 1, maxval = 10, group = grpE)

grpS = "Stop & exit"
stopMode   = input.string("Breakout candle extreme (his)", "Stop", options = ["Breakout candle extreme (his)", "Other side of the range", "Range midpoint"], group = grpS)
exitMode   = input.string("Trail swings (his)", "Exit style", options = ["Trail swings (his)", "Fixed R:R", "Trail + R:R cap"], group = grpS)
rr         = input.float(2.0, "R:R target (Fixed / cap)", minval = 0.5, step = 0.25, group = grpS)
pivLen     = input.int(2, "Swing size for trailing (bars each side)", minval = 1, maxval = 10, group = grpS)

grpC = "Fills & costs"
fillMode   = input.string("Next candle open (realistic)", "Entry fill", options = ["Next candle open (realistic)", "Breakout candle close (optimistic)"], group = grpC, tooltip = "You only know the break once the candle has closed, so the first price you can really get is the next candle's open.")
slipPts    = input.float(0.25, "Slippage per market fill (points)", minval = 0, step = 0.05, group = grpC, tooltip = "NQ / NAS100 about 0.25-0.5 · ES / US500 about 0.25 · QQQ / SPY about 0.01-0.02.")
commPts    = input.float(0.0, "Commission + spread per trade (points)", minval = 0, step = 0.05, group = grpC, tooltip = "Your broker's round-trip cost in index points. On CFDs, put the spread here.")

grpV = "Visuals"
showBox    = input.bool(true, "Show opening range", group = grpV)
showTrades = input.bool(true, "Show trades", group = grpV)
showPanel  = input.bool(true, "Show results panel", group = grpV)

cGreen = #00E561
cRed   = #FF4D5E
cGrey  = #7E918A
cWhite = #EEF4F0
cPanel = #0B1410
cAmber = #F5B942

// ───────────── Helpers ─────────────
toMin(hhmm) => math.floor(hhmm / 100) * 60 + hhmm % 100
openM  = toMin(openHHMM)
orEndM = openM + orMinutes
startM = math.max(toMin(startHHMM), orEndM)
lastM  = toMin(lastHHMM)
flatM  = toMin(flatHHMM)
detM   = dirFrom == "First break after the range" ? orEndM : startM
tfMin  = timeframe.isminutes ? timeframe.multiplier : timeframe.isseconds ? 1 : 1440
okTF   = timeframe.isminutes and timeframe.multiplier == 1   // 1-minute chart only
nextOpen = fillMode == "Next candle open (realistic)"

mOpen  = hour(time, tz) * 60 + minute(time, tz)   // bar open, minutes since midnight (New York)
mClose = mOpen + tfMin                              // bar close
newDay = nz(ta.change(dayofmonth(time, tz)), 1) != 0

blockN = confirmTF == "5-minute candle close" ? 5 : confirmTF == "15-minute candle close" ? 15 : tfMin
blockStart = mOpen % blockN == 0
blockEnd   = mClose % blockN == 0

// trailing swings: strictly higher / lower than the pivLen bars on each side (ties don't count).
// Same definition as the MT5 EA, so both find the same swings.
swingHigh() =>
    bool ok = bar_index >= 2 * pivLen
    if ok
        for i = 0 to 2 * pivLen
            if i != pivLen and high[i] >= high[pivLen]
                ok := false
    ok
swingLow() =>
    bool ok = bar_index >= 2 * pivLen
    if ok
        for i = 0 to 2 * pivLen
            if i != pivLen and low[i] <= low[pivLen]
                ok := false
    ok
pH = swingHigh() ? high[pivLen] : na
pL = swingLow() ? low[pivLen] : na

// ───────────── State ─────────────
var float orH = na
var float orL = na
var bool  orDone = false
var int   dayDir = 0            // 0 = not broken yet, 1 = longs only, -1 = shorts only
var int   tradesToday = 0
var bool  needReset = false     // after a trade, price must close back inside before a re-entry
var float bH = na               // running high/low of the confirmation candle
var float bL = na

var int   pos = 0               // 1 long, -1 short, 0 flat
var float ent = na
var float stp = na
var float tgt = na
var float risk = na
var int   entBar = na
var line  lStop = na            // current segment of the (trailing) stop line
var box   rBox = na             // painted risk zone: entry -> first stop
var box   gBox = na             // painted reward zone: entry -> target, or entry -> best price (trail)
var float best = na             // best price reached since entry
var float stop0 = na            // first stop (the risk the trade was sized on)
var box   orBox = na
var int   pend = 0              // signal waiting for the next candle's open
var float pendStop = na
var float prevBC = na           // close of the previous confirmation candle

// stats
var int   nT = 0
var int   nW = 0
var int   nBE = 0
var float sumR = 0.0
var float grossW = 0.0
var float grossL = 0.0
var float pts = 0.0
var int   consec = 0
var int   maxConsec = 0
var float eqR = 0.0
var float peakR = 0.0
var float maxDD = 0.0
var int   nDays = 0
var int   nBreakDays = 0

// result of a trade after commission; px already includes exit slippage
closeTrade(float px, string why) =>
    p = (pos == 1 ? px - ent : ent - px) - commPts
    r = p / risk
    [r, p, why]

// open a trade (entry price already includes slippage)
openTrade(int d, float e, float s) =>
    rk = d == 1 ? e - s : s - e
    rk > syminfo.mintick ? rk : na

// entry markers, painted like TradingView's long/short position tool.
// returns [stop line, risk box, reward box]
drawEntry(int d, float e, float s, float t) =>
    label.new(bar_index, d == 1 ? low : high, d == 1 ? "LONG" : "SHORT", style = d == 1 ? label.style_label_up : label.style_label_down, color = color.new(d == 1 ? cGreen : cRed, 10), textcolor = color.black, size = size.small)
    rb = box.new(bar_index, d == 1 ? e : s, bar_index + 1, d == 1 ? s : e, border_color = color.new(cRed, 30), bgcolor = color.new(cRed, 78), text = "Stop  " + str.tostring(s, format.mintick), text_size = size.tiny, text_color = cRed, text_halign = text.align_right, text_valign = d == 1 ? text.align_bottom : text.align_top)
    gTop = na(t) ? e : (d == 1 ? t : e)
    gBot = na(t) ? e : (d == 1 ? e : t)
    gTxt = na(t) ? "Trailing" : "Target  " + str.tostring(t, format.mintick) + "  ·  1:" + str.tostring(rr, "#.##")
    gb = box.new(bar_index, gTop, bar_index + 1, gBot, border_color = color.new(cGreen, 30), bgcolor = color.new(cGreen, 78), text = gTxt, text_size = size.tiny, text_color = cGreen, text_halign = text.align_right, text_valign = d == 1 ? text.align_top : text.align_bottom)
    ls = line.new(bar_index, s, bar_index + 1, s, color = cRed, width = 2)
    [ls, rb, gb]

// ───────────── New day ─────────────
if newDay
    orH := na
    orL := na
    orDone := false
    dayDir := 0
    tradesToday := 0
    needReset := false
    pend := 0
    prevBC := na
    nDays += 1

// ───────────── Opening range ─────────────
inOR = mOpen >= openM and mOpen < orEndM
if inOR
    orH := na(orH) ? high : math.max(orH, high)
    orL := na(orL) ? low : math.min(orL, low)
if inOR and showBox and mOpen == openM
    orBox := box.new(bar_index, high, bar_index, low, border_color = color.new(cWhite, 40), bgcolor = color.new(cWhite, 92), border_width = 1)
if inOR and showBox and not na(orBox)
    box.set_top(orBox, orH)
    box.set_bottom(orBox, orL)
    box.set_right(orBox, bar_index)
if not orDone and not na(orH) and mOpen >= orEndM
    orDone := true
if orDone and showBox and not na(orBox) and mOpen < flatM
    box.set_right(orBox, bar_index)

// running high/low of the confirmation candle
if blockStart or na(bH)
    bH := high
    bL := low
else
    bH := math.max(bH, high)
    bL := math.min(bL, low)

// ───────────── Fill a waiting entry at this candle's open ─────────────
if pend != 0
    eP = pend == 1 ? open + slipPts : open - slipPts
    rkP = openTrade(pend, eP, pendStop)
    if not na(rkP)            // skipped if the open has already gapped through the stop
        pos := pend
        ent := eP
        stp := pendStop
        risk := rkP
        entBar := bar_index - 1   // the breakout candle, so this candle is already managed
        tgt := exitMode == "Trail swings (his)" ? na : (pend == 1 ? eP + rr * rkP : eP - rr * rkP)
        best := eP
        stop0 := pendStop
        if showTrades
            [ls1, rb1, gb1] = drawEntry(pend, eP, stp, tgt)
            lStop := ls1
            rBox := rb1
            gBox := gb1
    pend := 0

// ───────────── Manage open trade ─────────────
float exitPx = na
string exitWhy = ""
if pos != 0 and bar_index > entBar
    // 1) stop / target against the stop that was live when this candle opened
    if pos == 1
        if low <= stp
            exitPx := math.min(open, stp) - slipPts
            exitWhy := "stop"
        else if not na(tgt) and high >= tgt
            exitPx := math.max(open, tgt)
            exitWhy := "target"
    else
        if high >= stp
            exitPx := math.max(open, stp) + slipPts
            exitWhy := "stop"
        else if not na(tgt) and low <= tgt
            exitPx := math.min(open, tgt)
            exitWhy := "target"
    if na(exitPx) and newDay
        exitPx := close[1] - pos * slipPts
        exitWhy := "close"
    if na(exitPx) and mClose >= flatM
        exitPx := close - pos * slipPts
        exitWhy := "close"
    // best price reached (up to the exit price on the exit candle)
    best := pos == 1 ? math.max(best, na(exitPx) ? high : math.min(high, math.max(exitPx, ent))) : math.min(best, na(exitPx) ? low : math.max(low, math.min(exitPx, ent)))
    // 2) a swing that confirmed on THIS candle's close moves the stop for the NEXT candle
    trail = exitMode != "Fixed R:R"
    float newStp = na
    if na(exitPx) and trail and pos == 1 and not na(pL) and bar_index - pivLen > entBar and pL > stp and pL < close
        newStp := pL
    if na(exitPx) and trail and pos == -1 and not na(pH) and bar_index - pivLen > entBar and pH < stp and pH > close
        newStp := pH
    if showTrades
        if not na(lStop)
            line.set_x2(lStop, bar_index)
        box.set_right(rBox, bar_index)
        box.set_right(gBox, bar_index)
        if exitMode == "Trail swings (his)"
            box.set_top(gBox, pos == 1 ? best : ent)
            box.set_bottom(gBox, pos == 1 ? ent : best)
            box.set_text(gBox, "Ran  +" + str.tostring(math.abs(best - ent) / risk, "#.#") + "R")
        if not na(newStp)
            // step the stop line: the old level ends here, the new one starts on this candle
            line.new(bar_index, stp, bar_index, newStp, color = color.new(cRed, 40), width = 1, style = line.style_dotted)
            lStop := line.new(bar_index, newStp, bar_index + 1, newStp, color = cRed, width = 2)
    if not na(newStp)
        stp := newStp

if not na(exitPx)
    [r, p, why] = closeTrade(exitPx, exitWhy)
    nT += 1
    sumR += r
    pts += p
    eqR += r
    peakR := math.max(peakR, eqR)
    maxDD := math.max(maxDD, peakR - eqR)
    isBE = math.abs(r) < 1e-9   // exactly 0R: neither a win nor a loss, streak unchanged
    if isBE
        nBE += 1
    else if r > 0
        nW += 1
        grossW += r
        consec := 0
    else
        grossL += -r
        consec += 1
        maxConsec := math.max(maxConsec, consec)
    if showTrades
        label.new(bar_index, pos == 1 ? high : low, (r >= 0 ? "+" : "") + str.tostring(r, "#.##") + "R", style = pos == 1 ? label.style_label_down : label.style_label_up, color = color.new(isBE ? cGrey : r > 0 ? cGreen : cRed, 15), textcolor = color.black, size = size.tiny)
    pos := 0
    needReset := true
    lStop := na
    rBox := na
    gBox := na

// ───────────── Breaks & entries ─────────────
inside = orDone and close <= orH and close >= orL
if needReset and inside
    needReset := false

canEnter = okTF and orDone and pos == 0 and pend == 0 and blockEnd and mClose >= startM and mClose <= lastM and tradesToday < maxTradesI and not needReset
brokeUp = orDone and blockEnd and close > orH
brokeDn = orDone and blockEnd and close < orL
// direction detection is separate from entry eligibility (see "First break counted from")
firstBreak = dayDir == 0 and (brokeUp or brokeDn) and mClose >= detM
if firstBreak
    nBreakDays += 1
// fresh break: the previous confirmation candle closed inside the range
wasInside = not na(prevBC) and prevBC <= orH and prevBC >= orL
freshOK = freshOnly == "Any close beyond the range" or wasInside
int sig = 0
if canEnter and freshOK and brokeUp and (dayDir == 0 or dayDir == 1 or dirMode == "Either side (each break)")
    sig := 1
if canEnter and freshOK and brokeDn and (dayDir == 0 or dayDir == -1 or dirMode == "Either side (each break)")
    sig := -1
if firstBreak
    dayDir := brokeUp ? 1 : -1
if blockEnd and (inOR or orDone)
    prevBC := close

if sig != 0
    s = stopMode == "Other side of the range" ? (sig == 1 ? orL : orH) : stopMode == "Range midpoint" ? (orH + orL) / 2 : (sig == 1 ? bL : bH)
    tradesToday += 1
    if nextOpen
        pend := sig               // filled at the next candle's open
        pendStop := s
    else
        e = sig == 1 ? close + slipPts : close - slipPts
        rk = openTrade(sig, e, s)
        if not na(rk)
            pos := sig
            ent := e
            stp := s
            risk := rk
            entBar := bar_index
            tgt := exitMode == "Trail swings (his)" ? na : (sig == 1 ? e + rr * rk : e - rr * rk)
            best := e
            stop0 := s
            if showTrades
                [ls2, rb2, gb2] = drawEntry(sig, e, s, tgt)
                lStop := ls2
                rBox := rb2
                gBox := gb2

// range levels after the range candle closes
plot(orDone and mOpen < flatM ? orH : na, "OR high", color = color.new(cGreen, 30), style = plot.style_linebr, linewidth = 1)
plot(orDone and mOpen < flatM ? orL : na, "OR low", color = color.new(cRed, 30), style = plot.style_linebr, linewidth = 1)

// ───────────── Results panel ─────────────
var table pnl = table.new(position.top_right, 2, 15, bgcolor = color.new(cPanel, 8), border_color = color.new(cGrey, 60), border_width = 1)
if showPanel and barstate.islast
    wr = nT > 0 ? 100.0 * nW / nT : 0.0
    pf = grossL > 0 ? grossW / grossL : na
    table.cell(pnl, 0, 0, "BTH · Patrick 15m ORB", text_color = cGreen, text_size = size.small)
    table.cell(pnl, 1, 0, okTF ? "1M ✓" : "SWITCH TO 1-MINUTE CHART", text_color = okTF ? cGreen : cRed, text_size = size.small)
    table.cell(pnl, 0, 1, "Break by · direction", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 1, 1, (blockN == 1 ? "1m close" : str.tostring(blockN) + "m close") + (freshOnly == "Fresh break only" ? " · fresh" : " · any") + " · " + (dirMode == "Locked by the first break" ? (dirFrom == "First break after the range" ? "locked at range" : "locked at entry time") : "either"), text_color = cAmber, text_size = size.small)
    table.cell(pnl, 0, 2, "Stop · exit", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 1, 2, (stopMode == "Breakout candle extreme (his)" ? "candle" : stopMode == "Other side of the range" ? "range side" : "midpoint") + " · " + (exitMode == "Trail swings (his)" ? "trail" : exitMode == "Fixed R:R" ? str.tostring(rr) + "R" : "trail+" + str.tostring(rr) + "R"), text_color = cAmber, text_size = size.small)
    table.cell(pnl, 0, 3, "LOADED HISTORY", text_color = cGreen, text_size = size.small)
    table.cell(pnl, 1, 3, str.tostring(nDays) + " days", text_color = nDays < 20 ? cRed : cWhite, text_size = size.small)
    table.cell(pnl, 0, 4, "Days the range broke", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 1, 4, str.tostring(nBreakDays), text_color = cWhite, text_size = size.small)
    table.cell(pnl, 0, 5, "Trades", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 1, 5, str.tostring(nT) + (nBE > 0 ? "  (" + str.tostring(nBE) + " break-even)" : ""), text_color = cWhite, text_size = size.small)
    table.cell(pnl, 0, 6, "Win rate", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 1, 6, str.tostring(wr, "#.#") + "%", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 0, 7, "Total (R)", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 1, 7, str.tostring(sumR, "#.##") + "R", text_color = sumR >= 0 ? cGreen : cRed, text_size = size.small)
    table.cell(pnl, 0, 8, "Average per trade", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 1, 8, nT > 0 ? str.tostring(sumR / nT, "#.###") + "R" : "—", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 0, 9, "Profit factor", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 1, 9, na(pf) ? "—" : str.tostring(pf, "#.##"), text_color = cWhite, text_size = size.small)
    table.cell(pnl, 0, 10, "Total points", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 1, 10, str.tostring(pts, "#.#"), text_color = pts >= 0 ? cGreen : cRed, text_size = size.small)
    table.cell(pnl, 0, 11, "Max drawdown (R)", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 1, 11, str.tostring(maxDD, "#.##") + "R", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 0, 12, "Worst losing streak", text_color = cWhite, text_size = size.small)
    table.cell(pnl, 1, 12, str.tostring(maxConsec), text_color = cWhite, text_size = size.small)
    table.cell(pnl, 0, 13, "Fills · costs (points)", text_color = cGrey, text_size = size.tiny)
    table.cell(pnl, 1, 13, (nextOpen ? "next open" : "candle close") + " · slip " + str.tostring(slipPts) + " · cost " + str.tostring(commPts), text_color = cGrey, text_size = size.tiny)
    table.cell(pnl, 0, 14, "Visual check", text_color = cGrey, text_size = size.tiny)
    table.cell(pnl, 1, 14, "MT5 EA = final numbers", text_color = cGrey, text_size = size.tiny)

Overview

Patrick 15m Opening Range marks the first 15-minute range, waits for a candle close beyond it, then simulates one trade per day by default with the stop at the breakout candle extreme. Exits can trail swings, use a fixed reward-to-risk target, or combine both. Settings cover session times, entry window, direction lock, fill mode, slippage and cost. It draws boxes, trade markers and a results panel on the price chart, and is built for the 1-minute chart.

Details

Published by

spice2807 on GitHub

Code credit

Backtest the Hype, as written in the script's header

Draws

On the price chart

Markets

Indices

Timeframes

M1-M5

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
TimezonestringAmerica/New_Yorktz
Session open (HHMM)int930openHHMM
Opening range length (minutes)int15orMinutes
Earliest entry (HHMM)int945startHHMM
Last entry (HHMM)int1200lastHHMM
Close every trade by (HHMM)int1555flatHHMM
Break confirmed bystringChart candle (1-minute)confirmTF
Direction for the daystringLocked by the first breakdirMode
First break counted fromstringFirst break after the rangedirFrom
Entry candlestringFresh break onlyfreshOnly
Max trades per dayint1maxTradesI
StopstringBreakout candle extreme (his)stopMode
Show all 21 settings
SettingTypeDefaultVariable
Exit stylestringTrail swings (his)exitMode
R:R target (Fixed / cap)float2.0rr
Swing size for trailing (bars each side)int2pivLen
Entry fillstringNext candle open (realistic)fillMode
Slippage per market fill (points)float0.25slipPts
Commission + spread per trade (points)float0.0commPts
Show opening rangebooltrueshowBox
Show tradesbooltrueshowTrades
Show results panelbooltrueshowPanel
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

IB / ORB Live Stats

by TamaraKGreen
46 stars

This overlay indicator marks the New York initial balance and a configurable opening range on the price chart and reports live range statistics in two tables. It builds an IB box for a default 09:30–10:30 ET window, an ORB box from 09:30 for a set number of mi

Indicator v6 Sessions & timeBreakout
Updated 7 weeks ago · None stated GitHub repository of IB / ORB Live Stats

Zen-DAX GX

by Zen-Tim
29 stars

This indicator calculates and plots session ranges and key breakout levels for DAX futures directly on the price chart. It defines the overnight Globex session, the Frankfurt pre-market range, and the regular trading hours open using European timezone settings

Indicator v5 Sessions & timeBreakout
Updated 2 weeks ago · MIT GitHub repository of Zen-DAX GX
23 stars

Point-Clip Unified Indicator plots breakout and directional labels on the price chart. It scores volume spikes against a volume average, range or opening-range breaks, optional VWAP or session-anchored VWAP, fast and slow EMA trend, and a higher-timeframe EMA

Indicator v6 BreakoutVolume Repaints
Updated 3 weeks ago · Custom licence GitHub repository of Point-Clip Unified Indicator

ORB Multi-Model Indicator

by Mrshahidali420
16 stars

This indicator plots several New York opening-range breakout models on the price chart and can also show a combined confidence-scored signal. Enabled models include classic Crabel, a five-minute scalper, a standard fifteen-minute breakout, and a gold variant,

Indicator v6 BreakoutSessions & time Repaints
Updated 3 months ago · None stated GitHub repository of ORB Multi-Model Indicator

Nexural ORB

by JasonTeixeira
9 stars

This indicator plots opening range breakout levels across multiple timeframes, including five, fifteen, thirty, and sixty minutes, directly on the price chart. It also displays the session open and overnight high and low levels. The script calculates an openin

Indicator v6 BreakoutSessions & time
Updated 13 days ago · Custom licence GitHub repository of Nexural ORB

FX Market Sessions

by itmakesyousick
7 stars

FX Market Sessions highlights distinct trading sessions, such as London, New York, and Tokyo, directly on the main price chart. It draws background boxes for each active session and optionally plots opening ranges, Fibonacci retracement levels, and session ext

Indicator v5 Sessions & timeSupport & resistance
Updated 3 years ago · None stated GitHub repository of FX Market Sessions

More Breakout scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers