1Copy the scriptPress Copy script above, or the copy button on the code below.
2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.
Source Code
247 lines of Pine Script v5 from code.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.
code.pine
//@version=5
indicator("RVol Panel", shorttitle="RVol Panel", overlay=false, max_bars_back = 5000)
//──────────────────── USER SETTINGS
daysRVol = input.int(20, "Days in RV Baseline")
volMALen = input.int(20, "Volume-MA Length")
th0 = input.float(0.50, "Thresh 0 (black → red)")
th1 = input.float(1.25, "Thresh 1 (red→orange)")
th2 = input.float(2.00, "Thresh 2 (orange→green)")
th3 = input.float(2.25, "Thresh 3 (green → light-blue)")
th4 = input.float(3.00, "Thresh 4 (light-blue → purple)")
useGradient = input.bool(false, "Gradient bar colours?")
//──────────────────── ALERT SETTINGS
string grpAlert = "RVol Alerts"
bool enableRVolAlert = input.bool(true, "Enable high RVol streak alert", group=grpAlert)
int alertBars = input.int(2, "Consecutive bars (green or higher)", minval=1, maxval=10, group=grpAlert)
// New York cash session (09:30–16:00) in chart timezone
string alertSession = input.session("0930-1600", "Alert session (New York time)", group=grpAlert)
//──────────────────── COLOURS (sampled from your screenshot)
chipMA = color.rgb(123, 163, 255)
chipHist = color.rgb(255, 191, 126)
chipVol = color.rgb(255, 231, 146)
chipCur = color.rgb(120, 183, 242)
chipRVol = color.rgb(255, 255, 255)
txtCol = color.rgb( 30, 30, 30)
borderCol= color.rgb(0, 0, 0)
colBlack = color.rgb(0, 0, 0) // super‑low volume
colLightBlue = color.rgb(74, 155, 232) // >2.25× RVOL
colPurple = color.rgb(145, 56, 235) // >3.00× RVOL
colRed = color.rgb(160, 0, 0)
colOrange = color.rgb(230,130, 0)
colGreen = color.rgb( 0,160, 0)
//──────────────────── HELPERS
fmt(v) => str.tostring(v, format.volume)
pad(s) => " " + s + " " // thin padding
//──────────────────── SESSION STATE (arrays → no bar-limit errors)
var float cumVol = 0.0
var int[] dayStart = array.new_int()
var float[] cumBuf = array.new_float()
var float[] volBuf = array.new_float()
isNewDay() =>
t = time("D")
(na(t[1]) and not na(t)) or t[1] < t
if isNewDay()
cumVol := 0
array.push(dayStart, bar_index)
if array.size(dayStart) > daysRVol + 1
array.shift(dayStart)
cumVol += volume
array.push(cumBuf, cumVol)
array.push(volBuf, volume)
//──────────────────── RV CALC (bar-RV & cumulative-RV)
calcRV() =>
float barAvg = 0.0
float cumAvg = 0.0
int n = array.size(dayStart)
if n >= daysRVol + 1
int barsIntoSess = bar_index - array.get(dayStart, n-1)
for i = 1 to daysRVol
int d0 = array.get(dayStart, n - i - 1)
int d1 = (i == 1) ? bar_index : array.get(dayStart, n - i) - 1
int idx = math.min(d0 + barsIntoSess, d1) // clamp if that day was shorter
barAvg += array.get(volBuf, idx) / daysRVol
cumAvg += array.get(cumBuf, idx) / daysRVol
[barAvg > 0 ? volume / barAvg : 0,
cumAvg > 0 ? cumVol / cumAvg : 0,
barAvg, cumAvg]
[barRV, cumRV, histBarAvg, histCumAvg] = calcRV()
//──────────────────── BAR COLOUR
getBarCol(rv) =>
// ── Simple traffic‑light (no gradient) ───────────────────────────
if not useGradient
rv < th0 ? colBlack : rv < th1 ? colRed : rv < th2 ? colOrange: rv < th3 ? colGreen : rv < th4 ? colLightBlue : colPurple
// ── Smooth gradient version ─────────────────────────────────────
else
rv < th0 ? colBlack :rv < th1 ? color.from_gradient(rv, th0, th1, colBlack, colRed) :rv < th2 ? color.from_gradient(rv, th1, th2, colRed, colOrange) : color.from_gradient(rv, th2, th2*2, colOrange, colGreen)
//──────────────────── PLOTS
// MA first (bars will overlap it)
// Historical same-bar average volume baseline from past daysRVol sessions
avgVolBaseline = histBarAvg > 0 ? histBarAvg : na
plot(avgVolBaseline, color=chipMA, linewidth=2, title="Avg Volume (same-bar baseline)")
// Bars on top
plot(volume,
style = plot.style_columns,
color = getBarCol(barRV),
linewidth = 3,
title = "Bar Volume")
hline(0, color=color.new(color.gray, 90)) // keep zero visible
//──────────────────── LEGEND TABLE (2 cols × 5 rows)
var table panel = table.new(position.top_right, 2, 1, border_width=1, border_color=borderCol)
//──────────────────── APPEND — EXTRA CUMV STATS (add-only, no edits above)
// Human-friendly K/M/B formatter
fmtKM(v) =>
string out = na
if na(v)
out := "na"
else
float av = math.abs(v)
out := av >= 1e9 ? str.tostring(v / 1e9, "#.##") + "B" :
av >= 1e6 ? str.tostring(v / 1e6, "#.##") + "M" :
av >= 1e3 ? str.tostring(v / 1e3, "#.##") + "K" :
str.tostring(v, "#")
out
// Gather indices safely
int nDays = array.size(dayStart)
bool haveYday = nDays >= 2
bool have3 = nDays >= 4
int yStart = na
int yEndEx = na
int yEndIx = na
float yCumTotal = na
if haveYday
yStart := array.get(dayStart, nDays - 2)
yEndEx := array.get(dayStart, nDays - 1)
yEndIx := yEndEx - 1
yCumTotal := array.get(cumBuf, yEndIx)
// Last 3 complete days average cumulative volume
float avg3Total = na
if have3
float s = 0.0
int c = 0
for i = 1 to 3
int dStart = array.get(dayStart, nDays - i - 1)
int dEndEx = array.get(dayStart, nDays - i)
int dEndIx = dEndEx - 1
float totI = array.get(cumBuf, dEndIx)
s += totI
c += 1
avg3Total := c > 0 ? s / c : na
// % of today's cumulative (at this time) vs yesterday's same time
float pctVsY_sameTime = na
if haveYday
int currStart = array.get(dayStart, nDays - 1)
int barsInto = bar_index - currStart
int ySameIx = math.min(yStart + barsInto, yEndIx)
float ySame = array.get(cumBuf, ySameIx)
pctVsY_sameTime := ySame > 0 ? (cumVol / ySame) * 100.0 : na
// Table (separate from your existing 'panel' variable; zero edits to it)
var table rvolExtra = table.new(position.top_right, 2, 3, border_width=1, border_color=borderCol)
// Update table cells each bar
table.cell(rvolExtra, 0, 0, "Yday CV", text_color=txtCol, bgcolor=chipVol)
table.cell(rvolExtra, 1, 0, fmtKM(yCumTotal), text_color=txtCol)
table.cell(rvolExtra, 0, 1, "3d CV", text_color=txtCol, bgcolor=chipVol)
table.cell(rvolExtra, 1, 1, fmtKM(avg3Total), text_color=txtCol)
table.cell(rvolExtra, 0, 2, "% vs Y", text_color=txtCol, bgcolor=chipVol)
table.cell(rvolExtra, 1, 2, na(pctVsY_sameTime) ? "na" : str.tostring(pctVsY_sameTime, "#.##") + "%", text_color=txtCol)
//──────── DAILY TOTALS (consolidated) — append-only
float dVol = request.security(syminfo.tickerid, "D", volume) // daily aggregated volume
float ydayDTotal = dVol[1]
float avg3DTotal = ta.sma(dVol[1], 3)
//──────── SCALE “@now vs Yday” to daily-consolidated totals — append-only
float yIntraTotal = haveYday ? array.get(cumBuf, yEndIx) : na
float scaleY = haveYday and yIntraTotal > 0 ? ydayDTotal / yIntraTotal : na
float ySameScaled = not na(scaleY) ? (array.get(cumBuf, math.min(yStart + (bar_index - array.get(dayStart, nDays - 1)), yEndIx)) * scaleY) : na
float pctVsY_sameTime_adj = not na(ySameScaled) and ySameScaled > 0 ? (cumVol / ySameScaled) * 100.0 : na
//──────────────────── ALERT LOGIC — append-only
// "Green or higher" = barRV >= th2
bool isHighRVol = not na(barRV) and barRV >= th2
// Running streak of consecutive high-RVol bars
var int streakHighRVol = 0
if isHighRVol
streakHighRVol := streakHighRVol + 1
else
streakHighRVol := 0
// Condition: at least `alertBars` consecutive green-or-higher bars
bool highRVolStreak = enableRVolAlert and streakHighRVol >= alertBars
// Optional visual marker in the pane
// plotshape(highRVolStreak, title="High RVol streak", style=shape.triangleup, location=location.top, size=size.tiny, color=colGreen)
// Alert condition — set alert to "Once per bar close"
alertcondition(highRVolStreak, "RVol: high streak", "RVol Panel: high RVol streak")
//──────────────────── APPEND — EXTRA PANEL STYLE (fixed)
// Inputs
string grpStyle = "RVol Extra — Style"
bool compactLbls = input.bool(true, "Compact labels", group=grpStyle)
string txtSizeOpt = input.string("Tiny", "Text size", options=["Tiny","Small","Normal"], group=grpStyle)
color hdrBgCol = input.color(color.new(color.yellow, 10), "Header BG", group=grpStyle)
color valBgCol = input.color(color.new(color.black, 0), "Value BG", group=grpStyle)
color tblBorderCol = input.color(borderCol, "Border color", group=grpStyle)
int tblBorderW = input.int(1, "Border width", minval=0, maxval=3, group=grpStyle)
// Map string → enum size (no type annotation; just assign)
txtSize = txtSizeOpt == "Tiny" ? size.tiny :
txtSizeOpt == "Small" ? size.small :
size.normal
// Slimmer borders/frame
table.set_border_color(rvolExtra, tblBorderCol)
table.set_border_width(rvolExtra, tblBorderW)
table.set_frame_color(rvolExtra, tblBorderCol)
table.set_frame_width(rvolExtra, tblBorderW)
// Compact labels
string lblY = compactLbls ? "Yday" : "Yday CumVol"
string lblAvg3 = compactLbls ? "Avg 3d" : "Avg 3d CumVol"
string lblPct = compactLbls ? "% Yday@" : "% vs Yday @now"
// Repaint cells with smaller text + chosen colors
table.cell(rvolExtra, 0, 0, lblY, text_color=txtCol, bgcolor=hdrBgCol, text_size=txtSize)
table.cell(rvolExtra, 1, 0, fmtKM(yCumTotal), text_color=txtCol, bgcolor=valBgCol, text_size=txtSize)
table.cell(rvolExtra, 0, 1, lblAvg3, text_color=txtCol, bgcolor=hdrBgCol, text_size=txtSize)
table.cell(rvolExtra, 1, 1, fmtKM(avg3Total), text_color=txtCol, bgcolor=valBgCol, text_size=txtSize)
string pctText = na(pctVsY_sameTime) ? "na" : str.tostring(pctVsY_sameTime, "#.##") + "%"
table.cell(rvolExtra, 0, 2, lblPct, text_color=txtCol, bgcolor=hdrBgCol, text_size=txtSize)
table.cell(rvolExtra, 1, 2, pctText, text_color=txtCol, bgcolor=valBgCol, text_size=txtSize)
Overview
RVol Panel compares each bar’s volume with the same bar position across a configurable number of recent sessions and also tracks cumulative session volume against that baseline. Bars are colored by adjustable relative-volume thresholds, with an optional gradient. A table shows current readings. An optional alert fires after a chosen streak of high relative-volume bars during the New York cash session. It does not generate entries or exits.
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
Days in RV Baseline
int
20
daysRVol
Volume-MA Length
int
20
volMALen
Thresh 0 (black → red)
float
0.50
th0
Thresh 1 (red→orange)
float
1.25
th1
Thresh 2 (orange→green)
float
2.00
th2
Thresh 3 (green → light-blue)
float
2.25
th3
Thresh 4 (light-blue → purple)
float
3.00
th4
Gradient bar colours?
bool
false
useGradient
Enable high RVol streak alert
bool
true
enableRVolAlert
Consecutive bars (green or higher)
int
2
alertBars
Alert session (New York time)
session
0930-1600
alertSession
Compact labels
bool
true
compactLbls
Show all 17 settings
Setting
Type
Default
Variable
Text size
string
Tiny
txtSizeOpt
Header BG
color
color.new(color.yellow, 10)
hdrBgCol
Value BG
color
color.new(color.black, 0)
valBgCol
Border color
color
borderCol
tblBorderCol
Border width
int
1
tblBorderW
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.
This indicator plots a session VWAP of the typical price on the price chart. It marks an up triangle under a bar when close crosses above VWAP and a down triangle above a bar when close crosses below it. A star pinned at the top of the pane marks bars whose vo
Equity Intraday Analyst is a comprehensive intraday overlay indicator for US equities and ETFs. It evaluates multi-EMA ribbons, session-anchored VWAP bands, OBV trends, momentum oscillators, TTM Squeeze, and optional market breadth indicators like NYSE TICK an
Peak Trading Activity Graphs displays historical market activity across cyclical timeframes directly on the main chart using an on-screen dashboard table. It evaluates volume or volatility across selected periods, including hours of the day, days of the week,
Smart Money Dashboard plots key Smart Money Concepts on the price chart, including Order Blocks with mitigation tracking, Fair Value Gaps, and Equal Highs or Lows sweeps. It analyzes Cumulative Volume Delta for divergence and combines multi-timeframe structure
This overlay indicator runs a CRT state engine on the price chart. It can analyze draw-on-liquidity pivots, a session state machine, and optional 1AM, 5AM, and 9AM CRT models. Optional modules track market structure, liquidity pools, volume-profile levels, and
Indicatorv5SMC / ICT / price actionSessions & time
This indicator aggregates multiple technical signals into an on-chart summary table. It calculates a session-based VWAP, a triple-EMA-smoothed price-volume oscillator, an EMA 9/21 trend spread, multi-timeframe Donchian channel breakouts, and an opening range h