Pine Script Volume Rate of Change (Volume ROC)

Master this unique volume-based indicator in TradingView's Pine Script that measures the percentage change in trading volume, providing insights into market participation and trend conviction.

Last Updated on: Expertise: Intermediate

What is Volume Rate of Change (Volume ROC)?

Volume Rate of Change (Volume ROC) is a momentum oscillator that measures the percentage change in trading volume over a specified number of periods. Unlike indicators that calculate the rate of change of price, Volume ROC specifically focuses on volume momentum, indicating whether volume is increasing or decreasing relative to its past levels.

The core idea behind Volume ROC is that volume often precedes price, and changes in volume can provide early signals of shifts in market interest and trend strength. A positive Volume ROC indicates that current volume is higher than the volume `N` periods ago, suggesting increasing participation. A negative Volume ROC indicates current volume is lower, suggesting decreasing participation.

Volume ROC is primarily used to:

In Pine Script, Volume ROC provides a clear way to quantify volume surges and contractions, adding another layer of analysis to trend and momentum strategies.

Components and Calculation

The calculation of Volume Rate of Change is straightforward:

  1. Volume refers to the current bar's trading volume.
  2. Previous Volume refers to the trading volume from `length` periods ago.
  3. Volume ROC Formula:
    `Volume ROC = ((Current Volume - Volume[length]) / Volume[length]) * 100`
    * Handle `Volume[length] == 0` to avoid division by zero.

A common `length` for Volume ROC is 14 periods, but this can be adjusted.

Basic Volume Rate of Change (Volume ROC) Implementation in Pine Script

Pine Script v5 provides a built-in function `ta.roc()` that can be applied to `volume` to calculate Volume ROC.


//@version=5
indicator("My Volume Rate of Change (Volume ROC)", overlay=false, format=format.percent) // overlay=false to plot in a separate pane

// Input for Volume ROC length
length = input.int(14, title="Volume ROC Length", minval=1)

// Calculate Volume ROC using ta.roc applied to volume
// Add a check to prevent division by zero if volume[length] is 0
volumeRocValue = volume[length] != 0 ? ta.roc(volume, length) : 0.0

// Plot the Volume ROC line
plot(volumeRocValue, title="Volume ROC", color=color.blue, linewidth=2)

// Plot the Zero Line as a key reference point
hline(0, "Zero Line", color=color.gray, linestyle=hline.style_dotted)

// Optional: Add reference levels for visual clarity, e.g., +50% and -50%
// These are subjective and depend on the asset and typical Volume ROC values.
hline(50, "Upper Ref (+50%)", color=color.green, linestyle=hline.style_dashed)
hline(-50, "Lower Ref (-50%)", color=color.red, linestyle=hline.style_dashed)

// Highlight areas where Volume ROC is significantly high (volume surge)
bgcolor(volumeRocValue > 50 ? color.new(color.lime, 90) : na, title="High Volume ROC")
Volume Momentum: Volume ROC measures the *rate of change* of volume, not just its absolute level. This helps identify accelerated or decelerated market participation.

Practical Volume ROC Trading Strategies

1. Trend Confirmation

Volume ROC is excellent for confirming the conviction behind a price trend. Ideally, price and Volume ROC should move in the same direction.


//@version=5
strategy("Volume ROC Trend Confirmation", overlay=true)

length = input.int(14, title="Volume ROC Length", minval=1)
volumeRocValue = volume[length] != 0 ? ta.roc(volume, length) : 0.0

plot(volumeRocValue, "Volume ROC", color=color.blue, display=display.pane_only)
hline(0, "Zero Line", color=color.gray, linestyle=hline.style_dotted, display=display.pane_only)

// Price trend filter (e.g., using a long-term EMA)
priceMALength = input.int(50, title="Price MA Length", minval=1)
priceMA = ta.ema(close, priceMALength)

// Conditions for trend confirmation
// Long: Price above MA, and Volume ROC is positive and rising
longConfirm = close > priceMA and volumeRocValue > 0 and volumeRocValue > volumeRocValue[1]

// Short: Price below MA, and Volume ROC is negative and falling
shortConfirm = close < priceMA and volumeRocValue < 0 and volumeRocValue < volumeRocValue[1]

if (longConfirm)
    strategy.entry("Long Confirm", strategy.long)

if (shortConfirm)
    strategy.entry("Short Confirm", strategy.short)

// Basic exit: Price crosses back over price MA or Volume ROC weakens
strategy.close("Long Confirm", when=close < priceMA or volumeRocValue < 0)
strategy.close("Short Confirm", when=close > priceMA or volumeRocValue > 0)

2. Breakout Confirmation

A sudden surge in Volume ROC often provides strong confirmation for a price breakout. When price breaks out of a consolidation or a significant support/resistance level, a corresponding sharp increase in Volume ROC suggests the move has strong institutional backing.


