Indicator TutorialPine Script v5

How to Code the Momentum Indicator in Pine Script

Price change over n bars, zero-line interpretation, and ROC context

Momentum measures how much price has moved compared to a past bar, typically as the arithmetic difference between the current close and the close n periods ago. It is intuitive, fast to compute, and pairs well with trend and volume tools. This tutorial covers the math, zero-line logic, and a complete Pine Script v5 example using ta.mom() with optional smoothing and signal markers.

What Is the Momentum Indicator?

Momentum in its simplest form is close - close[n], the raw change in price over n bars. Positive values mean price has increased versus the lookback; negative values mean it has decreased.

This differs from Rate of Change (ROC), which expresses movement as a percentage: (close / close[n] - 1) × 100, though both answer the same question—how much motion occurred.

Why traders use it

Momentum highlights acceleration and deceleration of price trends and helps time entries when pace expands in the direction of the dominant move.

Why Traders Use This Indicator

  • See instantaneous pace of price change without bounding to 0–100 like RSI.
  • Use zero-line crosses as simple bias toggles when confirmed by structure.
  • Compare momentum peaks to price peaks to spot potential exhaustion.
  • Feed momentum into broader systems as a feature or filter.
ParameterDefaultDescription
Length10Lookback bars for the reference close. Shorter lengths are reactive; longer lengths emphasize slower drifts.
SourcecloseMost implementations use close; you can test hl2 or hlc3 for smoother behavior.
Smoothing (optional)None / SMA(3)Applying a short MA to momentum can reduce noise while preserving direction.
Signal line (optional)EMA(9) of momentumCrossings between momentum and its signal mimic MACD-style timing on pace.

How Momentum Is Calculated

Basic momentum: MOM = source - source[n]

TradingView’s ta.mom(source, length) implements this difference using the specified length as the lookback offset.

ROC link: Percentage ROC can be written as (source / source[n] - 1) * 100, which rescales momentum by past price level.

Normalization note: Raw momentum is in price units; comparing across symbols requires scaling (e.g., percent) or using logarithmic prices.

Signal Interpretation

Above zero: Price is higher than n bars ago—bullish impulse in isolation.

Below zero: Bearish impulse versus the lookback window.

Zero-line cross: Indicates a sign change in the n-bar return; confirm with higher-timeframe bias to avoid chop.

Divergence: Price prints higher highs while momentum prints lower highs (bearish); inverse for bullish—treat as a warning, not a guarantee.

Combining with Other Indicators

Combine momentum with a 200 MA or MACD to align pace signals with prevailing trend.

Volume spikes alongside rising momentum can validate breakout participation.

Bollinger Bands on momentum highlight statistically rare pace readings for mean-reversion or breakout follow-through setups.

The Hard Way: Writing Pine Script Manually

Challenges of Manual Coding

Implement ta.mom manually and assert equality with the built-in across the chart.

Plot both momentum and ROC in separate panes with synced scales for study.

Add a volatility-normalized momentum: mom / ta.atr(14).

Build a histogram coloring bars by momentum sign and magnitude buckets.

Detect momentum crests using pivot points and label them on chart.

Pine Script v5
//@version=5
indicator("Momentum Tutorial (ta.mom)", shorttitle="MOM", overlay=false)

// -----------------------------------------------------------------------------
// Inputs
// -----------------------------------------------------------------------------
length = input.int(10, "Momentum length", minval=1)
src = input.source(close, "Source")
smoothLen = input.int(3, "Smoothing length (0 = off)", minval=0)
signalLen = input.int(9, "Signal line length", minval=1)
showHist = input.bool(true, "Show histogram")
showZero = input.bool(true, "Highlight zero crosses")

// -----------------------------------------------------------------------------
// Core series
// -----------------------------------------------------------------------------
mom = ta.mom(src, length)
momSmoothed = smoothLen > 0 ? ta.sma(mom, smoothLen) : mom
signal = ta.ema(momSmoothed, signalLen)

// -----------------------------------------------------------------------------
// Cross conditions
// -----------------------------------------------------------------------------
crossZeroUp = ta.crossover(momSmoothed, 0)
crossZeroDn = ta.crossunder(momSmoothed, 0)
crossSigUp = ta.crossover(momSmoothed, signal)
crossSigDn = ta.crossunder(momSmoothed, signal)

// -----------------------------------------------------------------------------
// Plots
// -----------------------------------------------------------------------------
plot(momSmoothed, "Momentum", color=color.teal, linewidth=2)
plot(signal, "Signal", color=color.orange, linewidth=1)
hline(0, "Zero", color=color.gray, linestyle=hline.style_dotted)

plot(showHist ? momSmoothed : na, "Momentum hist", style=plot.style_histogram, color=momSmoothed >= 0 ? color.new(color.teal, 35) : color.new(color.orange, 35))

