Indicator library · Momentum

Relative Momentum Index (RMI)

RSI with one substitution: each close is compared to the close n bars back rather than to the one immediately before it. That single change is what makes the line hold its extremes through a trend instead of oscillating across the middle.

The calculation

Roger Altman published the Relative Momentum Index in 1993. It takes two parameters, a length and a momentum, and is computed in three steps.

  1. For each bar, take the change against the close n bars ago, where n is the momentum parameter: change = close − close[i − n]. Positive changes go to the up series, negative ones to the down series as positive numbers.
  2. Average each series with Wilder smoothing over the length parameter: the first value is a simple mean, and every value after it is ((previous × (len − 1)) + current) ÷ len.
  3. Convert to the index exactly as RSI does: RMI = 100 − (100 ÷ (1 + average up ÷ average down)). When the average down is zero, RMI is defined as 100.

Setting the momentum parameter to 1 makes step one identical to RSI's, and the two indicators produce the same line. That equivalence is the most reliable way to check an implementation: if your RMI with momentum 1 does not match your RSI, the bug is in the smoothing, not in the momentum lookback.

Price with its Relative Momentum IndexThe upper panel shows a price series rising for about fifteen bars and then falling back. The lower panel shows the RMI on a nought-to-one-hundred scale, which holds above the seventy line through most of the advance rather than oscillating across the middle, then falls through fifty and reaches the low thirties during the decline.CLOSE705030RMI 8/334.92Price with its Relative Momentum IndexThe upper panel shows a price series rising for about fifteen bars and then falling back. The lower panel shows the RMI on a nought-to-one-hundred scale, which holds above the seventy line through most of the advance rather than oscillating across the middle, then falls through fifty and reaches the low thirties during the decline.CLOSE70RMI 8/334.92
Fig. 1: schematicComputed at build time from the formula above with a length of 8 and a momentum of 3. Watch what the line does during the advance: it stays high rather than dipping every time price pauses, because a one-bar pullback is not a down bar when the comparison reaches three bars back. That persistence is the whole reason to choose this over RSI, and it is also why the line takes longer to admit that the trend has ended.

Reading it

Everything true of RSI applies, with one adjustment: the extremes are stickier. In a trend, RMI with a momentum of 5 will sit above 70 for long stretches, and treating each crossing as a signal produces a stream of losing counter-trend trades. The reading that survives is the same one that survives on RSI, divergence, where price makes a higher high and the oscillator does not.

The momentum parameter deserves to be chosen against the swing length you actually trade. If your typical pullback lasts three days, a momentum of 5 will absorb it entirely and the oscillator will never register it; that is either exactly what you want or a way of hiding the thing you needed to see, and only you can say which.

Reference implementation

The code below is the function that produced the figure on this page. It is written to be read rather than to be fast: two passes, no libraries, and the Wilder recursion spelled out. A correct port of it will reproduce the values in the table that follows exactly.

function rmi(close, len, mom) {
  const up = [], dn = [];
  for (let i = mom; i < close.length; i++) {
    const ch = close[i] - close[i - mom];      // NOT close[i-1]
    up.push(Math.max(ch, 0));
    dn.push(Math.max(-ch, 0));
  }
  const out = [];
  let au = up.slice(0, len).reduce((a, b) => a + b, 0) / len;   // simple-mean seed
  let ad = dn.slice(0, len).reduce((a, b) => a + b, 0) / len;
  const emit = () => out.push(ad === 0 ? 100 : 100 - 100 / (1 + au / ad));
  emit();
  for (let i = len; i < up.length; i++) {
    au = (au * (len - 1) + up[i]) / len;        // Wilder: weight 1/len, not 2/(len+1)
    ad = (ad * (len - 1) + dn[i]) / len;
    emit();
  }
  return out;   // out[0] corresponds to bar index mom + len - 1
}

Three lines carry all the usual bugs. The lookback in the first loop must reach back mom bars, not one. The seed must be a simple mean of the first len values, not a recursion started from a single change. And the smoothing weight is 1 ÷ len, which is Wilder’s average, not 2 ÷ (len + 1), which is a conventional exponential average and will produce values that are close enough to look right and wrong everywhere.

Test vectors

