Indicator · Pine Script v6 · On the chart

NWOG + ORG

by traderdiegox

This overlay indicator draws the new week opening gap and the opening range gap on the price chart.

View on GitHub

Repaints

GitHub stars16on the repository
Pine versionv6current
Lines of code594
Settings40inputs
LicenceNone statedfile: MPL-2.0
Last update6 months ago15 Apr 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

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

NWOG.pine
// This source code is subject to the terms of the Mozilla Public License 2.0
// https://mozilla.org/MPL/2.0/
// © traderdiegox
// Portions derived from cryptonnnite (NWOG/NDOG), © cryptonnnite, MPL 2.0

//@version=6
indicator("NWOG + ORG", shorttitle="NWOG/ORG", overlay=true,
          max_boxes_count=500, max_lines_count=500, max_labels_count=500)

// ═══════════════════════════════════════════════════════════════════════════
//  NEW WEEK OPENING GAP — INPUTS
// ═══════════════════════════════════════════════════════════════════════════
string G = "NEW WEEK OPENING GAP"

show_zone = input.bool(true,  "Show NWOG",      group=G, inline="1")
zone_col  = input.color(color.new(color.red, 75), "", group=G, inline="1")

nwog_bdr_col   = input.color(color.new(color.red, 0), "Border", group=G, inline="2")
nwog_bdr_sty   = input.string("None", "",             group=G, inline="2", options=["None","Solid","Dashed","Dotted"])
nwog_bdr_width = input.int(1, "",                     group=G, inline="2", minval=1, maxval=4)