plotshape(crossZeroUp and showZero, "Zero up", shape.circle, location.absolute, color.new(color.green, 0), size=size.tiny, text="0+")
plotshape(crossZeroDn and showZero, "Zero dn", shape.circle, location.absolute, color.new(color.red, 0), size=size.tiny, text="0-")

bgcolor(crossSigUp ? color.new(color.green, 92) : crossSigDn ? color.new(color.red, 92) : na)

// -----------------------------------------------------------------------------
// ROC companion (for data window study)
// -----------------------------------------------------------------------------
roc = (src / src[length] - 1.0) * 100.0
plot(roc, "ROC % (data window)", display=display.data_window)

// -----------------------------------------------------------------------------
// Alerts
// -----------------------------------------------------------------------------
alertcondition(crossZeroUp, "Momentum cross above zero", "Smoothed momentum crossed above zero")
alertcondition(crossZeroDn, "Momentum cross below zero", "Smoothed momentum crossed below zero")
alertcondition(crossSigUp, "Momentum cross above signal", "Momentum crossed above signal line")
alertcondition(crossSigDn, "Momentum cross below signal", "Momentum crossed below signal line")

// -----------------------------------------------------------------------------
// Summary table
// -----------------------------------------------------------------------------
var table tab = table.new(position.top_right, 1, 3, bgcolor=color.new(color.black, 78))
if barstate.islast
    table.cell(tab, 0, 0, "Mom: " + str.tostring(momSmoothed, "#.##"), text_color=color.white)
    table.cell(tab, 0, 1, "Sig: " + str.tostring(signal, "#.##"), text_color=color.silver)
    table.cell(tab, 0, 2, "ROC%: " + str.tostring(roc, "#.##"), text_color=color.silver)

Maintenance Note: Momentum is unit-dependent; when switching symbols, revisit smoothing and signal lengths. If Pine adjusts ta.mom() definition, revalidate against manual close - close[n] on your chart.

The Easy Way: Build with Pineify Visual Editor

What if you could create the same indicator without writing a single line of code? Pineify is a visual editor designed for TradingView users who want professional-grade indicators through an intuitive interface.

FeatureManual Pine ScriptPineify Visual Editor
ReadabilityMixing momentum with ROC and filters inflates script length.Keeps modules separated for easier navigation.
ExperimentationSwapping lengths requires editing multiple lines.Input-driven blocks make A/B tests faster.
AlertsBoilerplate alertconditions are easy to miswire.Reusable alert patterns reduce mistakes.
ScalingHarder to normalize across tickers inside raw Pine.Composable transforms (e.g., / ATR) stay organized.
OnboardingNew users must learn series indexing nuances.Visual wiring lowers the initial learning curve.

Assemble momentum, smoothing, and signals without repetitive code.

Export consistent Pine v5 for teams and publishing.

Layer confirmations visually before writing branching logic by hand.

Iterate lengths and sources with guardrails on min/max values.

Step-by-Step Tutorial

1

Create pane indicator

Use overlay=false so momentum displays beneath price.

2

Add ta.mom()

Pick source and length; verify sign against a manual difference.

3

Optional smoothing

Add SMA/EMA on the momentum series to tame noisy symbols.

4

Signal line

Plot EMA of momentum and mark crosses for timing triggers.

5

Zero-line cues

Highlight crosses and add alerts for regime change notifications.

6

Export

Generate Pine, paste to TradingView, and compare to your research notes.

Trading Strategies & Pro Tips

Zero-line with trend filter

Long when price > 200 SMA and smoothed momentum crosses above zero; exit on cross below zero or trailing stop.

Pro Tip: Add a minimum hold time to avoid micro chop entries.

Signal line momentum

Trade in direction of signal cross only if ADX > 20 to ensure some trend strength.

Breakout pace

On range breakouts, require momentum histogram expansion for two consecutive bars before entering.

Divergence fade (advanced)

Mark divergence, then wait for momentum histogram to cross zero against the prior impulse before fading.

Pro Tip: Keep risk tight; divergences can extend in strong trends.

Common Mistakes to Avoid

  • Using very short lengths on choppy assets, generating constant zero crosses.
  • Confusing momentum with ROC when comparing readings across symbols.
  • Trading zero crosses against a strong higher-timeframe downtrend.
  • Ignoring that momentum is unbounded and can spike on news.
  • Smoothing excessively until signals lag beyond acceptable drawdowns.

Frequently Asked Questions

Prototype momentum logic faster with Pineify

  • Wire ta.mom(), smoothing, and alerts with less boilerplate.
  • Export Pine v5 aligned with TradingView conventions.
  • Test combinations with MACD, ADX, and MA filters visually.

Disclaimer: Trading involves significant risk. The indicators, code, and strategies provided are for educational purposes only and do not constitute financial advice. Past performance is not indicative of future results.