Pine Script ROC (Rate of Change)

Master this fundamental momentum indicator in TradingView's Pine Script for identifying trend strength, overbought/oversold conditions, and divergence.

Subscribe now @ $99/month

What is the Rate of Change (ROC)?

The Rate of Change (ROC) is a pure momentum oscillator that measures the percentage change in price over a specified period. It indicates the speed and direction of price movement, helping traders identify trend strength and potential reversals. Unlike bounded oscillators (like RSI or Stochastic), ROC oscillates around a zero line and has no upper or lower limits, allowing it to reflect the full extent of price surges or drops.

In Pine Script, ROC is a straightforward yet powerful tool for assessing how quickly price is accelerating or decelerating, providing insights into momentum shifts and trend conviction.

Components and Calculation

The calculation of ROC is simple:

  1. Current Close (C): The most recent closing price.
  2. Previous Close (C_n): The closing price `N` periods ago.
  3. ROC Formula:
    `ROC = ((Current Close - Close N periods ago) / Close N periods ago) * 100`
    A positive ROC value indicates that the current price is higher than `N` periods ago, signaling bullish momentum. A negative ROC value indicates the current price is lower, signaling bearish momentum. The further away from zero, the stronger the momentum.

Basic Rate of Change (ROC) Implementation in Pine Script

Pine Script v5 provides a straightforward built-in function `ta.roc()` for calculating the Rate of Change.

//@version=5
indicator("My Rate of Change Indicator", overlay=false) // overlay=false to plot in a separate pane

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

// Calculate ROC value using the built-in function
rocValue = ta.roc(close, length)

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

// Plot the Zero Line
hline(0, "Zero Line", color.gray, linestyle=hline.style_dotted)

// Optional: Add typical extreme levels for visual reference (adjust based on asset)
hline(10, "Upper Reference (+10)", color.red, linestyle=hline.style_dashed)
hline(-10, "Lower Reference (-10)", color.green, linestyle=hline.style_dashed)
Zero Line is Key: The zero line is the most important level for ROC. Values above zero indicate upward momentum, values below zero indicate downward momentum.

Practical ROC Trading Strategies

1. Zero Line Crossover (Momentum Shift)

The crossover of the zero line is a primary signal from ROC, indicating a shift in momentum from bullish to bearish or vice versa. This can be used to identify new trends or confirm a change in the prevailing bias.

//@version=5
strategy("ROC Zero Line Crossover Strategy", overlay=true)

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

// Calculate ROC
rocValue = ta.roc(close, length)

// Plot ROC in a separate pane
plot(rocValue, "ROC", color.blue, display=display.pane_only)
hline(zeroLine, "Zero Line", color.gray, linestyle=hline.style_dotted, display=display.pane_only)

// Define conditions for entries
longSignal = ta.crossover(rocValue, zeroLine)
shortSignal = ta.crossunder(rocValue, zeroLine)

// Strategy entries/exits
if (longSignal)
    strategy.entry("Long", strategy.long)

if (shortSignal)
    strategy.entry("Short", strategy.short)

2. Extreme Readings (Overbought/Oversold)

Although ROC has no fixed upper/lower bounds, historically extreme positive or negative values can indicate overbought or oversold conditions, respectively. These extreme levels need to be determined by analyzing an asset's historical ROC behavior, as they vary widely.

//@version=5
indicator("ROC Extreme Readings Scanner", overlay=true)

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

// Define custom overbought/oversold levels based on asset's historical behavior
// Adjust these values after observing your chosen asset's ROC range
customOverbought = input.float(15.0, title="Custom Overbought Level")
customOversold = input.float(-15.0, title="Custom Oversold Level")

// Calculate ROC
rocValue = ta.roc(close, length)

// Plot ROC in a separate pane
plot(rocValue, "ROC", color.blue)
hline(0, "Zero Line", color.gray, linestyle=hline.style_dotted)
hline(customOverbought, "Custom Overbought", color.red, linestyle=hline.style_dashed)
hline(customOversold, "Custom Oversold", color.green, linestyle=hline.style_dashed)

// Signals for potential reversals from extremes
alertcondition(ta.crossunder(rocValue, customOverbought), "ROC Overbought Exit", "ROC moved below custom overbought level.")
alertcondition(ta.crossover(rocValue, customOversold), "ROC Oversold Exit", "ROC moved above custom oversold level.")

plotshape(ta.crossunder(rocValue, customOverbought) and rocValue[1] > customOverbought, title="Overbought Reversal", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small)
plotshape(ta.crossover(rocValue, customOversold) and rocValue[1] < customOversold, title="Oversold Reversal", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.small)

3. ROC Divergence Strategy

Divergence between price and ROC is a strong signal for a potential trend reversal, as it indicates a weakening of the underlying momentum.

//@version=5
indicator("ROC Divergence Scanner", overlay=true)

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

// Calculate ROC
rocValue = ta.roc(close, length)

// Plot ROC in a separate pane
plot(rocValue, "ROC", color.blue)
hline(0, "Zero Line", color.gray, linestyle=hline.style_dotted)

// Simple divergence detection (conceptual, robust detection requires advanced pivot logic)
// This is a simplified example focusing on price vs ROC divergence.

// Bullish Divergence (Price lower low, ROC higher low)
bullishDivergence = close[2] > close[1] and close[1] > close and rocValue[2] < rocValue[1] and rocValue[1] < rocValue

// Bearish Divergence (Price higher high, ROC lower high)
bearishDivergence = close[2] < close[1] and close[1] < close and rocValue[2] > rocValue[1] and rocValue[1] > rocValue

plotshape(bullishDivergence, title="Bullish Divergence", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.small)
plotshape(bearishDivergence, title="Bearish Divergence", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small)

alertcondition(bullishDivergence, "Bullish ROC Divergence", "Potential bullish reversal based on ROC divergence.")
alertcondition(bearishDivergence, "Bearish ROC Divergence", "Potential bearish reversal based on ROC divergence.")

Optimizing ROC Performance

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

Relative Power: ROC tells you not just *if* price is changing, but *how fast* that change is occurring relative to a past point, giving a sense of the momentum's power.

Common ROC Pitfalls

Conclusion

The Rate of Change (ROC) is a fundamental and insightful momentum oscillator in Pine Script for TradingView. Its straightforward calculation provides a clear measure of price acceleration and deceleration, making it valuable for identifying shifts in momentum, confirming trend strength, and spotting potential reversals through divergence. By understanding its mechanics, thoughtfully tuning its parameters, and integrating it strategically with other technical analysis tools, you can leverage the ROC to gain a deeper understanding of market dynamics and enhance your trading decisions.

Enhance Your Trading

Get a high-performance Pine Script analysis tool for actionable market insights, designed for traders on the move.

This strategy runs in live mode on TradingView, helping you identify potential opportunities.

Subscribe now @ $99/month