ADR Plots + Overlay

ADR Plots + Overlay

This tool calculates and displays Average Daily Range (ADR) levels on your chart, giving traders a quick visual reference for expected daily price movement. It plots guide levels above and below the daily open and shows how much of the day’s typical range has already been covered—all in one interactive table and on-chart overlay.

What It Does

ADR Calculation:
Uses daily high-low differences over a user-defined period (default 14 days), smoothed via RMA, SMA, EMA, or WMA to calculate the average daily range.

Projected Levels:
Plots four reference levels relative to the current day’s open price:

+100% ADR: Open + ADR

+50% ADR: Open + 50% of ADR

−50% ADR: Open − 50% of ADR

−100% ADR: Open − ADR

Coverage %:
Tracks intraday high and low prices to calculate what percentage of the ADR has already been covered for the current session:

Coverage % = (High − Low) ÷ ADR × 100

Interactive Table:
Shows the ADR value and today’s ADR coverage percentage in a customizable table overlay. The table position, colors, border, transparency, and an optional empty top row can all be adjusted via settings.

Customization Options
Table Settings:

Position the table (top/bottom × left/right).

Change background color, text color, border color and thickness.

Toggle an empty top row for spacing.

Line Settings:

Choose color, line style (solid/dotted/dashed), and width.

Lines automatically reposition each day based on that day’s open price and ADR calculation.

General Inputs:

ADR length (number of days).

Smoothing method (RMA, SMA, EMA, WMA).

How to Use It for Trading
Measure Daily Movement: Instantly know the expected daily price range based on historical volatility.

Identify Overextension: Use the coverage % to see if the market has already moved close to or beyond its typical daily range.

Plan Entries & Exits: Align trade targets and stops with ADR levels for more objective intraday planning.

Visual Reference: Horizontal guide lines and table update automatically as new data comes in, helping traders stay informed without manual calculations.

Ideal For
Intraday traders tracking daily volatility limits.

Swing traders wanting a quick reference for expected price movement per day.

Anyone seeking a volatility-based framework for planning targets, stops, or identifying extended market conditions.

// ADR Plots + Overlay
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © abbadon9 [If you modify this script please acknowledge me.]

//@version=6
indicator("ADR Plots + Overlay", shorttitle="ADR+", overlay=true)

// --- Input start --- //
length       = input.int(title="ADR Length", defval=14, minval=1, group='ADR Settings')
smoothing    = input.string(title="Smoothing", defval="WMA", options=["RMA","SMA","EMA","WMA"], group='ADR Settings')
ma_function(source, length) =>
    switch smoothing
        "RMA" => ta.rma(source, length)
        "SMA" => ta.sma(source, length)
        "EMA" => ta.ema(source, length)
        => ta.wma(source, length)
    
m           = float(1)
// --- ADR calculation ---
a           = ma_function(high - low, length) * m 

// === Table Settings ===
showTopSpacer = input.bool(true, "Add Empty Top Spacer Row", group='Table Settings')
dash_loc    = input.string("Bottom Right","Table Position", options=["Top Right","Bottom Right","Top Left","Bottom Left", "Middle Right","Bottom Center"], group='Table Settings')
text_size   = input.string('Normal',"Table Size", options=["Tiny","Small","Normal","Large"]  ,group='Table Settings')
col_H       = input.color(color.new(color.rgb(94, 49, 157), 100), "Table Color", inline="0", group='Table Settings')
Col_txt     = input.color(color.rgb(255, 255, 255, 25), "Text Color", inline="0", group='Table Settings')


// === Border Settings ===
borderColor = input.color(color.new(color.rgb(94, 49, 157), 100), "Table Border Color", group="Table Settings")
borderWidth = input.int(1, "Table Border Width", minval=0, maxval=5, group="Table Settings")

// === Line Settings ===
col_D       = input.color(color.rgb(255, 235, 59, 25), "Close", inline="0", group='Line Settings') 
col_P100    = input.color(color.rgb(242, 54, 69, 25), "+100%", inline="0", group='Line Settings') 
col_M100    = input.color(color.rgb(242, 54, 69, 25), "-100%", inline="0", group='Line Settings')
col_P50     = input.color(color.rgb(255, 152, 0, 25), "+50%", inline="0", group='Line Settings') 
col_M50     = input.color(color.rgb(255, 152, 0, 25), "-50%", inline="0", group='Line Settings')  
styleOption = input.string("dotted", "Line Style", options=["solid", "dotted", "dashed"], group='Line Settings' )
lineWidth   = input.int(1, "Line Width", minval=1, maxval=5, group='Line Settings')

lineStyle = styleOption == "dotted" ? line.style_dotted :
     styleOption == "dashed" ? line.style_dashed :
         line.style_solid       

