Indicator · Pine Script v6 · On the chart

Zen Toolkit ETH

by Zen-Tim

This indicator plots intraday reference levels, projection targets, and opening range boundaries tailored for continuous electronic trading session instruments such as gold.

View on GitHub

GitHub stars29on the repository
Pine versionv6current
Lines of code374
Settings40inputs
LicenceMIT
Last update2 weeks ago14 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

374 lines of Pine Script v6 from indicators/Zen-Trading-Toolkit-ETH/zen-trading-toolkit-eth-v1.3.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

zen-trading-toolkit-eth-v1.3.pine
//@version=6
// Zen Trading Toolkit — ETH Edition v1.3 · 20260707
// For continuous/near-24hr session instruments (e.g. GC/GOLD). One session, no RTH split.
// Daily reset = timeframe.change("D"), aligned to instrument's actual trade-date roll (not calendar midnight).
// v1.3: M1 yesterday levels now latch at first_bar from the LIVE "D" security series with [1]
// applied in CHART context, instead of request.security(..., "D", high[1]) which offset inside
// the security call and rolled on the exchange calendar day — misaligned from the chart's
// timeframe.change("D") boundary that M2/M3 use. On GC/GOLD the two "days" roll at different
// times, so M1 referenced the wrong prior day or jumped mid-session. Now all three modules
// share one day boundary. lookahead_off set explicitly to prevent repaint.

indicator("Zen Toolkit ETH v1.3", shorttitle="ETH Toolkit 1.3",
     overlay=true, max_lines_count=500, max_labels_count=500, max_boxes_count=500)

grpSession = "SESSION"
string symbolLabel = input.string("ETH — Full Day", "Display Label", group=grpSession)
int lookback = input.int(8, "Lookback Period (days)", minval=1, maxval=50, group=grpSession)

grpMM2 = "M1: Targets"
mm_show05x = input.bool(true,  "Show 0.5x ABR targets", group=grpMM2)
mm_show1x  = input.bool(true,  "Show 1.0x ABR targets", group=grpMM2)
mm_show15x = input.bool(false, "Show 1.5x ABR targets", group=grpMM2)
mm_show2x  = input.bool(false, "Show 2.0x ABR targets", group=grpMM2)

grpMM3 = "M1: Reference Lines"
mm_showYClose = input.bool(false, "Yesterday's Close",  group=grpMM3)
mm_showYHiLo  = input.bool(true,  "Yesterday's Hi / Lo", group=grpMM3)
mm_showYdMM   = input.bool(true,  "Yesterday's Range MM", group=grpMM3)

grpMM4 = "M1: Display"
mm_lineExt    = input.int(20, "Line Extension (bars)", minval=10, maxval=500, group=grpMM4)
mm_lineWidth  = input.int(1,  "Line Width", minval=1, maxval=4, group=grpMM4)
mm_showLabels = input.bool(true, "Show Labels", group=grpMM4)
mm_showTable  = input.bool(false, "Show Targets Table (debug)", group=grpMM4)
mm_tableSize  = input.string("small", "Table Text Size", options=["tiny", "small", "normal", "large"], group=grpMM4)
mm_labelOff   = input.int(5, "Label Offset (bars right)", minval=0, maxval=50, group=grpMM4)

