What it measures
The Rate of Change is the percentage change in price over a fixed number of bars. A 9-period ROC of +3 means the close is 3% higher than it was nine bars ago. It oscillates around zero: positive when price is higher than N bars ago, negative when it's lower.
It's one of the simplest momentum indicators, and a close relative of the momentum indicator, which shows the same change in price units instead of percent. Because ROC is a percentage, its values can be compared across symbols in a way that MACD or momentum values can't.
The formula in words
- Pick a length N.
- ROC = 100 × (close − close N bars ago) ÷ close N bars ago.
That's all. Pine Script has ta.roc(source, length), which returns the same value; the script writes it out. The optional signal line is a simple moving average of ROC.
Because only two prices are involved, ROC moves when either of them changes. A large bar dropping out of the window N bars later shifts ROC as much as a new bar does; this is sometimes called the drop-off effect.
How traders read it
- Zero-line crosses. ROC crossing above zero means price is now higher than N bars ago. It's a slow, simple trend signal; with long lengths (100 to 250 bars) it's used as a trend filter.
- Acceleration. Rising ROC means the move over the window is speeding up; falling ROC while price still rises means the move is slowing.
- Relative extremes. ROC has no fixed range, so traders compare it with its own history on the same symbol: a reading near the highest of the past year is stretched for that market.
- Ranking. Because it's a percentage, ROC over a fixed window is often used to rank symbols by momentum.
Common settings
| Length | Typical use |
|---|---|
| 9 to 14 | Short-term momentum |
| 21 to 25 | About one month of daily bars |
| 125 to 250 | Six to twelve months of daily bars, for trend filters and momentum ranking |
The optional signal line is usually a 9-period SMA. Short lengths cross zero constantly, so most traders pair them with a longer filter.
Pine Script v6 code
The complete, self-contained script is below. Copy it into a new indicator in TradingView's Pine Editor, or download the .pine file.
//@version=6
indicator("Rate of Change (ROC)", shorttitle = "ROC", format = format.percent, precision = 2)
src = input.source(close, "Source", group = "Calculation")
len = input.int(9, "Length", minval = 1, group = "Calculation")
showSig = input.bool(true, "Show signal line", group = "Signal line")
sigLen = input.int(9, "Signal line length (SMA)", minval = 1, group = "Signal line")
// Percentage change of the source over len bars.
roc = src[len] != 0 ? 100 * (src - src[len]) / src[len] : na
sig = ta.sma(roc, sigLen)
zeroUp = ta.crossover(roc, 0)
zeroDown = ta.crossunder(roc, 0)
sigUp = ta.crossover(roc, sig)
sigDown = ta.crossunder(roc, sig)
plot(roc, "ROC", color = roc >= 0 ? color.new(color.teal, 0) : color.new(color.red, 0), linewidth = 2)
plot(showSig ? sig : na, "Signal", color = color.new(color.orange, 0))
hline(0, "Zero", color = color.new(color.gray, 50))
plotshape(zeroUp, "Crosses above zero", shape.triangleup, location.bottom, color.new(color.teal, 0), size = size.tiny)
plotshape(zeroDown, "Crosses below zero", shape.triangledown, location.top, color.new(color.red, 0), size = size.tiny)
alertcondition(zeroUp, "ROC above zero", "ROC crossed above zero on {{ticker}} ({{interval}})")
alertcondition(zeroDown, "ROC below zero", "ROC crossed below zero on {{ticker}} ({{interval}})")
alertcondition(sigUp, "ROC above signal", "ROC crossed above its signal line on {{ticker}} ({{interval}})")
alertcondition(sigDown, "ROC below signal", "ROC crossed below its signal line on {{ticker}} ({{interval}})")ROC is plotted in its own pane, green above zero and red below, with an optional signal line and triangles on zero-line crosses. Values are formatted as percentages.
Four alert conditions cover zero-line and signal-line crosses in both directions. Set them to Once per bar close.
Add it to your chart
- Open any chart on TradingView and open the Pine Editor.
- Create a new indicator, delete the template code and paste the script.
- Click Save, then Add to chart. Change lengths and levels from the indicator's settings.
Stuck on an error? See how to add a Pine Script indicator to TradingView.
Pitfalls
- The drop-off effect. A large bar leaving the window moves ROC even if today's price barely changes. Check the bar N periods back before reading a jump.
- No fixed levels. "ROC above 5" means very different things on a currency pair and a small-cap stock. Compare with the symbol's own history.
- Noise at short lengths. A 3- or 5-period ROC crosses zero all the time.
- Live-bar crosses. The close isn't final until the bar closes.
Related reading
- Pine Script alerts: alertcondition() vs alert(), messages, webhooks and frequency
- 8 backtesting mistakes that make a strategy look better than it is
- Expectancy & Win-Rate Calculator (free tool)
- Correlation Calculator (free tool)
The script is an educational example: test it on your own markets before relying on it. Indicators describe the past; they don't predict the future. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.