Rate of Change indicator: formula, code and limits
The Rate of Change indicator (ROC) measures the percentage difference between the current price and the price N bars earlier. Its zero line marks equal endpoints. With a positive reference price, a positive ROC means the current price is higher; a negative value means it is lower. Use the calculation table and Pine Script below to check the denominator, lookback and closing-bar behavior before turning a crossing into a trading rule.
ROC = 100 × (source − source[N]) / source[N]
Output: percent · Default example: 9 bars · Reference: N bars back
Formula and default inputs: TradingView ROC documentation.
A 2-period example you can recompute
These are hypothetical closes on consecutive chart bars, with source = close and N = 2. Values are rounded to four decimals for display. No market prices or backtest results are implied.
| Bar | Close | Close[2] | Momentum | ROC(2) |
|---|---|---|---|---|
| 0 | 100 | Not available | Not available | Not available |
| 1 | 110 | Not available | Not available | Not available |
| 2 | 105 | 100 | +5 | +5.0000% |
| 3 | 108 | 110 | -2 | -1.8182% |
| 4 | 108 | 105 | +3 | +2.8571% |
Bar 3: 100 × (108 − 110) / 110 = −1.8182%. Price rose from 105 to 108 on that bar, yet ROC is negative because the comparison is with 110 two bars earlier. At bar 4, price stays at 108 while ROC turns positive: the reference rolls from 110 to 105.
This is why a rising ROC is not proof of accelerating price. Both endpoints can change. ROC(2) is also not the sum of two daily returns: +10% followed by −4.5455% compounds to +5%, rather than +5.4545%.
Choose the window and keep the inputs comparable
| Input | Example default | What to check |
|---|---|---|
| Length | 9; accepted range 1 to 500 | A bar offset, not an average; N = 2 needs the current bar plus two earlier bars. |
| Source | Close | Keep the source identical when comparing scripts. |
| Chart context | Current chart | Match interval, session, symbol feed and chart type. |
On a 5-minute chart, N = 2 compares closes two chart bars apart, nominally 10 minutes during continuous trading. On a daily chart it compares two daily bars. Session gaps and missing bars mean the elapsed clock time can be longer. The script does not request another timeframe.
Start with standard candles. Heikin Ashi and other non-standard charts can supply synthetic prices, changing the inputs to the same formula. TradingView documents chart price and timeframe behavior.
Copy the ROC indicator in Pine Script v6
Paste the complete script into TradingView Pine Editor, save it and add it to a chart. It exposes length and source, leaves gaps for undefined percentages, and shows the reference price and absolute Momentum in the Data Window. It is an indicator, with no strategy orders.
//@version=6
indicator("Rate of Change: checked baseline", overlay = false, precision = 4)
length = input.int(9, "Length in bars", minval = 1, maxval = 500)
source = input.source(close, "Source")
base = source[length]
validBase = not na(source) and not na(base) and base != 0
roc = validBase ? 100.0 * (source - base) / base : na
plot(roc, "ROC (%)", color = color.blue, linewidth = 2, style = plot.style_linebr)
hline(0, "Zero", color = color.gray)
plot(base, "Reference source", display = display.data_window)
plot(source - base, "Momentum (source units)", display = display.data_window)
crossUp = ta.crossover(roc, 0)
crossDown = ta.crossunder(roc, 0)
positiveBases = base > 0 and base[1] > 0
confirmedUp = crossUp and positiveBases and barstate.isconfirmed
confirmedDown = crossDown and positiveBases and barstate.isconfirmed
plotshape(confirmedUp, "Confirmed cross up", shape.triangleup, location.bottom, color.green, size = size.tiny)
plotshape(confirmedDown, "Confirmed cross down", shape.triangledown, location.top, color.red, size = size.tiny)
alertcondition(confirmedUp, "ROC crossed above zero", "ROC crossed above zero on a closed bar with positive reference prices.")
alertcondition(confirmedDown, "ROC crossed below zero", "ROC crossed below zero on a closed bar with positive reference prices.")- The blue line is the current ROC percentage. The gray line is zero.
- Green and red triangles mark confirmed zero crossings only when both the current and previous reference prices are positive.
- The live line can move before close. Markers and alert conditions wait for
barstate.isconfirmed; create a TradingView alert from the named condition if needed. - A missing source or reference, or a zero reference, produces
na. The line-break plot style avoids connecting across these gaps.
History access and confirmation semantics: Pine operators and bar states. Syntax checking does not establish trading performance.
Zero, negative and near-zero reference prices
The denominator determines whether the percentage has a useful interpretation. The following cases are arithmetic examples, not claims about a particular instrument.
| Reference → current | Arithmetic ROC | Interpretation |
|---|---|---|
| 0 → 5 | Undefined | Return na; replacing the denominator with 1 changes the measure. |
| −10 → −5 | −50% | Price rises by 5; a negative base reverses the sign. |
| 0.01 → 1 | +9,900% | A small denominator magnifies the ratio. |
| 100 → 0 | −100% | The floor applies only if the reference is positive and the current price cannot be negative. |
The script retains the signed formula for negative bases so you can inspect the value. It disables crossing alerts across nonpositive reference prices. If your series can cross zero, use absolute price differences or define another normalization explicitly; dividing by the absolute reference would be a different indicator.
A missing early value is not 0% momentum. The history operator has no value N bars back until enough history exists. Replacing that missing reference with zero or the current price would invent observations.
ROC versus absolute Momentum
For the same endpoints, Momentum is the numerator of ROC. A move from 50 to 55 gives Momentum = +5 price units and ROC = +10%. A move from 500 to 505 gives the same Momentum but ROC = +1%. Percentage units remove the nominal price scale; they do not equalize volatility, liquidity or trading costs.
For a hypothetical forex quote of 1.1000 rising to 1.1110, ROC is +1%. This is not a pip count or a 1% account gain. Reversing the quote gives about −0.9901%, since the base changes. Likewise, a +10% price move followed by −10% leaves the price 1% below its starting point.
A zero crossing only compares endpoints, and repeated crossings can occur in a range. Fixed overbought or oversold levels need a defined instrument and sample. Neither a large ROC nor divergence alone specifies an entry, an exit or a profitable trade.
Read the absolute Momentum indicator guideBuild and check a custom ROC rule with Pineify
- Open the Pine Script AI Coding Agent and request an ROC indicator with a chosen source and length.
- Specify the boundary policy: missing and zero bases return na; negative bases remain visible but do not trigger directional alerts.
- Request chart-bar confirmation for crossing conditions, and state whether the live plot should update before close.
- Copy the output into TradingView and compare the current source, reference and ROC on several closed bars. Use length 2 for the table checks.
- Define exits, sizing and costs separately if you later request a strategy. Verify those rules before interpreting any backtest.
Educational calculations and code; not investment advice or a performance guarantee.
Rate of Change questions
Sources and related guides
Official documentation checked October 17, 2026. Tables are original hypothetical calculations.