grpMM5 = "M1: Bull Colors"
mm_colBull05 = input.color(color.new(#059669, 60), "Bull 0.5x", group=grpMM5)
mm_colBull1  = input.color(color.new(#059669, 30), "Bull 1.0x", group=grpMM5)
mm_colBull15 = input.color(color.new(#059669, 15), "Bull 1.5x", group=grpMM5)
mm_colBull2  = input.color(color.new(#059669, 0),  "Bull 2.0x", group=grpMM5)

grpMM6 = "M1: Bear Colors"
mm_colBear05 = input.color(color.new(#DC2626, 60), "Bear 0.5x", group=grpMM6)
mm_colBear1  = input.color(color.new(#DC2626, 30), "Bear 1.0x", group=grpMM6)
mm_colBear15 = input.color(color.new(#DC2626, 15), "Bear 1.5x", group=grpMM6)
mm_colBear2  = input.color(color.new(#DC2626, 0),  "Bear 2.0x", group=grpMM6)

grpMM7 = "M1: Reference Colors"
mm_colYClose = input.color(color.new(#F59E0B, 30), "Yesterday Close", group=grpMM7)
mm_colYHiLo  = input.color(color.new(color.gray, 50), "Yesterday Hi/Lo", group=grpMM7)
mm_colYdMM   = input.color(color.new(color.teal, 0),  "Yesterday Range MM", group=grpMM7)

grpOR1 = "M2: Box Settings"
or_bars      = input.int(18, "Opening Range Bars", minval=2, maxval=100, group=grpOR1)
or_showBox   = input.bool(true,  "Show Box", group=grpOR1)
or_boxColor  = input.color(color.orange, "Box Color", group=grpOR1)
or_boxTrans  = input.int(80, "Box Transparency", minval=0, maxval=100, group=grpOR1)
or_showLabel = input.bool(false, "Show Range Label", group=grpOR1)
or_lblColor  = input.color(color.white, "Label Color", group=grpOR1)

grpOR2 = "M2: Projections"
or_projLen = input.int(40, "Projection Length (bars)", group=grpOR2)
or_show025 = input.bool(false, "0.25x", inline="or0", group=grpOR2)
or_col025  = input.color(color.new(color.yellow, 30), "", inline="or0", group=grpOR2)
or_show050 = input.bool(true,  "0.50x", inline="or1", group=grpOR2)
or_col050  = input.color(color.new(color.teal, 30),   "", inline="or1", group=grpOR2)
or_show075 = input.bool(false, "0.75x", inline="or2", group=grpOR2)
or_col075  = input.color(color.new(color.blue, 30),   "", inline="or2", group=grpOR2)
or_show100 = input.bool(true,  "1.00x", inline="or3", group=grpOR2)
or_col100  = input.color(color.new(color.gray, 30),   "", inline="or3", group=grpOR2)
or_show150 = input.bool(false, "1.50x", inline="or4", group=grpOR2)
or_col150  = input.color(color.new(color.orange, 30), "", inline="or4", group=grpOR2)
or_show200 = input.bool(false, "2.00x", inline="or5", group=grpOR2)
or_col200  = input.color(color.new(color.red, 30),    "", inline="or5", group=grpOR2)
or_showProjLbl = input.bool(false, "Show Target Labels", group=grpOR2)

grpST = "M3: Stats Table"
st_showTable   = input.bool(true, "Show Stats Table", group=grpST)
st_position    = input.string("Top Right", "Table Position", options=["Top Left", "Top Right", "Bottom Left", "Bottom Right"], group=grpST)
st_showSession = input.bool(true, "Show Session Label", group=grpST)

grpSTRows = "M3: Stats Table Rows"
st_showSwing = input.bool(true,  "Swing Row  (% of ADR)", inline="swing", group=grpSTRows)
st_swingPct  = input.float(40.0, "", inline="swing", group=grpSTRows, minval=1, maxval=100, step=5)
st_showScalp = input.bool(true,  "Scalp Row  (% of ADR)", inline="scalp", group=grpSTRows)
st_scalpPct  = input.float(10.0, "", inline="scalp", group=grpSTRows, minval=1, maxval=100, step=1)

grpSTCol = "M3: Stats Table Colours"
st_colHdrBG  = input.color(color.purple, "Header BG", group=grpSTCol)
st_colHdrTxt = input.color(color.white,  "Header Text", group=grpSTCol)
st_colLabel  = input.color(color.gray,   "Row Labels", group=grpSTCol)
st_colValue  = input.color(color.black,  "Values", group=grpSTCol)

// --- Session: one continuous session, reset on instrument's actual trade-date roll ---
bool first_bar = timeframe.change("D")

// --- Yesterday's H/L/C/O: latched at first_bar from the LIVE "D" security series (v1.3 fix) ---
float d_high  = request.security(syminfo.tickerid, "D", high,  lookahead=barmerge.lookahead_off)
float d_low   = request.security(syminfo.tickerid, "D", low,   lookahead=barmerge.lookahead_off)
float d_close = request.security(syminfo.tickerid, "D", close, lookahead=barmerge.lookahead_off)
float d_open  = request.security(syminfo.tickerid, "D", open,  lookahead=barmerge.lookahead_off)

var float yHigh  = na
var float yLow   = na
var float yClose = na
var float yOpen  = na

if first_bar
    yHigh  := d_high[1]
    yLow   := d_low[1]
    yClose := d_close[1]
    yOpen  := d_open[1]

float yRange = not na(yHigh) and not na(yLow) ? yHigh - yLow : na

// --- ABR: rolling N daily ranges ---
var float[] dailyRanges = array.new_float(0)
var float currentABR = na

if first_bar and not na(yRange) and yRange > 0
    array.push(dailyRanges, yRange)
    if array.size(dailyRanges) > lookback + 5
        array.shift(dailyRanges)

if first_bar and array.size(dailyRanges) >= lookback
    float sumR = 0.0
    for i = array.size(dailyRanges) - lookback to array.size(dailyRanges) - 1
        sumR += array.get(dailyRanges, i)
    currentABR := sumR / lookback
else if first_bar and array.size(dailyRanges) > 0
    float sumR = 0.0
    for i = 0 to array.size(dailyRanges) - 1
        sumR += array.get(dailyRanges, i)
    currentABR := sumR / array.size(dailyRanges)

// --- M1: measured move targets ---
var float bull05 = na, var float bull1 = na, var float bull15 = na, var float bull2 = na
var float bear05 = na, var float bear1 = na, var float bear15 = na, var float bear2 = na

if first_bar and not na(yClose) and not na(currentABR)
    bull05 := yClose + 0.5 * currentABR
    bull1  := yClose + 1.0 * currentABR
    bull15 := yClose + 1.5 * currentABR
    bull2  := yClose + 2.0 * currentABR
    bear05 := yClose - 0.5 * currentABR
    bear1  := yClose - 1.0 * currentABR
    bear15 := yClose - 1.5 * currentABR
    bear2  := yClose - 2.0 * currentABR

f_drawLevel(float _price, color _col, string _style, string _txt) =>
    ln = line.new(bar_index, _price, bar_index + mm_lineExt, _price, xloc.bar_index, color=_col,
         style=_style == "solid" ? line.style_solid : _style == "dashed" ? line.style_dashed : line.style_dotted, width=mm_lineWidth)
    lb = mm_showLabels ? label.new(bar_index + mm_lineExt + mm_labelOff, _price, text=_txt + " " + str.tostring(_price, format.mintick),
         xloc=xloc.bar_index, style=label.style_none, textcolor=_col, size=size.small) : na
    [ln, lb]

if first_bar and not na(yClose) and not na(currentABR)
    if mm_show05x
        f_drawLevel(bull05, mm_colBull05, "solid", "Bull 0.5x")
        f_drawLevel(bear05, mm_colBear05, "solid", "Bear 0.5x")
    if mm_show1x
        f_drawLevel(bull1, mm_colBull1, "solid", "Bull 1.0x")
        f_drawLevel(bear1, mm_colBear1, "solid", "Bear 1.0x")
    if mm_show15x
        f_drawLevel(bull15, mm_colBull15, "dashed", "Bull 1.5x")
        f_drawLevel(bear15, mm_colBear15, "dashed", "Bear 1.5x")
    if mm_show2x
        f_drawLevel(bull2, mm_colBull2, "dashed", "Bull 2.0x")
        f_drawLevel(bear2, mm_colBear2, "dashed", "Bear 2.0x")
    if mm_showYClose
        f_drawLevel(yClose, mm_colYClose, "dotted", "y.Close")
    if mm_showYHiLo and not na(yHigh)
        f_drawLevel(yHigh, mm_colYHiLo, "dotted", "y.Hi")
        f_drawLevel(yLow, mm_colYHiLo, "dotted", "y.Lo")
    if mm_showYdMM and not na(yHigh) and not na(yLow)
        f_drawLevel(yHigh + yRange, mm_colYdMM, "dotted", "yd MM up")
        f_drawLevel(yLow - yRange, mm_colYdMM, "dotted", "yd MM dn")

// --- M1 debug table ---
if mm_showTable and barstate.islast and not na(currentABR)
    sz = switch mm_tableSize
        "tiny" => size.tiny
        "small" => size.small
        "normal" => size.normal
        "large" => size.large
        => size.small
    var table mmTbl = table.new(position.top_left, 2, 12, bgcolor=color.new(#1a1a2e, 10),
         border_color=color.new(color.gray, 70), border_width=1, frame_color=color.new(color.gray, 50), frame_width=1)
    table.cell(mmTbl, 0, 0, "ABR MM Targets", text_color=color.white, text_size=sz, bgcolor=color.new(#059669, 20), text_halign=text.align_left)
    table.cell(mmTbl, 1, 0, "from y.Close", text_color=color.gray, text_size=sz, bgcolor=color.new(#059669, 20), text_halign=text.align_right)
    table.cell(mmTbl, 0, 1, "y.Close", text_color=mm_colYClose, text_size=sz, text_halign=text.align_left)
    table.cell(mmTbl, 1, 1, str.tostring(yClose, format.mintick), text_color=mm_colYClose, text_size=sz, text_halign=text.align_right)
    table.cell(mmTbl, 0, 2, "ABR (" + str.tostring(lookback) + "d)", text_color=color.white, text_size=sz, text_halign=text.align_left)
    table.cell(mmTbl, 1, 2, str.tostring(currentABR, "#.##"), text_color=color.white, text_size=sz, text_halign=text.align_right)
    table.cell(mmTbl, 0, 3, "y.Range", text_color=color.gray, text_size=sz, text_halign=text.align_left)
    table.cell(mmTbl, 1, 3, str.tostring(yRange, "#.##") + " (" + str.tostring(not na(yRange) and currentABR > 0 ? yRange / currentABR : na, "#.##") + "x ABR)",
         text_color=color.gray, text_size=sz, text_halign=text.align_right)
    table.cell(mmTbl, 0, 4, "--- Bull ---", text_color=mm_colBull1, text_size=sz, text_halign=text.align_left)
    table.cell(mmTbl, 1, 4, "", text_size=sz)
    int row = 5
    if mm_show05x
        table.cell(mmTbl, 0, row, "Bull 0.5x", text_color=mm_colBull05, text_size=sz, text_halign=text.align_left)
        table.cell(mmTbl, 1, row, str.tostring(bull05, format.mintick), text_color=mm_colBull05, text_size=sz, text_halign=text.align_right)
        row += 1
    if mm_show1x
        table.cell(mmTbl, 0, row, "Bull 1.0x", text_color=mm_colBull1, text_size=sz, text_halign=text.align_left)
        table.cell(mmTbl, 1, row, str.tostring(bull1, format.mintick), text_color=mm_colBull1, text_size=sz, text_halign=text.align_right)
        row += 1
    if mm_show15x
        table.cell(mmTbl, 0, row, "Bull 1.5x", text_color=mm_colBull15, text_size=sz, text_halign=text.align_left)
        table.cell(mmTbl, 1, row, str.tostring(bull15, format.mintick), text_color=mm_colBull15, text_size=sz, text_halign=text.align_right)
        row += 1
    if mm_show2x
        table.cell(mmTbl, 0, row, "Bull 2.0x", text_color=mm_colBull2, text_size=sz, text_halign=text.align_left)
        table.cell(mmTbl, 1, row, str.tostring(bull2, format.mintick), text_color=mm_colBull2, text_size=sz, text_halign=text.align_right)
        row += 1
    table.cell(mmTbl, 0, row, "--- Bear ---", text_color=mm_colBear1, text_size=sz, text_halign=text.align_left)
    table.cell(mmTbl, 1, row, "", text_size=sz)
    row += 1
    if mm_show05x
        table.cell(mmTbl, 0, row, "Bear 0.5x", text_color=mm_colBear05, text_size=sz, text_halign=text.align_left)
        table.cell(mmTbl, 1, row, str.tostring(bear05, format.mintick), text_color=mm_colBear05, text_size=sz, text_halign=text.align_right)
        row += 1
    if mm_show1x
        table.cell(mmTbl, 0, row, "Bear 1.0x", text_color=mm_colBear1, text_size=sz, text_halign=text.align_left)
        table.cell(mmTbl, 1, row, str.tostring(bear1, format.mintick), text_color=mm_colBear1, text_size=sz, text_halign=text.align_right)
        row += 1
    if mm_show15x
        table.cell(mmTbl, 0, row, "Bear 1.5x", text_color=mm_colBear15, text_size=sz, text_halign=text.align_left)
        table.cell(mmTbl, 1, row, str.tostring(bear15, format.mintick), text_color=mm_colBear15, text_size=sz, text_halign=text.align_right)
        row += 1
    if mm_show2x
        table.cell(mmTbl, 0, row, "Bear 2.0x", text_color=mm_colBear2, text_size=sz, text_halign=text.align_left)
        table.cell(mmTbl, 1, row, str.tostring(bear2, format.mintick), text_color=mm_colBear2, text_size=sz, text_halign=text.align_right)

// --- M2: opening range ---
or_new_day = timeframe.change("D")
or_bars_since = ta.barssince(or_new_day)

var float or_hi = na, var float or_lo = na, var float or_lockedHigh = na, var float or_lockedLow = na

if or_bars_since == 0
    or_hi := high
    or_lo := low
    or_lockedHigh := na
    or_lockedLow := na
else if or_bars_since < or_bars
    or_hi := math.max(or_hi, high)
    or_lo := math.min(or_lo, low)

if or_bars_since == or_bars - 1
    or_lockedHigh := or_hi
    or_lockedLow := or_lo

or_dailyHigh = request.security(syminfo.tickerid, "D", high)
or_dailyLow = request.security(syminfo.tickerid, "D", low)
or_dailyRange = or_dailyHigh - or_dailyLow
or_adr = ta.sma(or_dailyRange, lookback)
or_range18 = or_lockedHigh - or_lockedLow
or_rangePct = or_adr != 0 ? (or_range18 / or_adr) * 100 : na

or_drawProj(bool show, float mult, color col, string tag, int x1, int x2, float rHi, float rLo, float rng) =>
    if show
        float upTgt = rHi + mult * rng
        float dnTgt = rLo - mult * rng
        line.new(x1, upTgt, x2, upTgt, color=col, style=line.style_dashed, width=1)
        line.new(x1, dnTgt, x2, dnTgt, color=col, style=line.style_dashed, width=1)
        if or_showProjLbl
            label.new(x2, upTgt, tag, style=label.style_label_left, textcolor=col, size=size.small, color=color.new(color.black, 100))
            label.new(x2, dnTgt, tag, style=label.style_label_left, textcolor=col, size=size.small, color=color.new(color.black, 100))

if or_bars_since == or_bars - 1
    if or_showBox
        box.new(bar_index - (or_bars - 1), or_lockedHigh, bar_index, or_lockedLow, border_color=or_boxColor, bgcolor=color.new(or_boxColor, or_boxTrans))
    if or_showLabel
        label.new(bar_index, or_lockedHigh, str.tostring(or_range18, format.mintick) + "\nD: " + str.tostring(or_dailyRange, format.mintick) +
             "\n%: " + str.tostring(or_rangePct, "#.##") + "%", style=label.style_label_down, textcolor=or_lblColor, size=size.normal)
    int x1 = bar_index + 1
    int x2 = bar_index + or_projLen
    or_drawProj(or_show025, 0.25, or_col025, "0.25x", x1, x2, or_lockedHigh, or_lockedLow, or_range18)
    or_drawProj(or_show050, 0.50, or_col050, "0.5x", x1, x2, or_lockedHigh, or_lockedLow, or_range18)
    or_drawProj(or_show075, 0.75, or_col075, "0.75x", x1, x2, or_lockedHigh, or_lockedLow, or_range18)
    or_drawProj(or_show100, 1.00, or_col100, "1.0x", x1, x2, or_lockedHigh, or_lockedLow, or_range18)
    or_drawProj(or_show150, 1.50, or_col150, "1.5x", x1, x2, or_lockedHigh, or_lockedLow, or_range18)
    or_drawProj(or_show200, 2.00, or_col200, "2.0x", x1, x2, or_lockedHigh, or_lockedLow, or_range18)

// --- M3: stats table, single column ---
float st_bar_range = high - low
float st_abr_raw = math.sum(st_bar_range, lookback) / lookback
var float st_abr = na
if barstate.isconfirmed
    st_abr := st_abr_raw

var float st_day_hi = na, var float st_day_lo = na
var array<float> st_completed_ranges = array.new_float(0)

if first_bar
    if not na(st_day_hi) and not na(st_day_lo)
        array.push(st_completed_ranges, st_day_hi - st_day_lo)
        if array.size(st_completed_ranges) > lookback
            array.shift(st_completed_ranges)
    st_day_hi := high
    st_day_lo := low
else
    st_day_hi := math.max(nz(st_day_hi, high), high)
    st_day_lo := math.min(nz(st_day_lo, low), low)

float st_adr = array.size(st_completed_ranges) > 0 ? array.avg(st_completed_ranges) : na
float st_today = not na(st_day_hi) and not na(st_day_lo) ? st_day_hi - st_day_lo : na
float st_pct = not na(st_adr) and st_adr > 0 and not na(st_today) ? (st_today / st_adr) * 100.0 : 0.0
color st_pct_col = st_pct >= 80 ? color.red : st_colValue
float st_or_pct = not na(or_lockedHigh) and not na(or_lockedLow) and not na(st_adr) and st_adr > 0 ? ((or_lockedHigh - or_lockedLow) / st_adr) * 100.0 : na
float st_swing = not na(st_adr) ? st_adr * (st_swingPct / 100.0) : na
float st_scalp = not na(st_adr) ? st_adr * (st_scalpPct / 100.0) : na

stPos = switch st_position
    "Top Left" => position.top_left
    "Top Right" => position.top_right
    "Bottom Left" => position.bottom_left
    "Bottom Right" => position.bottom_right
    => position.top_right

if st_showTable and (barstate.islastconfirmedhistory or barstate.isrealtime)
    var table stTbl = table.new(stPos, 2, 9, border_width=1)
    int row = 0
    if st_showSession
        table.cell(stTbl, 0, row, symbolLabel, text_color=st_colHdrTxt, text_size=size.small, bgcolor=color.new(st_colHdrBG, 40))
        table.cell(stTbl, 1, row, '', text_size=size.small, bgcolor=color.new(st_colHdrBG, 40))
        table.merge_cells(stTbl, 0, row, 1, row)
        row += 1
    table.cell(stTbl, 0, row, 'ABR (' + str.tostring(lookback) + ')', text_color=st_colLabel, text_size=size.small)
    table.cell(stTbl, 1, row, str.tostring(st_abr, format.mintick), text_color=st_colValue, text_size=size.small)
    row += 1
    table.cell(stTbl, 0, row, 'ADR (' + str.tostring(lookback) + ')', text_color=st_colLabel, text_size=size.small)
    table.cell(stTbl, 1, row, str.tostring(math.round(nz(st_adr)), '#'), text_color=st_colValue, text_size=size.small)
    row += 1
    table.cell(stTbl, 0, row, 'Today', text_color=st_colLabel, text_size=size.small)
    table.cell(stTbl, 1, row, str.tostring(math.round(nz(st_today)), '#'), text_color=st_colValue, text_size=size.small)
    row += 1
    table.cell(stTbl, 0, row, '% ADR', text_color=st_colLabel, text_size=size.small)
    table.cell(stTbl, 1, row, str.tostring(math.round(st_pct), '#') + '%', text_color=st_pct_col, text_size=size.small)
    row += 1
    table.cell(stTbl, 0, row, 'OR %', text_color=st_colLabel, text_size=size.small)
    table.cell(stTbl, 1, row, not na(st_or_pct) ? str.tostring(math.round(st_or_pct), '#') + '%' : '-', text_color=st_colValue, text_size=size.small)
    row += 1
    if st_showSwing
        table.cell(stTbl, 0, row, 'Swing ' + str.tostring(math.round(st_swingPct), '#') + '%', text_color=st_colLabel, text_size=size.small)
        table.cell(stTbl, 1, row, not na(st_swing) ? str.tostring(math.round(st_swing), '#') : '-', text_color=st_colValue, text_size=size.small)
        row += 1
    if st_showScalp
        table.cell(stTbl, 0, row, 'Scalp ' + str.tostring(math.round(st_scalpPct), '#') + '%', text_color=st_colLabel, text_size=size.small)
        table.cell(stTbl, 1, row, not na(st_scalp) ? str.tostring(math.round(st_scalp), '#') : '-', text_color=st_colValue, text_size=size.small)
        row += 1

plot(st_abr, title="ABR", display=display.data_window)
plot(st_adr, title="ADR", display=display.data_window)
plot(st_today, title="Today", display=display.data_window)
plot(st_pct, title="% ADR", display=display.data_window)
plot(st_or_pct, title="OR %", display=display.data_window)
plot(st_swing, title="Swing", display=display.data_window)
plot(st_scalp, title="Scalp", display=display.data_window)

// Version | Date       | Changes
// v1.3    | 2026-07-07 | M1 daily levels fixed for ETH instruments (GC/GOLD): yHigh/yLow/yClose/
//         |            | yOpen now latch at first_bar from the LIVE "D" security series with [1]
//         |            | applied in chart context, instead of request.security(..., "D", high[1])
//         |            | which offset inside the security call and rolled on the exchange calendar
//         |            | day — misaligned from the chart's timeframe.change("D") boundary M2/M3 use.
//         |            | All three modules now share one day boundary. lookahead_off set explicit.
// v1.2    | 2026-07-07 | Attempted fix via request.security "D" pull — still misaligned on GC.
// v1.1    | 2026-07-06 | Fixed day-boundary bug: timeframe.change("D") replaces ta.change(time("D")).
// v1.0    | 2026-07-06 | Generic ETH build: one session, one column, no RTH, no instrument naming.

Overview

Zen Toolkit ETH calculates Average Bar Range targets in bullish and bearish multiples, previous day high, low, and close levels, and previous day measured moves. It also constructs an opening range box over a configurable number of bars. All elements are drawn on the price chart alongside optional labels and an info table, aligning calculations to daily roll boundaries without historical lookahead.

Details

Published by

Zen-Tim on GitHub

Type

Indicator, Pine Script v6

Draws

On the price chart

Category

Support & resistance, Sessions & time, Volatility & bands

Markets

Gold

Timeframes

M1-M5, M15-H1

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
Display LabelstringETH — Full DaysymbolLabel
Lookback Period (days)int8lookback
Show 0.5x ABR targetsbooltruemm_show05x
Show 1.0x ABR targetsbooltruemm_show1x
Show 1.5x ABR targetsboolfalsemm_show15x
Show 2.0x ABR targetsboolfalsemm_show2x
Yesterday's Closeboolfalsemm_showYClose
Yesterday's Hi / Lobooltruemm_showYHiLo
Yesterday's Range MMbooltruemm_showYdMM
Line Extension (bars)int20mm_lineExt
Line Widthint1mm_lineWidth
Show Labelsbooltruemm_showLabels
Show all 40 settings
SettingTypeDefaultVariable
Show Targets Table (debug)boolfalsemm_showTable
Table Text Sizestringsmallmm_tableSize
Label Offset (bars right)int5mm_labelOff
Bull 0.5xcolorcolor.new(#059669, 60)mm_colBull05
Bull 1.0xcolorcolor.new(#059669, 30)mm_colBull1
Bull 1.5xcolorcolor.new(#059669, 15)mm_colBull15
Bull 2.0xcolorcolor.new(#059669, 0)mm_colBull2
Bear 0.5xcolorcolor.new(#DC2626, 60)mm_colBear05
Bear 1.0xcolorcolor.new(#DC2626, 30)mm_colBear1
Bear 1.5xcolorcolor.new(#DC2626, 15)mm_colBear15
Bear 2.0xcolorcolor.new(#DC2626, 0)mm_colBear2
Yesterday Closecolorcolor.new(#F59E0B, 30)mm_colYClose
Yesterday Hi/Locolorcolor.new(color.gray, 50)mm_colYHiLo
Yesterday Range MMcolorcolor.new(color.teal, 0)mm_colYdMM
Opening Range Barsint18or_bars
Show Boxbooltrueor_showBox
Box Colorcolorcolor.orangeor_boxColor
Box Transparencyint80or_boxTrans
Show Range Labelboolfalseor_showLabel
Label Colorcolorcolor.whiteor_lblColor
Projection Length (bars)int40or_projLen
0.25xboolfalseor_show025
or_col025colorcolor.new(color.yellow, 30)or_col025
0.50xbooltrueor_show050
or_col050colorcolor.new(color.teal, 30)or_col050
0.75xboolfalseor_show075
or_col075colorcolor.new(color.blue, 30)or_col075
1.00xbooltrueor_show100
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

56 stars

This indicator marks forex trading sessions and opening ranges on the price chart. It can draw Sydney, Tokyo, Frankfurt, London, and New York session boxes or five- and fifteen-minute opening ranges, plus an optional opening channel and a day-open range. Day r

Indicator v5 Sessions & timeSupport & resistance Repaints
Updated 2 months ago · None stated GitHub repository of Day Trading Booster by DGT

AM TBR — NQ Stats

by TamaraKGreen
46 stars

The AM TBR indicator calculates statistical levels for NQ futures using standard deviation. It plots a sigma ladder showing touch levels at 0.5 to 2.0 standard deviations, marks touch points, displays Mean Absolute Error (MAE) zones after touches, and shows Me

Indicator v6 Volatility & bandsSupport & resistance
Updated 7 weeks ago · None stated GitHub repository of AM TBR — NQ Stats

LoD Intraday Entry

by ChartsLector
41 stars

This overlay indicator marks the current day's low and a suggested entry zone a fraction of daily ATR below that low. It compares daily volume with a volume moving average, plots daily SMA and EMA distance, and draws an optional ATR-width price cloud. Labels c

Indicator v6 Support & resistanceVolatility & bands
Updated 2 days ago · None stated GitHub repository of LoD Intraday Entry

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
6 stars

This overlay indicator maps an opening drive for a chosen session, using the first 30 or 60 minutes. It tracks drive high, low, midpoint, range, pace, and volume versus a multi-session average, then projects continuation lines from the drive edge and fade line

Indicator v6 Sessions & timeSupport & resistance
Updated 8 weeks ago · MIT GitHub repository of Capital41 Opening Drive Playbook

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