The first eight outputs for the series charted above, with a length of 8 and a momentum of 3, rounded to two decimals. The first value lands on bar 11, that is mom + len bars in, counting from one, and every value before it does not exist rather than being zero.

Length 8, momentum 3: expected output
BarCloseRMI
1155.1100.00
1256.0100.00
1356.7100.00
1456.1100.00
1557.4100.00
1658.0100.00
1757.3100.00
1856.188.74

Two checks are worth running before trusting a port against real data. Set the momentum to 1 and compare the output against a known-good RSI over the same closes: the two must agree to the last decimal, because with that setting they are the same formula. Then feed a strictly rising straight line and confirm the result is 100 rather than an error, that is the branch where the average down is zero.

Choosing the two parameters

The length governs how much history each reading aggregates; the momentum governs what counts as an up bar in the first place. They are not interchangeable, and increasing one does not compensate for decreasing the other.

What each parameter does
ChangeEffect on the line
Longer lengthEach reading aggregates more history; the line moves less per bar and holds its level longer. Same behaviour as lengthening RSI.
Shorter lengthMore movement per bar and more crossings of any threshold, most of which reverse immediately.
Longer momentumPullbacks shorter than the momentum stop being counted as down bars at all; the line parks in the upper or lower half through a trend.
Momentum of 1The indicator becomes RSI exactly. Useful as a test, pointless as a setting.
Momentum near the swing lengthThe most useful region and the most instrument-specific: pauses you intend to sit through disappear, turns you care about still register.

A defensible way to set the momentum is to measure something first. Count the length in bars of the pullbacks you have actually held through on the instrument in question, take the typical value, and use it. That produces a number you can justify to yourself afterwards, which is the property no grid search can give you.

What volume adds

RMI is computed from closing prices and nothing else, so it cannot distinguish between a move made on heavy participation and an identical move made in a thin book. The distinction is not academic: the same 70 reading means something quite different when the advance behind it came on expanding volume and confirming breadth than when it came on the quietest three sessions of the month.

The practical habit is to read the oscillator for the shape of the momentum and read volume for whether anyone was there. A divergence that develops while volume is also thinning describes an advance running out of participants. The same divergence on rising volume describes disagreement, which resolves less predictably. Neither is a signal, and the pair is worth more than either alone.

Where it misleads

Known failure modes
SituationWhat goes wrong
RSI thresholds reusedA longer momentum makes extremes easier to reach and hold; 70 and 30 are not equivalent to their RSI counterparts.
Strong trendThe line parks at an extreme, exactly as RSI does, and crossings generate counter-trend losses.
Momentum longer than the swingPullbacks stop registering at all, the indicator is smoothed by construction, not by choice.
Short historyWilder smoothing carries the whole series forward; readings depend on where the data starts until it converges.
Unadjusted pricesA split creates one enormous change against the close n bars back, distorting both averages for the whole smoothing window.

Frequently asked questions

How is RMI different from RSI?

One substitution. RSI measures each bar’s change against the bar immediately before it; RMI measures it against the close n bars before, where n is the momentum parameter. Everything downstream — Wilder smoothing of the up and down averages, the relative-strength ratio, the 0–100 conversion — is identical. With the momentum parameter set to 1, RMI and RSI are the same indicator, which is the cleanest way to verify an implementation.

What does the momentum parameter actually change?

It changes what counts as an up bar. With momentum 5, a bar is "up" if the close is above the close five bars ago, even if today fell, so short pullbacks inside a trend stop registering as down moves at all. The practical effect is a line that stays in the upper or lower half of its range much longer during a trend, with fewer swings through the middle. Larger momentum values produce a smoother, more decisive-looking oscillator that is also slower to acknowledge a real turn.

What settings are standard?

Roger Altman introduced the indicator in Technical Analysis of Stocks & Commodities in 1993 with a length of 20 and a momentum of 5. Those remain the common defaults. There is no reason to treat them as optimal, but changing them for a reason you can state is different from trying values until a signal appears, and the second is a curve fit.

Do the 70 and 30 lines mean the same as on RSI?

Not quite. Because a longer momentum parameter suppresses counter-trend bars, RMI reaches and holds extremes more readily than RSI on the same data. Practitioners using momentum 5 often widen the bands to 80 and 20 for that reason. The levels are conventions in both cases; the important part is that a threshold quoted for RSI is not automatically valid here.