show_prev = input.bool(false, "Previous NWOGs", group=G, inline="3")
n_prev    = input.int(1,    "",               group=G, inline="3", minval=1, maxval=10)
prev_col  = input.color(color.new(#26A69A, 75), "", group=G, inline="3")

show_ce   = input.bool(true,  "NWOG Midpoint", group=G, inline="4")
ce_sty_in = input.string("Dashed", "",          group=G, inline="4", options=["Solid","Dashed","Dotted"])
ce_col    = input.color(color.red, "",           group=G, inline="4")

show_lbl  = input.bool(true,    "Label", group=G, inline="5")
lbl_h     = input.string("Right", "",    group=G, inline="5", options=["Left","Center","Right"])
lbl_v     = input.string("Top",   "",    group=G, inline="5", options=["Top","Middle","Bottom"])
lbl_sz_in = input.string("Small", "",    group=G, inline="5", options=["Tiny","Small","Normal","Large"])
lbl_col   = input.color(color.black, "", group=G, inline="5")

ext_prev = input.bool(true, "Extend Previous NWOGs", group=G)

int eff_prev = show_prev ? n_prev : 0

// ═══════════════════════════════════════════════════════════════════════════
//  OPENING RANGE GAP — INPUTS
// ═══════════════════════════════════════════════════════════════════════════
string G2 = "OPENING RANGE GAP"

show_org      = input.bool(true,  "Show ORG",       group=G2, inline="o1")
org_col       = input.color(color.new(color.green, 75), "", group=G2, inline="o1")

org_bdr_col   = input.color(color.new(color.green, 0), "Border", group=G2, inline="o2")
org_bdr_sty   = input.string("None", "",               group=G2, inline="o2", options=["None","Solid","Dashed","Dotted"])
org_bdr_width = input.int(1, "",                       group=G2, inline="o2", minval=1, maxval=4)

show_prev_org = input.bool(false, "Previous ORGs",  group=G2, inline="o3")
n_prev_org    = input.int(1, "",                    group=G2, inline="o3", minval=1, maxval=4)
prev_org_col  = input.color(color.new(#9C27B0, 75), "", group=G2, inline="o3")

show_org_ce   = input.bool(true,  "ORG Midpoint",   group=G2, inline="o4")
org_ce_sty_in = input.string("Dashed", "",          group=G2, inline="o4", options=["Solid","Dashed","Dotted"])
org_ce_col    = input.color(color.green, "",         group=G2, inline="o4")

show_org_lbl  = input.bool(true,  "Label",          group=G2, inline="o5")
org_lbl_h     = input.string("Right", "",           group=G2, inline="o5", options=["Left","Center","Right"])
org_lbl_v     = input.string("Top",   "",           group=G2, inline="o5", options=["Top","Middle","Bottom"])
org_lbl_sz_in = input.string("Small", "",           group=G2, inline="o5", options=["Tiny","Small","Normal","Large"])
org_lbl_col   = input.color(color.black, "", group=G2, inline="o5")

ext_prev_org  = input.bool(true, "Extend Previous ORGs", group=G2)

int eff_prev_org = show_prev_org ? n_prev_org : 0

// ═══════════════════════════════════════════════════════════════════════════
//  GENERAL
// ═══════════════════════════════════════════════════════════════════════════
string G3 = "GENERAL"
extend_bars  = input.int(5,   "Extend boxes (bars)", group=G3, minval=0, maxval=500)
mid_show     = input.bool(true, "Midnight Open",     group=G3, inline="mid")
mid_col      = input.color(color.new(color.gray, 50), "", group=G3, inline="mid")
mid_sty_in   = input.string("Solid", "",             group=G3, inline="mid", options=["Solid","Dashed","Dotted"])
mid_width    = input.int(1, "",                      group=G3, inline="mid", minval=1, maxval=4)
mid_prev     = input.int(10, "Previous Midnight Opens", group=G3, minval=0, maxval=50)
sun_show     = input.bool(true, "Sunday Open",       group=G3, inline="sun")
sun_col      = input.color(color.new(color.orange, 50), "", group=G3, inline="sun")
sun_sty_in   = input.string("Solid", "",             group=G3, inline="sun", options=["Solid","Dashed","Dotted"])
sun_width    = input.int(1, "",                      group=G3, inline="sun", minval=1, maxval=4)
sun_prev     = input.int(10, "Previous Sunday Open Lines", group=G3, minval=0, maxval=50)

// ═══════════════════════════════════════════════════════════════════════════
//  ORG STATS TABLE — INPUTS
// ═══════════════════════════════════════════════════════════════════════════
string G4     = "ORG STATS"
stats_show    = input.bool(true,  "Show ORG Fill Table",  group=G4)
stats_days    = input.int(20,     "Lookback (days)",       group=G4, minval=1, maxval=252)
stats_pos_in  = input.string("Top Right", "Position",     group=G4, options=["Top Right","Top Left","Top Center","Bottom Right","Bottom Left","Bottom Center","Middle Right","Middle Left"])
stats_sz_in   = input.string("Small", "Text Size",        group=G4, options=["Tiny","Small","Normal","Large"])
stats_txt_col = input.color(color.white,                  "Text",     group=G4, inline="sc")
stats_hdr_col = input.color(color.new(color.green, 30),  "Header",   group=G4, inline="sc")
stats_hdr_txt = input.color(color.white,                  "Hdr Text", group=G4, inline="sc")
stats_bg_col  = input.color(color.new(color.black, 20),  "BG",       group=G4, inline="sc")

// ═══════════════════════════════════════════════════════════════════════════
//  NWOG — STYLE
// ═══════════════════════════════════════════════════════════════════════════
ce_ls = switch ce_sty_in
    "Solid"  => line.style_solid
    "Dashed" => line.style_dashed
    =>          line.style_dotted

lbl_sz = switch lbl_sz_in
    "Tiny"   => size.tiny
    "Small"  => size.small
    "Normal" => size.normal
    =>          size.large

lbl_halign = switch lbl_h
    "Left"   => text.align_left
    "Center" => text.align_center
    =>          text.align_right

lbl_valign = switch lbl_v
    "Top"    => text.align_top
    "Middle" => text.align_center
    =>          text.align_bottom

int  nwog_bw           = nwog_bdr_sty == "None" ? 0 : nwog_bdr_width
nwog_border_style      = switch nwog_bdr_sty
    "Dashed" => line.style_dashed
    "Dotted" => line.style_dotted
    =>          line.style_solid

// ═══════════════════════════════════════════════════════════════════════════
//  ORG — STYLE
// ═══════════════════════════════════════════════════════════════════════════
org_ce_ls = switch org_ce_sty_in
    "Solid"  => line.style_solid
    "Dashed" => line.style_dashed
    =>          line.style_dotted

org_lbl_sz = switch org_lbl_sz_in
    "Tiny"   => size.tiny
    "Small"  => size.small
    "Normal" => size.normal
    =>          size.large

org_lbl_halign = switch org_lbl_h
    "Left"   => text.align_left
    "Center" => text.align_center
    =>          text.align_right

org_lbl_valign = switch org_lbl_v
    "Top"    => text.align_top
    "Middle" => text.align_center
    =>          text.align_bottom

int  org_bw            = org_bdr_sty == "None" ? 0 : org_bdr_width
org_border_style       = switch org_bdr_sty
    "Dashed" => line.style_dashed
    "Dotted" => line.style_dotted
    =>          line.style_solid

mid_ls = switch mid_sty_in
    "Dashed" => line.style_dashed
    "Dotted" => line.style_dotted
    =>          line.style_solid

sun_ls = switch sun_sty_in
    "Dashed" => line.style_dashed
    "Dotted" => line.style_dotted
    =>          line.style_solid

stats_sz = switch stats_sz_in
    "Tiny"   => size.tiny
    "Normal" => size.normal
    "Large"  => size.large
    =>          size.small

stats_tbl_pos = switch stats_pos_in
    "Top Left"      => position.top_left
    "Top Center"    => position.top_center
    "Bottom Right"  => position.bottom_right
    "Bottom Left"   => position.bottom_left
    "Bottom Center" => position.bottom_center
    "Middle Right"  => position.middle_right
    "Middle Left"   => position.middle_left
    =>                 position.top_right

// ─── Helper: format a stats table cell ────────────────────────────────────
f_cell(int cnt, int n) =>
    n == 0 ? "—" : str.tostring(cnt) + "/" + str.tostring(n) + "  " + str.tostring(math.round(cnt * 100.0 / n)) + "%"

// ═══════════════════════════════════════════════════════════════════════════
//  SECURITY CALLS
// ═══════════════════════════════════════════════════════════════════════════

// NWOG — weekly ETH timestamps + 4H price override
int wk_t_start = request.security(syminfo.tickerid, "1W", time,       lookahead=barmerge.lookahead_on)
int wk_t_end   = request.security(syminfo.tickerid, "1W", time_close, lookahead=barmerge.lookahead_on)
[isNewWeek_4h, h4_prev, h4_open] = request.security(syminfo.tickerid, "240", [ta.change(time("W")) != 0, close[1], open], lookahead=barmerge.lookahead_on)

// ORG — 15-min bar data fetched as plain scalars; ta.change() evaluated at CHART level
// so is_at_930am / is_at_415pm fire exactly once per new 15-min period (not every sub-bar)
int   time_15m       = request.security(syminfo.tickerid, "15", time,       lookahead=barmerge.lookahead_on)
int   time_close_15m = request.security(syminfo.tickerid, "15", time_close, lookahead=barmerge.lookahead_on)
float open_15m       = request.security(syminfo.tickerid, "15", open,       lookahead=barmerge.lookahead_on)
float close_15m      = request.security(syminfo.tickerid, "15", close,      lookahead=barmerge.lookahead_on)
float high_15m       = request.security(syminfo.tickerid, "15", high,       lookahead=barmerge.lookahead_on)
float low_15m        = request.security(syminfo.tickerid, "15", low,        lookahead=barmerge.lookahead_on)

bool is_new_15m  = ta.change(time_15m) != 0
bool is_at_930am = is_new_15m and hour(time_15m, "America/New_York") == 9  and minute(time_15m, "America/New_York") == 30
bool is_at_415pm = is_new_15m and hour(time_15m, "America/New_York") == 16 and minute(time_15m, "America/New_York") == 0
bool is_at_noon  = is_new_15m and hour(time_15m, "America/New_York") == 12 and minute(time_15m, "America/New_York") == 0

int ts_930 = time_15m  // 9:30am bar timestamp — used as box left edge

// ═══════════════════════════════════════════════════════════════════════════
//  GAP DETECTION & PRICES
// ═══════════════════════════════════════════════════════════════════════════
bool is_new_week    = ta.change(time("W")) != 0
bool is_day_change  = ta.change(dayofmonth(time, "America/New_York")) != 0
bool is_midnight    = is_day_change and hour(time, "America/New_York") == 0
bool is_sunday_open = is_day_change and dayofweek(time, "America/New_York") == dayofweek.sunday

float box_h = timeframe.multiplier < 60 and isNewWeek_4h ? math.max(h4_prev, h4_open) : math.max(close[1], open)
float box_l = timeframe.multiplier < 60 and isNewWeek_4h ? math.min(h4_prev, h4_open) : math.min(close[1], open)

// Saved RTH boundary prices (persist across bars)
var float prev_rth_close   = na  // 4:15pm close saved here each day
var int   prev_rth_close_t = na  // 4:15pm timestamp

// ═══════════════════════════════════════════════════════════════════════════
//  PERSISTENT ARRAYS
// ═══════════════════════════════════════════════════════════════════════════

// NWOG
var float[] a_h   = array.new_float()
var float[] a_l   = array.new_float()
var box[]   a_box = array.new_box()
var line[]  a_ce  = array.new_line()

// Midnight lines
var line[] mid_lines = array.new_line()
var line[] sun_lines = array.new_line()

// ORG
var float[] org_ah        = array.new_float()
var float[] org_al        = array.new_float()
var box[]   org_box       = array.new_box()   // filled box: 9:30am → latest candle
var box[]   org_connector = array.new_box()   // border-only box: 4:15pm → 9:30am
var line[]  org_ace       = array.new_line()

// ORG STATS — per-day tracking state
var float trk_org_h      = na
var float trk_org_l      = na
var bool  trk_gap_up     = true
var float trk_am_h       = na
var float trk_am_l       = na
var float trk_day_h      = na
var float trk_day_l      = na
var float trk_am_h_saved = na
var float trk_am_l_saved = na
var bool  trk_noon_done  = false

// ORG STATS — result history (one entry per completed day)
var bool[] res_am_25   = array.new_bool()
var bool[] res_am_50   = array.new_bool()
var bool[] res_am_100  = array.new_bool()
var bool[] res_day_25  = array.new_bool()
var bool[] res_day_50  = array.new_bool()
var bool[] res_day_100 = array.new_bool()

// ORG STATS — table
var table stats_tbl = na

// ═══════════════════════════════════════════════════════════════════════════
//  LATEST BAR EXTENSION TIMESTAMP (used by all draw blocks)
// ═══════════════════════════════════════════════════════════════════════════
int latest_t = time + timeframe.in_seconds() * 1000 * (extend_bars + 1)

// ═══════════════════════════════════════════════════════════════════════════
//  NWOG — DRAW ON NEW WEEK
// ═══════════════════════════════════════════════════════════════════════════
if is_new_week and (timeframe.isintraday or timeframe.isdaily) and box_h != box_l and not na(box_h)
    float mid = (box_h + box_l) / 2.0

    array.push(a_h,   box_h)
    array.push(a_l,   box_l)
    array.push(a_box, box.new(wk_t_start, box_h, wk_t_end, box_l, xloc=xloc.bar_time, bgcolor=show_zone ? zone_col : na, border_color=show_zone ? nwog_bdr_col : na, border_width=nwog_bw, border_style=nwog_border_style, text=show_lbl ? "NWOG" : "", text_size=lbl_sz, text_halign=lbl_halign, text_valign=lbl_valign, text_color=lbl_col))

    if show_ce
        array.push(a_ce, line.new(wk_t_start, mid, wk_t_end, mid, xloc=xloc.bar_time, color=ce_col, style=ce_ls, width=1))

    if array.size(a_box) > eff_prev + 1
        array.shift(a_h)
        array.shift(a_l)
        box.delete(array.shift(a_box))
    if show_ce and array.size(a_ce) > eff_prev + 1
        line.delete(array.shift(a_ce))

// ═══════════════════════════════════════════════════════════════════════════
//  ORG STATS — START TRACKING AT 9:30AM
// ═══════════════════════════════════════════════════════════════════════════
if is_at_930am and not na(prev_rth_close)
    float s_h = math.max(prev_rth_close, open_15m)
    float s_l = math.min(prev_rth_close, open_15m)
    if s_h != s_l
        trk_org_h     := s_h
        trk_org_l     := s_l
        trk_gap_up    := open_15m > prev_rth_close
        trk_am_h      := open_15m
        trk_am_l      := open_15m
        trk_day_h     := open_15m
        trk_day_l     := open_15m
        trk_noon_done := false

// ═══════════════════════════════════════════════════════════════════════════
//  ORG STATS — UPDATE INTRADAY HIGH/LOW (every new 15-min bar)
// ═══════════════════════════════════════════════════════════════════════════
if is_new_15m and not na(trk_org_h) and timeframe.isintraday
    int h_et  = hour(time_15m,   "America/New_York")
    int m_et  = minute(time_15m, "America/New_York")
    // RTH window: 9:30am up to and including the 4:00pm bar (closes 4:15pm)
    bool in_rth = (h_et == 9 and m_et >= 30) or (h_et >= 10 and h_et < 16) or (h_et == 16 and m_et == 0)
    bool in_am  = in_rth and h_et < 12
    if in_rth
        trk_day_h := math.max(trk_day_h, high_15m)
        trk_day_l := math.min(trk_day_l, low_15m)
    if in_am and not trk_noon_done
        trk_am_h := math.max(trk_am_h, high_15m)
        trk_am_l := math.min(trk_am_l, low_15m)

// ═══════════════════════════════════════════════════════════════════════════
//  ORG STATS — FREEZE AM RESULT AT NOON
// ═══════════════════════════════════════════════════════════════════════════
if is_at_noon and not na(trk_org_h) and not trk_noon_done
    trk_am_h_saved := trk_am_h
    trk_am_l_saved := trk_am_l
    trk_noon_done  := true

// ═══════════════════════════════════════════════════════════════════════════
//  ORG STATS — EVALUATE FILLS AT 4:15PM
// ═══════════════════════════════════════════════════════════════════════════
if is_at_415pm and not na(trk_org_h)
    float gap = trk_org_h - trk_org_l
    if gap > 0
        float am_h  = trk_noon_done ? trk_am_h_saved : trk_am_h
        float am_l  = trk_noon_done ? trk_am_l_saved : trk_am_l
        bool am25  = false
        bool am50  = false
        bool am100 = false
        bool d25   = false
        bool d50   = false
        bool d100  = false
        if trk_gap_up
            // Gap up: fill = price retracing down into the gap
            am25  := am_l      <= trk_org_h - 0.25 * gap
            am50  := am_l      <= trk_org_h - 0.50 * gap
            am100 := am_l      <= trk_org_l
            d25   := trk_day_l <= trk_org_h - 0.25 * gap
            d50   := trk_day_l <= trk_org_h - 0.50 * gap
            d100  := trk_day_l <= trk_org_l
        else
            // Gap down: fill = price retracing up into the gap
            am25  := am_h      >= trk_org_l + 0.25 * gap
            am50  := am_h      >= trk_org_l + 0.50 * gap
            am100 := am_h      >= trk_org_h
            d25   := trk_day_h >= trk_org_l + 0.25 * gap
            d50   := trk_day_h >= trk_org_l + 0.50 * gap
            d100  := trk_day_h >= trk_org_h
        array.push(res_am_25,   am25)
        array.push(res_am_50,   am50)
        array.push(res_am_100,  am100)
        array.push(res_day_25,  d25)
        array.push(res_day_50,  d50)
        array.push(res_day_100, d100)
    trk_org_h := na
    trk_org_l := na

// ═══════════════════════════════════════════════════════════════════════════
//  ORG — SAVE 4:15PM CLOSE EACH DAY
// ═══════════════════════════════════════════════════════════════════════════
if is_at_415pm
    prev_rth_close   := close_15m
    prev_rth_close_t := time_close_15m

// ═══════════════════════════════════════════════════════════════════════════
//  ORG — RESET DISPLAY ON NEW WEEK (keep saved prices for Monday's ORG)
// ═══════════════════════════════════════════════════════════════════════════
if is_new_week
    int n = array.size(org_box)
    if n > 0
        for i = 0 to n - 1
            box.delete(array.get(org_box, i))
    n := array.size(org_connector)
    if n > 0
        for i = 0 to n - 1
            box.delete(array.get(org_connector, i))
    n := array.size(org_ace)
    if n > 0
        for i = 0 to n - 1
            line.delete(array.get(org_ace, i))
    array.clear(org_ah)
    array.clear(org_al)
    array.clear(org_box)
    array.clear(org_connector)
    array.clear(org_ace)

// ═══════════════════════════════════════════════════════════════════════════
//  ORG — DRAW AT 9:30AM (only after RTH open, using saved 4:15pm close)
// ═══════════════════════════════════════════════════════════════════════════
if is_at_930am and not na(prev_rth_close) and (timeframe.isintraday or timeframe.isdaily)
    float org_h_val = math.max(prev_rth_close, open_15m)
    float org_l_val = math.min(prev_rth_close, open_15m)
    if org_h_val != org_l_val
        float org_mid = (org_h_val + org_l_val) / 2.0

        array.push(org_ah, org_h_val)
        array.push(org_al, org_l_val)

        // Border-only connector: 4:15pm → 9:30am (shows the overnight gap range)
        array.push(org_connector, box.new(prev_rth_close_t, org_h_val, ts_930, org_l_val, xloc=xloc.bar_time, bgcolor=na, border_width=1, border_color=show_org ? org_col : na))

        // Filled box: 9:30am → latest candle (extended every bar)
        array.push(org_box, box.new(ts_930, org_h_val, latest_t, org_l_val, xloc=xloc.bar_time, bgcolor=show_org ? org_col : na, border_color=show_org ? org_bdr_col : na, border_width=org_bw, border_style=org_border_style, text=show_org_lbl ? "ORG" : "", text_size=org_lbl_sz, text_halign=org_lbl_halign, text_valign=org_lbl_valign, text_color=org_lbl_col))

        if show_org_ce
            array.push(org_ace, line.new(ts_930, org_mid, latest_t, org_mid, xloc=xloc.bar_time, color=org_ce_col, style=org_ce_ls, width=1))

        if array.size(org_box) > eff_prev_org + 1
            array.shift(org_ah)
            array.shift(org_al)
            box.delete(array.shift(org_box))
            box.delete(array.shift(org_connector))
        if show_org_ce and array.size(org_ace) > eff_prev_org + 1
            line.delete(array.shift(org_ace))

// ═══════════════════════════════════════════════════════════════════════════
//  NWOG — EVERY BAR: lock prices + extend to latest candle
// ═══════════════════════════════════════════════════════════════════════════
int nb = array.size(a_box)
if nb > 0
    int nc = array.size(a_ce)
    for i = 0 to nb - 1
        bool is_cur = i == nb - 1
        box.set_top(   array.get(a_box, i), array.get(a_h, i))
        box.set_bottom(array.get(a_box, i), array.get(a_l, i))
        if is_cur or ext_prev
            box.set_right(array.get(a_box, i), latest_t)
        box.set_bgcolor(      array.get(a_box, i), show_zone ? (is_cur ? zone_col : prev_col) : na)
        box.set_border_color( array.get(a_box, i), show_zone ? (is_cur ? nwog_bdr_col : prev_col) : na)
        box.set_border_width( array.get(a_box, i), show_zone ? nwog_bw : 0)
        box.set_border_style( array.get(a_box, i), nwog_border_style)
        box.set_text(         array.get(a_box, i), show_zone and show_lbl ? (is_cur ? "NWOG" : "NWOG -" + str.tostring(nb - 1 - i)) : "")
    if nc > 0
        for i = 0 to nc - 1
            if i == nc - 1 or ext_prev
                line.set_x2(array.get(a_ce, i), latest_t)
            line.set_color(array.get(a_ce, i), show_zone ? (i == nc - 1 ? ce_col : prev_col) : na)

// ═══════════════════════════════════════════════════════════════════════════
//  ORG — EVERY BAR: lock prices + extend to latest candle
// ═══════════════════════════════════════════════════════════════════════════
int nb_org = array.size(org_box)
if nb_org > 0
    int nc_org = array.size(org_ace)
    for i = 0 to nb_org - 1
        bool  is_cur_org  = i == nb_org - 1
        color org_zone_col = show_org ? (is_cur_org ? org_col : prev_org_col) : na

        // Filled box
        box.set_top(   array.get(org_box, i), array.get(org_ah, i))
        box.set_bottom(array.get(org_box, i), array.get(org_al, i))
        if is_cur_org or ext_prev_org
            box.set_right(array.get(org_box, i), latest_t)
        box.set_bgcolor(      array.get(org_box, i), org_zone_col)
        box.set_border_color( array.get(org_box, i), show_org ? (is_cur_org ? org_bdr_col : prev_org_col) : na)
        box.set_border_width( array.get(org_box, i), show_org ? org_bw : 0)
        box.set_border_style( array.get(org_box, i), org_border_style)
        box.set_text(         array.get(org_box, i), show_org and show_org_lbl ? (is_cur_org ? "ORG" : "ORG -" + str.tostring(nb_org - 1 - i)) : "")

        // Connector box (lock prices + sync border color)
        box.set_top(          array.get(org_connector, i), array.get(org_ah, i))
        box.set_bottom(       array.get(org_connector, i), array.get(org_al, i))
        box.set_border_color( array.get(org_connector, i), org_zone_col)

    if nc_org > 0
        for i = 0 to nc_org - 1
            if i == nc_org - 1 or ext_prev_org
                line.set_x2(array.get(org_ace, i), latest_t)
            line.set_color(array.get(org_ace, i), show_org ? (i == nc_org - 1 ? org_ce_col : prev_org_col) : na)

// ═══════════════════════════════════════════════════════════════════════════
//  MIDNIGHT LINE — DRAW ON NEW DAY (ET timezone)
// ═══════════════════════════════════════════════════════════════════════════
if is_midnight and timeframe.isintraday
    array.push(mid_lines, line.new(time, high, time, low, xloc=xloc.bar_time, extend=extend.both, color=mid_show ? mid_col : na, style=mid_ls, width=mid_width))

// MIDNIGHT LINE — EVERY BAR: trim to count, sync color/style changes
int nm = array.size(mid_lines)
if nm > mid_prev
    int mid_excess = nm - mid_prev
    for _i = 0 to mid_excess - 1
        line.delete(array.shift(mid_lines))
    nm := array.size(mid_lines)
if nm > 0
    for i = 0 to nm - 1
        line.set_color(array.get(mid_lines, i), mid_show ? mid_col : na)
        line.set_style(array.get(mid_lines, i), mid_ls)
        line.set_width(array.get(mid_lines, i), mid_width)

// ═══════════════════════════════════════════════════════════════════════════
//  SUNDAY OPEN LINE — DRAW AT 18:00 ET SUNDAY
// ═══════════════════════════════════════════════════════════════════════════
if is_sunday_open and timeframe.isintraday
    array.push(sun_lines, line.new(time, high, time, low, xloc=xloc.bar_time, extend=extend.both, color=sun_show ? sun_col : na, style=sun_ls, width=sun_width))

// SUNDAY OPEN LINE — EVERY BAR: trim to count, sync color/style changes
int ns = array.size(sun_lines)
if ns > sun_prev
    int sun_excess = ns - sun_prev
    for _i = 0 to sun_excess - 1
        line.delete(array.shift(sun_lines))
    ns := array.size(sun_lines)
if ns > 0
    for i = 0 to ns - 1
        line.set_color(array.get(sun_lines, i), sun_show ? sun_col : na)
        line.set_style(array.get(sun_lines, i), sun_ls)
        line.set_width(array.get(sun_lines, i), sun_width)

// ═══════════════════════════════════════════════════════════════════════════
//  ORG STATS — TABLE (rendered on last bar only)
// ═══════════════════════════════════════════════════════════════════════════
if barstate.islast
    if stats_show and timeframe.isintraday
        int n_data  = array.size(res_day_25)
        int lb      = math.min(n_data, stats_days)
        int off     = n_data - lb
        int cnt_d25  = 0
        int cnt_d50  = 0
        int cnt_d100 = 0
        int cnt_a25  = 0
        int cnt_a50  = 0
        int cnt_a100 = 0
        if lb > 0
            for i = off to n_data - 1
                if array.get(res_day_25,  i)
                    cnt_d25  += 1
                if array.get(res_day_50,  i)
                    cnt_d50  += 1
                if array.get(res_day_100, i)
                    cnt_d100 += 1
                if array.get(res_am_25,   i)
                    cnt_a25  += 1
                if array.get(res_am_50,   i)
                    cnt_a50  += 1
                if array.get(res_am_100,  i)
                    cnt_a100 += 1
        if na(stats_tbl)
            stats_tbl := table.new(stats_tbl_pos, 3, 4,
                 bgcolor=stats_bg_col,
                 border_color=color.new(color.gray, 60), border_width=1,
                 frame_color=color.new(color.gray, 40),  frame_width=1)
        // Row 0: header (title + column labels)
        table.cell(stats_tbl, 0, 0, "ORG Fill (" + str.tostring(lb) + "d)",
             text_color=stats_hdr_txt, text_size=stats_sz,
             bgcolor=stats_hdr_col, text_halign=text.align_center)
        table.cell(stats_tbl, 1, 0, "Same Day\n9:30–4:15",
             text_color=stats_hdr_txt, text_size=stats_sz,
             bgcolor=stats_hdr_col, text_halign=text.align_center)
        table.cell(stats_tbl, 2, 0, "AM Session\n9:30–12:00",
             text_color=stats_hdr_txt, text_size=stats_sz,
             bgcolor=stats_hdr_col, text_halign=text.align_center)
        // Row 1: ≥ 25%
        table.cell(stats_tbl, 0, 1, "≥ 25%",
             text_color=stats_txt_col, text_size=stats_sz, text_halign=text.align_left)
        table.cell(stats_tbl, 1, 1, f_cell(cnt_d25,  lb),
             text_color=stats_txt_col, text_size=stats_sz, text_halign=text.align_center)
        table.cell(stats_tbl, 2, 1, f_cell(cnt_a25,  lb),
             text_color=stats_txt_col, text_size=stats_sz, text_halign=text.align_center)
        // Row 2: ≥ 50%
        table.cell(stats_tbl, 0, 2, "≥ 50%",
             text_color=stats_txt_col, text_size=stats_sz, text_halign=text.align_left)
        table.cell(stats_tbl, 1, 2, f_cell(cnt_d50,  lb),
             text_color=stats_txt_col, text_size=stats_sz, text_halign=text.align_center)
        table.cell(stats_tbl, 2, 2, f_cell(cnt_a50,  lb),
             text_color=stats_txt_col, text_size=stats_sz, text_halign=text.align_center)
        // Row 3: 100%
        table.cell(stats_tbl, 0, 3, "100%",
             text_color=stats_txt_col, text_size=stats_sz, text_halign=text.align_left)
        table.cell(stats_tbl, 1, 3, f_cell(cnt_d100, lb),
             text_color=stats_txt_col, text_size=stats_sz, text_halign=text.align_center)
        table.cell(stats_tbl, 2, 3, f_cell(cnt_a100, lb),
             text_color=stats_txt_col, text_size=stats_sz, text_halign=text.align_center)
    else if not na(stats_tbl)
        table.delete(stats_tbl)
        stats_tbl := na

Overview

NWOG + ORG paints each gap as a colored zone with optional borders, a dashed midpoint line, and a text label. Users can hide either gap, change colors and border style, and keep a limited number of earlier gaps, with previous new week gaps optionally extended. It does not generate trade entries or exits. Higher-timeframe gap detection uses lookahead.

Details

Published by

traderdiegox on GitHub

Type

Indicator, Pine Script v6

Draws

On the price chart

Category

SMC / ICT / price action, Support & resistance, Sessions & time

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

  • Reads higher-timeframe data with lookahead on, so the history can show signals that were not there in real time

Settings

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

SettingTypeDefaultVariable
Show NWOGbooltrueshow_zone
zone_colcolorcolor.new(color.red, 75)zone_col
Bordercolorcolor.new(color.red, 0)nwog_bdr_col
nwog_bdr_stystringNonenwog_bdr_sty
nwog_bdr_widthint1nwog_bdr_width
Previous NWOGsboolfalseshow_prev
n_prevint1n_prev
prev_colcolorcolor.new(#26A69A, 75)prev_col
NWOG Midpointbooltrueshow_ce
ce_sty_instringDashedce_sty_in
ce_colcolorcolor.redce_col
Labelbooltrueshow_lbl
Show all 40 settings
SettingTypeDefaultVariable
lbl_hstringRightlbl_h
lbl_vstringToplbl_v
lbl_sz_instringSmalllbl_sz_in
lbl_colcolorcolor.blacklbl_col
Extend Previous NWOGsbooltrueext_prev
Show ORGbooltrueshow_org
org_colcolorcolor.new(color.green, 75)org_col
Bordercolorcolor.new(color.green, 0)org_bdr_col
org_bdr_stystringNoneorg_bdr_sty
org_bdr_widthint1org_bdr_width
Previous ORGsboolfalseshow_prev_org
n_prev_orgint1n_prev_org
prev_org_colcolorcolor.new(#9C27B0, 75)prev_org_col
ORG Midpointbooltrueshow_org_ce
org_ce_sty_instringDashedorg_ce_sty_in
org_ce_colcolorcolor.greenorg_ce_col
Labelbooltrueshow_org_lbl
org_lbl_hstringRightorg_lbl_h
org_lbl_vstringToporg_lbl_v
org_lbl_sz_instringSmallorg_lbl_sz_in
org_lbl_colcolorcolor.blackorg_lbl_col
Extend Previous ORGsbooltrueext_prev_org
Extend boxes (bars)int5extend_bars
Midnight Openbooltruemid_show
mid_colcolorcolor.new(color.gray, 50)mid_col
mid_sty_instringSolidmid_sty_in
mid_widthint1mid_width
Previous Midnight Opensint10mid_prev
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

Golden Bullet Strategy

by TradersPost
218 stars

The Golden Bullet Strategy is an overlay signal indicator based on Smart Money Concepts and time-based liquidity models. It identifies liquidity sweeps of a designated reference session range during a specified hunt window. It then confirms Market Structure Sh

Indicator v6 SMC / ICT / price actionSessions & time
Updated 3 months ago · None stated GitHub repository of Golden Bullet Strategy

This indicator detects and draws the first Fair Value Gap (FVG) that forms in each hourly session based on a selected lower timeframe, with specialized handling for Regular Trading Hours (RTH) confluence windows. It draws FVG range boxes, midpoint lines, hourl

Indicator v5 SMC / ICT / price actionSupport & resistance Repaints

This indicator combines six trading tools into a single chart overlay to optimize indicator limits. It calculates Bollinger Bands, projects weekend price boundaries, plots market structure elements like order blocks, breaker blocks, and MSB lines, marks New Yo

Indicator v6 Support & resistanceSMC / ICT / price action Repaints
19 stars

This indicator highlights Inner Circle Trader (ICT) killzones and key session pivot points directly on the price chart. It projects shaded boxes for specific trading sessions, including Asia, London, NY AM, NY Lunch, and NY PM, to help traders identify high-li

Indicator v5 SMC / ICT / price actionSessions & time
Updated 3 years ago · MIT GitHub repository of ICT Killzones & Pivots

Bandz Session Ranges + ORG + Opening Prices plots trading session ranges, killzones, opening RTH gaps, standard deviation projections, and key opening prices directly on the price chart. It calculates gap ranges based on prior regular trading hours close sourc

Indicator v6 Sessions & timeSupport & resistance
Updated 2 weeks ago · MPL-2.0 GitHub repository of Bandz Session Ranges + ORG + Opening Prices

More indicators

Trade Your Charts With a Regulated Broker

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

Compare brokers