//@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)