Skip to content
Open RaamTrade

ForceIndex — Force Index

Elder’s measure of the force behind a move: price change times volume, smoothed. It combines the three things that make a move convincing — direction, size, and participation — into one number.

Signature

ForceIndex(period, on=<source>)
Argument Type Required Notes
period int Param or literal Yes EMA smoothing. Default 13 (Elder’s); 2 for the short-term form. Bounds 1–400.
on= symbol No Source symbol. Defaults to the trade symbol. Reads close and volume.

Formula

$$ \text{Force} = \text{EMA}\big((C_t - C_{t-1}),V_t,\ n\big) $$

Warmup

period bars of EMA convergence; starts at 0.

Reading the value

fi.value
fi.crossed_above(0)

Example

class ForceEntry(Strategy):
"""Elder's setup: buy a short-term force dip inside a longer uptrend."""
trade = Symbol()
sizing = FixedCapital()
def execute(self):
short_force = ForceIndex(2, on=self.trade)
sma = SMA(50, on=self.trade)
if short_force.value < 0 and self.trade.close > sma.value and self.trade.is_flat:
self.buy(self.trade, reason="Force dip in uptrend")
if short_force.value > 0 and self.trade.close < sma.value and self.trade.is_long:
self.sell(self.trade, self.trade.position, reason="Trend lost")

Notes

  • Alexander Elder, Trading for a Living (1993). Elder uses 13 for the trend read and 2 for entries.
  • In price × volume units, so the level is instrument-specific — the sign and divergences are the signal.
  • The recursion seeds from the first bar rather than from a warm-up window, so early values are not comparable with pandas_ta’s efi(13), which seeds from an average of the first n; measured on a 300-bar tape the two agree to 1e-6 from bar 90 onward.