Skip to content
Open RaamTrade

RangeExpansionIndex — Range Expansion Index

DeMark’s REI: how much recent highs and lows have expanded, relative to the size of that movement, on a −100 to +100 scale. The gating condition means the index only accumulates when the recent bars are in contact with the older ones — it deliberately ignores runaway moves.

Signature

RangeExpansionIndex(period, on=<source>)
Argument Type Required Notes
period int Param or literal Yes Summation window. Default 8, bounds 1–200.
on= symbol No Source symbol. Defaults to the trade symbol. Reads high and low.

Formula

For each bar, the two-bar-ago high and low changes are summed and gated by DeMark’s overlap condition against bars 5 and 6; the sum is normalised by the absolute changes:

$$ \text{REI} = 100,\frac{\sum_n \text{gate}\cdot[(H_t - H_{t-2}) + (L_t - L_{t-2})]}{\sum_n |H_t - H_{t-2}| + |L_t - L_{t-2}|} $$

Warmup

period + 8 bars — the gate reaches back six bars beyond the two-bar comparison.

Reading the value

rei.value
rei < -45
rei.crossed_above(-45)

Example

class ReiExhaustion(Strategy):
"""DeMark's read: a move out of oversold after the index has been below -45."""
trade = Symbol()
sizing = FixedCapital()
def execute(self):
rei = RangeExpansionIndex(8, on=self.trade)
if rei.crossed_above(-45) and self.trade.is_flat:
self.buy(self.trade, reason=f"REI recovering {rei.value:.0f}")
if rei.value > 45 and self.trade.is_long:
self.sell(self.trade, self.trade.position, reason="REI overbought")

Notes

  • Tom DeMark, The New Science of Technical Analysis (1994). The ±45 thresholds are his.
  • Proven by an assert-via-trade run on SPY daily (stayed inside ±100 on every bar of a 140-bar run, with the gate firing; zero alarm trades).
  • The gating condition is the whole indicator — a version without it is just a range oscillator.