// --- Timeframe Settings Show/Hide Start --- //
showHTF     = true
showTFD     = true

// --- Definitions --- //
CLS         = close
ACLS        = a
EMA         = ta.ema(close,27)

// --- ADR Day Data --- //
adrD        = request.security(syminfo.tickerid,"D",ACLS)[1] // Recent daily ADR
CD          = request.security(syminfo.tickerid,"D",CLS)[1]
HD          = request.security(syminfo.tickerid,"D",high)
LD          = request.security(syminfo.tickerid,"D",low)
EMAD        = request.security(syminfo.tickerid,"D",EMA)
DP100       = (adrD * m * 1 )+ open 
DP050       = (adrD * m * 0.50 )+ open 
DM100       = open- (adrD * m * 1) 
DM050       = open- (adrD * m * 0.50) 

// --- Find the current intraday high and low --- //
intradayHigh = request.security(syminfo.tickerid, "1D", high)
intradayLow = request.security(syminfo.tickerid, "1D", low)

// --- Calculate the ratio: (Intraday High - Intraday Low) / Smoothed ADR --- //
intradayRange = intradayHigh - intradayLow
rangeToAdrRatio = (intradayRange / adrD) * 100  // Convert to percentage

// --- Draw Lines --- //
TF = timeframe.period
if showHTF
    var line CDLine    = line.new(na, na, na, na, xloc=xloc.bar_time, style=lineStyle, width=lineWidth, color=col_D,      extend=extend.both)
    var line DP100Line = line.new(na, na, na, na, xloc=xloc.bar_time, style=lineStyle, width=lineWidth, color=col_P100,   extend=extend.both)
    var line DM100Line = line.new(na, na, na, na, xloc=xloc.bar_time, style=lineStyle, width=lineWidth, color=col_M100,   extend=extend.both)
    var line DP50Line  = line.new(na, na, na, na, xloc=xloc.bar_time, style=lineStyle, width=lineWidth, color=col_P50,    extend=extend.both)
    var line DM50Line  = line.new(na, na, na, na, xloc=xloc.bar_time, style=lineStyle, width=lineWidth, color=col_M50,    extend=extend.both)
    if ta.change(time("D")) != 0
        line.set_xy1(DP100Line, time,   DP100)
        line.set_xy2(DP100Line, time+1, DP100)
        line.set_xy1(DM100Line, time,   DM100)
        line.set_xy2(DM100Line, time+1, DM100)
        line.set_xy1(CDLine,    time,   open) 
        line.set_xy2(CDLine,    time+1, open) 
        line.set_xy1(DP50Line,  time,   DP050)
        line.set_xy2(DP50Line,  time+1, DP050)
        line.set_xy1(DM50Line,  time,   DM050)
        line.set_xy2(DM50Line,  time+1, DM050)

// --- Table Position & Size Code Start --- //
max    = 160    
min    = 10     
var table_position = dash_loc   == 'Top Left'       ? position.top_left :
  dash_loc                      == 'Bottom Left'    ? position.bottom_left :
  dash_loc                      == 'Middle Right'   ? position.middle_right :
  dash_loc                      == 'Bottom Center'  ? position.bottom_center :
  dash_loc                      == 'Top Right'      ? position.top_right : position.bottom_right
var table_text_size = text_size == 'Tiny'           ? size.tiny :
  text_size                     == 'Small'          ? size.small :
  text_size                     == 'Normal'         ? size.normal : size.large

// === Table with configurable border ===
var t = table.new(table_position, 15, math.abs(max-min)+2,
  frame_color   = borderColor,
  frame_width   = borderWidth,
  border_color  = borderColor,
  border_width  = borderWidth)

if barstate.islast
    if showTFD
        rowOffset = showTopSpacer ? 1 : 0

        // Optional empty top row
        if showTopSpacer
            table.cell(t, 4, 1, "", text_color=Col_txt, text_size=table_text_size, bgcolor=color.new(color.black, 100))
            table.cell(t, 6, 1, "", text_color=Col_txt, text_size=table_text_size, bgcolor=color.new(color.black, 100))

        // Headers
        table.cell(t,4,5+rowOffset,' ADR ',text_color=Col_txt,text_size=table_text_size,bgcolor=col_H)
        table.cell(t,4,6+rowOffset,' COVERED ',text_color=Col_txt,text_size=table_text_size,bgcolor=col_H )

        // Data
        table.cell(t,6,5+rowOffset, str.tostring(adrD, ' #.### '),text_color=Col_txt,text_size=table_text_size,bgcolor=col_H)
        table.cell(t,6,6+rowOffset, str.tostring(rangeToAdrRatio, ' #.##') + "%", text_color=Col_txt, text_size=table_text_size, bgcolor=col_H)