Volume Rate of Change: formula and signal limits
Volume Rate of Change (VROC) measures the percentage change between current volume and volume N bars earlier. A reading of +50% means current volume is 1.5 times that reference bar. It says how trading activity changed; it does not tell you whether buyers or sellers drove the price.
VROC = 100 × (V − V[N]) / V[N]
V[N] is one historical bar, not the average of the preceding N bars. The percentage is defined only when the reference volume is positive and both endpoints are available.
Calculate VROC and check the denominator
For a 2-bar lookback and volumes [1,000, 2,000, 1,500], the third bar compares 1,500 with 1,000. Its VROC is +50%, despite volume falling from the immediately preceding 2,000. Dividing by the prior two-bar average of 1,500 would answer a different question.
| Case | Reference V[N] | Current V | VROC | Meaning |
|---|---|---|---|---|
| Higher volume | 1,000 | 1,500 | +50% | 1.5 times the reference |
| Lower volume | 1,000 | 500 | -50% | Half the reference |
| Unchanged | 1,000 | 1,000 | 0% | Equal to the reference |
| Zero now | 1,000 | 0 | -100% | Valid arithmetic if zero is a real observation |
| Small reference | 10 | 1,000 | +9,900% | Large percentage from a small denominator |
| Zero reference | 0 | 1,000 | Undefined | Return na; do not divide by zero |
| Missing endpoint | n/a | 1,000 | Unavailable | Return na; do not replace missing data with zero |
The -100% lower bound follows directly from nonnegative volume and a positive denominator. Tiny reference values can produce large positive percentages without large absolute activity. Verify that a reported zero is meaningful before treating it as a complete absence of trading.
Choose a comparable volume baseline
Units and exchange coverage
TradingView reports the volume supplied for the selected symbol. Units vary: stocks commonly use shares, futures use contracts, and crypto feeds can use base or quote currency. Some feeds supply tick volume, which counts price updates; others have no volume. Check the symbol and feed description before interpreting the result.
The percentage cancels a constant unit scale: converting both endpoints from shares to thousands of shares leaves VROC unchanged. It does not make different exchanges or spot and perpetual markets equivalent. Converting base volume into quote value at each bar introduces price changes into the comparison. The script reads only the current chart feed and does not aggregate exchanges.
Sessions and time of day
A fixed N-bar lookback can compare an opening-session bar with a quieter time of day. In a hypothetical example, opening volume of 900 versus a reference of 300 gives +200%. If the average of comparable opening bars is 1,000, relative volume at that time is only 0.9 times its baseline. Both calculations are correct, but their baselines answer different questions.
Use the same symbol, timeframe and session setting when comparing results. N counts available chart bars, so holidays, shortened sessions and missing bars can break an assumed same-clock-time match. For a time-of-day question, use a session-aware comparison such as TradingView Relative Volume at Time. The VROC example below performs no session adjustment.
Closed bars and alert timing
Volume accumulates while a bar is open. Comparing that partial count with a complete historical bar can make live VROC look unusually low. The example waits for the chart bar to close by default. This controls intrabar changes; it cannot prevent data-provider revisions.
Volume ROC vs price ROC, RVOL and Volume Oscillator
| Measure | Comparison | What the output describes |
|---|---|---|
| Volume ROC | Current volume vs one earlier volume bar | Percentage change in activity |
| Price ROC | Current price vs price N bars earlier | Percentage price change |
| Relative volume (RVOL) | Current volume / a defined historical average | A ratio such as 1.5 times average |
| Volume Oscillator | Fast volume average vs slow volume average | Average-volume difference, raw or normalized |
For example, price can fall from 100 to 95 while volume rises from 1,000 to 1,500 over the same window. Price ROC is -5%; VROC is +50%. The positive volume reading does not turn that price decline into a bullish signal.
Pine Script v6 with missing-volume and zero-base guards
Paste this indicator into TradingView Pine Editor and add it to a chart. The Data Window exposes both volume endpoints. The status box explains unavailable output, and gaps remain gaps instead of being filled with zero.
//@version=6
indicator("Volume Rate of Change: checked baseline", overlay=false, precision=2)
length = input.int(12, "Lookback in bars", minval=1, maxval=500)
threshold = input.float(50.0, "Volume increase threshold (%)", minval=0.0)
confirmedOnly = input.bool(true, "Plot only closed bars")
baseVolume = volume[length]
validVolume = not na(volume) and volume >= 0
validBase = not na(baseVolume) and baseVolume > 0
vroc = validVolume and validBase ? 100.0 * (volume - baseVolume) / baseVolume : na
showBar = not confirmedOnly or barstate.isconfirmed
plot(showBar ? vroc : na, "VROC (%)", color=color.blue, linewidth=2, style=plot.style_linebr)
hline(0, "Unchanged volume", color=color.gray)
plot(volume, "Current volume (feed units)", display=display.data_window)
plot(baseVolume, "Reference volume (feed units)", display=display.data_window)
// A demonstration filter, not an entry or exit system.
priceUp = not na(close[1]) and close > close[1]
filterPassed = barstate.isconfirmed and not na(vroc) and vroc >= threshold and priceUp
plotshape(filterPassed, "Closed-bar filter passed", shape.circle, location.bottom, color.orange, size=size.tiny)
alertcondition(filterPassed, "Volume and price filter", "Closed bar: VROC met the threshold and close exceeded the previous close.")
var table status = table.new(position.top_right, 1, 1)
if barstate.islast
string message = not validVolume ? "Current volume missing or invalid" : na(baseVolume) ? "Reference volume unavailable" : not validBase ? "Reference volume must be positive" : not showBar ? "Waiting for bar close" : "VROC unit: percent"
table.cell(status, 0, 0, message, text_color=color.white, bgcolor=color.new(color.black, 20))- Set the lookback to 2 and inspect any closed bar. Read current and reference volume from the Data Window, then calculate the percentage independently.
- Use 12 only if a 12-bar comparison fits your question. It means 12 chart bars, not a weekly average. Increasing N does not smooth the line.
- The orange marker requires a closed bar, valid VROC at or above the threshold, and close above the previous close. The default 50% threshold is illustrative, with no tested trading advantage.
- Create an alert from the named filter condition and choose once per bar close. It can qualify on consecutive bars; the code does not require a new threshold crossing.
Educational indicator only. The filter has no order execution, exits, position sizing or trading-cost model. A volume increase does not guarantee a breakout or return. Evaluate any trading rules separately; this page is not investment advice.
Adapt the volume filter with Pineify
Pine Script AI Coding Agent can help write or revise the indicator from explicit requirements. Specify the denominator, missing-data behavior, session and price condition, then check the generated script against chart values. It cannot reconstruct volume absent from the data feed.
Keep VROC as 100 × (volume − volume[N]) / volume[N]. Return na for missing endpoints or a nonpositive reference. Add an editable price condition and trigger the filter only at bar close. Expose the reference volume in the Data Window.Open Pine Script AI Coding Agent
Frequently asked questions
Sources and calculation notes
Reviewed October 17, 2026. TradingView documents one-bar volume percentage change and the general N-period ROC definition. This page applies that definition to volume; the numerical tables are hypothetical arithmetic examples, not market observations or backtest results.