//@version=5
strategy("Volume ROC Breakout Confirmation", overlay=true)

length = input.int(14, title="Volume ROC Length", minval=1)
volumeRocValue = volume[length] != 0 ? ta.roc(volume, length) : 0.0

plot(volumeRocValue, "Volume ROC", color=color.blue, display=display.pane_only)
hline(0, "Zero Line", color=color.gray, linestyle=hline.style_dotted, display=display.pane_only)

bullishRocThreshold = input.float(75, title="Bullish ROC Threshold (%)", minval=10, step=5)
bearishRocThreshold = input.float(-75, title="Bearish ROC Threshold (%)", maxval=-10, step=5)

hline(bullishRocThreshold, "Bullish Threshold", color=color.green, linestyle=hline.style_dashed, display=display.pane_only)
hline(bearishRocThreshold, "Bearish Threshold", color=color.red, linestyle=hline.style_dashed, display=display.pane_only)

// Price breakout conditions (simplified, use proper S/R or channel breaks in real strategy)
// Here, we'll use a simple highest/lowest price breakout for demonstration
priceLookback = input.int(20, title="Price Breakout Lookback", minval=5)
isBullishPriceBreakout = close > ta.highest(high, priceLookback)[1]
isBearishPriceBreakout = close < ta.lowest(low, priceLookback)[1]

// Combined conditions for confirmed breakout
longBreakoutConfirmed = isBullishPriceBreakout and volumeRocValue > bullishRocThreshold
shortBreakoutConfirmed = isBearishPriceBreakout and volumeRocValue < bearishRocThreshold

if (longBreakoutConfirmed)
    strategy.entry("Long Breakout", strategy.long)

if (shortBreakoutConfirmed)
    strategy.entry("Short Breakout", strategy.short)

// Basic exit: trend reversal or fixed percentage
strategy.exit("Long Breakout Exit", from_entry="Long Breakout", profit=close*0.03, loss=close*0.015)
strategy.exit("Short Breakout Exit", from_entry="Short Breakout", profit=close*0.03, loss=close*0.015)

3. Divergence (Key Reversal Signal)

Divergence between price and Volume ROC suggests that the underlying volume momentum is not supporting the current price trend, often preceding a reversal.


//@version=5
strategy("Volume ROC Divergence", overlay=true)

length = input.int(14, title="Volume ROC Length", minval=1)
volumeRocValue = volume[length] != 0 ? ta.roc(volume, length) : 0.0

plot(volumeRocValue, "Volume ROC", color=color.blue, display=display.pane_only)
hline(0, "Zero Line", color=color.gray, linestyle=hline.style_dotted, display=display.pane_only)

// Simple divergence detection (conceptual, robust detection requires advanced pivot logic)
// This example looks for recent higher/lower swings in price and Volume ROC.

// Bullish Divergence: Price lower low, Volume ROC higher low
bullishDiv = close < close[1] and close[1] < close[2] and volumeRocValue > volumeRocValue[1] and volumeRocValue[1] > volumeRocValue[2]

// Bearish Divergence: Price higher high, Volume ROC lower high
bearishDiv = close > close[1] and close[1] > close[2] and volumeRocValue < volumeRocValue[1] and volumeRocValue[1] < volumeRocValue[2]

// Plot shapes on the chart to indicate divergence
plotshape(bullishDiv, title="Bullish Vol ROC Divergence", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.small)
plotshape(bearishDiv, title="Bearish Vol ROC Divergence", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small)

if (bullishDiv)
    strategy.entry("Long Divergence", strategy.long)

if (bearishDiv)
    strategy.entry("Short Divergence", strategy.short)

// Basic exit after a few bars or on opposite signal
strategy.exit("Long Divergence Exit", from_entry="Long Divergence", profit=close*0.02, loss=close*0.01)
strategy.exit("Short Divergence Exit", from_entry="Short Divergence", profit=close*0.02, loss=close*0.01)

Optimizing Volume Rate of Change (Volume ROC) Performance

To get the most from Volume Rate of Change in Pine Script:

Volume as a Leading Indicator: Volume often changes before price. Volume ROC helps you spot these shifts in market participation, potentially giving you an edge.

Common Volume Rate of Change (Volume ROC) Pitfalls

Conclusion

Volume Rate of Change (Volume ROC) is an insightful technical indicator available in Pine Script for TradingView that focuses specifically on volume momentum. By quantifying the percentage change in trading volume over time, it provides traders with valuable insights into the underlying conviction behind price movements, aiding in trend confirmation, breakout detection, and identifying potential reversals through divergence. While it requires careful interpretation and combination with price action, mastering Volume ROC can significantly enhance your pine script strategies by providing a clearer understanding of market participation and the efficiency of price trends.