ORB

//@version=6
indicator("ORB_RD", overlay = true)

// ORB_RD - Opening Range Box (Ryan DeBraal)
// This indicator automatically draws a high/low box for the first portion of
// each trading day, stepping the range window from 15 to 30 minutes after
// the session starts. The box updates live as the range forms, then
// optionally extends across the rest of the session.
//
// FEATURES
// -----------------------------------------------------------------------------
// • Opening Range Detection
//     - Automatically ladders the range window: 0-15, then 0-30 minutes
//     - Automatic reset at each new trading day
//     - Live high/low updates while inside the 0-30 minute window
//
// • Auto-Drawing Range Box
//     - Draws a dynamic rectangle as the range forms
//     - Top and bottom update with every new high/low
//     - Extends sideways in real time during formation
//     - Optional full-day extension after the 30-minute range finalizes
//
// • Customizable Visuals
//     - Adjustable fill transparency
//     - Mild green tint by default for clarity
//
// PURPOSE
// -----------------------------------------------------------------------------
// This tool highlights the evolving opening range, a widely used intraday
// reference for breakout traders, mean-reversion setups, and session structure
// analysis. Ideal for:
//      • Identifying early support and resistance
//      • Framing breakout and pullback decisions
//      • Tracking intraday trend bias after the morning range

extend_today = input.bool(true, "Extend today's box across day")
fill_transp  = input.int(95, "Box transparency", minval = 0, maxval = 100)
box_color    = color.new(color.green, 80)

var int   first_bar_index = na
var int   day_start_ts    = na
var float rng_hi          = na
var float rng_lo          = na
var box   rng_box         = na

new_day = ta.change(time("D")) != 0

if new_day
    // New day starts: clear old box and start a new 0-15 minute laddered window
    if not na(rng_box)
        box.delete(rng_box)
        rng_box := na
    first_bar_index := bar_index
    rng_hi          := high
    rng_lo          := low
    day_start_ts    := time

// Compute elapsed minutes since the first bar of the day
elapsed_ms  = not na(day_start_ts) ? time - day_start_ts : 0
elapsed_min = elapsed_ms / 60000.0

// Active opening range window: update from 0-15 and 0-30 minutes
in_window = elapsed_min <= 30

if in_window
    // While inside the first 30 minutes, keep updating the growing range
    rng_hi := na(rng_hi) ? high : math.max(rng_hi, high)
    rng_lo := na(rng_lo) ? low  : math.min(rng_lo, low)

    if na(rng_box)
        rng_box := box.new(left = first_bar_index, top = rng_hi, right = bar_index, bottom = rng_lo, xloc = xloc.bar_index, border_color = box_color, bgcolor = color.new(box_color, fill_transp))
    else
        box.set_top(rng_box, rng_hi)
        box.set_bottom(rng_box, rng_lo)
        box.set_right(rng_box, bar_index)

// After the 30-minute window ends, just extend the finalized box to the right if desired
if extend_today and not na(rng_box) and not in_window
    box.set_right(rng_box, bar_index)