How many bars of history does it need before the values are trustworthy?

At minimum length plus momentum bars to produce a first value, and considerably more before that value stops depending on where the data begins. Wilder smoothing is a recursive average with no forgetting factor, so the seed, a simple mean of the first block, is carried forward permanently with a decaying weight. As a rule of thumb, discard three to five times the length after the seed. With length 20 and momentum 5 that means feeding at least 125 bars and reading none of the first 80.

Should the first value be a simple average or a Wilder step?

A simple average of the first n up-changes and down-changes, then Wilder steps from there. This is the convention Wilder specified for RSI in 1978 and it is what almost every library implements. It matters because the alternative, starting the recursion from the first single change, produces visibly different values for dozens of bars, and it is a common source of "my numbers do not match" reports against otherwise correct code.

What happens when the average down is zero?

The ratio is undefined and the indicator is defined as 100 by convention. In practice this occurs only in a synthetic series or after a long unbroken run, because Wilder smoothing keeps a decaying trace of any past down move for a very long time. The mirror case, an average up of zero, yields 0 by the same formula and needs no special casing. An implementation that returns NaN here will fail on a straight-line test series, which is the first test most people write.

Can it be computed on values other than the close?

Yes, and nothing in the formula objects, but the interpretation changes. Using the typical price or a median of high and low reduces the influence of one erratic close and is defensible. Using intraday highs makes the up series systematically larger than the down series and biases the whole oscillator upward. The arithmetic still runs, and the output no longer means what the bands were chosen for.

Is RMI valid on non-equity instruments?

The calculation is indifferent to what produced the price series, so it runs on futures, currencies and crypto without modification. Two cautions apply. Instruments that trade continuously have no meaningful daily close, so the choice of session boundary silently determines the input. And on instruments prone to sustained one-directional moves, the parking behaviour described above is more pronounced, which makes the divergence reading more important and the threshold reading less so.

How should it be adjusted for splits and dividends?

Always compute on an adjusted series. Because the change is taken against the close n bars back, an unadjusted two-for-one split does not merely put one bad value in the series. It puts n consecutive enormous negative changes into the down series, and Wilder smoothing then carries the distortion forward for many multiples of the length. A single unadjusted corporate action can make months of output meaningless.

Does a longer momentum parameter add lag?

It adds a specific kind of lag rather than general sluggishness. The line responds to today’s close immediately (that has not changed), but it responds to the difference against a close further back, so a genuine turn has to persist for several bars before the sign of the change flips. Reversals are therefore acknowledged late while the reaction to any single bar is unchanged. Calling this smoothing is loose but not misleading.

Can the two parameters be optimised on historical data?

They can be, and the results should be distrusted in proportion to how good they look. There are only two parameters and a modest sensible range for each, so a grid search over a few years of one instrument will always find a pair that looks excellent, and almost none of that edge survives out of sample. The defensible version of tuning is to choose the momentum from the length of the pullbacks you are willing to sit through, then leave both alone.

How does RMI compare with a stochastic oscillator?

Both are bounded 0–100 and both are read for extremes and divergence, but they measure different things. A stochastic locates the current close within the high-low range of the last n bars, a position measure. RMI aggregates the sizes of up and down changes over its length, a magnitude measure. A stochastic can sit at 100 on a tiny range; RMI cannot reach an extreme without real net movement behind it.

Why does my library disagree with my spreadsheet?

In order of likelihood: a different seed for the first smoothed value, a different momentum default, an off-by-one in the lookback (comparing against close[i − n] rather than close[i − n + 1]), or averaging with an exponential constant of 2/(n+1) instead of Wilder’s 1/n. Set the momentum to 1 and compare against a known-good RSI to isolate the first and last of those; if that matches, the fault is in the lookback index.

Is it worth using instead of RSI at all?

It is worth using when the specific thing you object to about RSI is that it dips through the middle of its range on every two-day pause in a trend you are trying to hold. RMI addresses precisely that and nothing else. If what you want is a faster or a less noisy oscillator in general, the momentum parameter is not the lever for it, and reaching for a different indicator is more honest than tuning this one until it behaves like one.