SMIErgodic — SMI Ergodic
Blau’s ergodic oscillator: the True Strength Index construction, presented on its natural −1 to
+1 scale with the signal line as the primary read. Shorter defaults than TSI, so it turns
sooner and whipsaws more.
Signature
SMIErgodic(long_period, short_period, signal_period, on=<source>)| Argument | Type | Required | Notes |
|---|---|---|---|
long_period |
int Param or literal | Yes | First smoothing. Default 20, bounds 1–200. |
short_period |
int Param or literal | Yes | Second smoothing. Default 5, bounds 1–200. |
signal_period |
int Param or literal | Yes | EMA of the oscillator. Default 5, bounds 1–200. |
on= |
symbol, OHLCV field, or indicator | No | Source. Defaults to the trade symbol’s close. |
Formula
$$ \text{Ergodic} = \frac{\text{EMA}(\text{EMA}(\Delta C, r), s)}{\text{EMA}(\text{EMA}(|\Delta C|, r), s)} $$
Identical to TSI without the ×100.
Warmup
Converges over roughly 3 × long_period bars.
Reading the value
erg.ergodicerg.signalerg.ergodic > erg.signalMulti-value: cannot be chained onto or crossed.
Example
class ErgodicCross(Strategy): """Trade the ergodic/signal crossover.""" trade = Symbol() sizing = FixedCapital()
def execute(self): erg = SMIErgodic(20, 5, 5, on=self.trade) if erg.ergodic > erg.signal and self.trade.is_flat: self.buy(self.trade, reason="Ergodic above signal") if erg.ergodic < erg.signal and self.trade.is_long: self.sell(self.trade, self.trade.position, reason="Ergodic below signal")Notes
- William Blau, Momentum, Direction, and Divergence (1995).
- Proven by an assert-via-trade run on SPY daily (tracked the independent TSI replication within the expected band once warm; zero alarm trades).
- Multiply by 100 to compare directly with
TSI.