The Intuition

Rate of Change (ROC) momentum is the most direct measure of price momentum: it simply measures the percentage change in price over a lookback period. If the N-day ROC exceeds a positive threshold, the asset has been rising — go long. If it falls below a negative threshold, the asset has been falling — go short. No smoothing, no signal line, no indicator derivation.

ROC captures the core finding of Jegadeesh and Titman (1993): stocks that outperform over the past 3–12 months tend to continue outperforming over the next 3–12 months. The threshold in our implementation adds a minimum hurdle: minor moves are ignored, only meaningful momentum triggers a position. This reduces turnover in choppy markets compared to a threshold-less momentum strategy.

ROC is often used as a building block in factor models rather than as a standalone strategy. In Fama-French-Carhart factor models, the momentum factor (UMD — Up Minus Down) is essentially a cross-sectional version of ROC: long the top decile of trailing 12-month returns, short the bottom decile. Our implementation adapts this cross-sectional insight to a single-asset time-series context.

Key assumptions: (1) The lookback period captures a meaningful momentum horizon for the asset. A 20-day ROC is a short-term momentum signal; a 252-day ROC is a long-term signal. (2) The threshold filters out noise — assets with ROC near zero are in no clear trend and should be held flat. (3) Momentum has sufficient persistence that the position entered today will be profitable before the signal reverses.

ROC momentum suffers from momentum crashes — sudden, sharp reversals in previously high-momentum assets. Barroso and Santa-Clara (2015) showed that momentum crashes are predictable using realised variance: momentum strategies tend to crash when market volatility is high and the market has been falling (conditions that generate large short-term reversals). Volatility scaling the ROC position by dividing by recent realised volatility significantly improves Sharpe ratios in practice.

The Math

Read this as a compact model summary: what the signal sees, what it ignores, and where fragility can creep in.

ROC(t, n) = (Close(t) - Close(t-n)) / Close(t-n)

Signal(t) = +1  if ROC(t) >  threshold
          = -1  if ROC(t) < -threshold
          =  0  otherwise

Parameters

ParameterTypeDefaultDescription
period int 20 Lookback period for rate of change calculation
threshold float 0.02 ROC magnitude threshold to trigger a trade

Source Code

def run(ticker: str, start: str, end: str, **params) -> dict:
    period = int(params.get("period", 20))
    threshold = float(params.get("threshold", 0.02))
    df = fetch_ohlcv(ticker, start, end)

    roc = df["Close"].pct_change(period)
    pos = pd.Series(0.0, index=df.index)
    pos[roc > threshold] = 1.0
    pos[roc < -threshold] = -1.0

    return run_backtest(df, pos, ticker=ticker, start=start, end=end,
                        strategy=METADATA["slug"], params={"period": period, "threshold": threshold})

Further Reading

  • Kaufman, P. (2013). Trading Systems and Methods, 5th ed. Wiley.
  • Jegadeesh, N. & Titman, S. (1993). Returns to Buying Winners and Selling Losers. Journal of Finance, 48(1), 65–91.
  • Chan, E. (2013). Algorithmic Trading, Ch. 2. Wiley.

When It Works / When It Fails

Works
  • Trending markets where raw return predicts continuation
  • Broad indices during clear directional phases
  • When threshold filters out low-conviction noise signals
Fails
  • Range-bound, oscillating markets with no persistence
  • Threshold too tight — always in market regardless of regime
  • Threshold too loose — signal almost never fires

Regime Fit

Bull / Calm or Normal vol
Best conditions at 1.0 long. Raw return sign predicts continuation most reliably.
Bull / Stressed vol
Scaled to 0.75 long. Signal valid but return series noisier.
Transition / any vol
0.0–0.35. Return sign flips frequently; threshold may not protect fully.
Bear side
Mirrors Bull profile on short scale. Threshold and lookback apply symmetrically.

Compared to Alternatives

vs TSMOM
Both use lookback return sign; ROC adds a magnitude threshold so it only fires when |return| exceeds a hurdle. TSMOM fires on any non-zero return.
vs MA Crossover
ROC uses raw period return; MA Crossover uses smoothed SMA level comparison. ROC is a more volatile signal with no smoothing applied.
vs MACD
MACD is a smoothed EMA divergence measure; ROC is the raw lookback return. ROC is simpler with fewer parameters but more sensitive to noise.
Run This Strategy →