- Measures where the close sits relative to the midpoint of the recent range, not the boundary. Zero means neutral; positive means above midpoint; negative means below.
- Two methods: Blau (default) smooths the ratio; Chande/Kroll smooths numerator and denominator separately before computing the ratio.
- Double EMA smoothing with warmup compensation produces clean crossover signals with controlled lag.
- Unlike classic Stochastic ($[0, 100]$), SMI ranges $[-100, +100]$, centered on zero. Traditional Stochastic thresholds do not apply.
- Uses `MonotonicDeque` for O(1) amortized highest/lowest tracking and `Math.FusedMultiplyAdd` for EMA stages.
William Blau introduced the Stochastic Momentum Index in *Momentum, Direction, and Divergence* (1995) as an improvement over George Lane's classic Stochastic Oscillator. Blau's key insight: measuring distance from the range midpoint rather than from the low eliminates the asymmetric bias inherent in traditional stochastics. When price closes at the exact middle of its range, classic Stochastic reads 50—an arbitrary number that says nothing. SMI reads 0—neutral, centered, semantically honest.
Tushar Chande and Stanley Kroll proposed a variant in *The New Technical Trader* (1994) that smooths numerator and denominator separately before computing the ratio. This subtle difference in order of operations produces different behavior during volatile periods: Blau's method smooths the ratio directly, which compresses extreme values; Chande/Kroll preserves the ratio's sensitivity by smoothing its components independently.
QuanTAlib implements both methods via the `blau` parameter. The Blau method (default) suits trend-following; the Chande/Kroll method suits mean-reversion. Neither is universally better.
SMI measures the closing price's distance from the midpoint of the highest-high to lowest-low range, normalized by half that range, then double-smoothed with cascaded EMAs. The result is a zero-centered oscillator bounded by $[-100, +100]$.
The centering around zero gives SMI cleaner semantics than classic Stochastic. Positive values mean the close is above the range midpoint; negative values mean it is below. The magnitude indicates the strength of the displacement. Values beyond $\pm 40$ indicate extreme momentum; values near zero indicate no meaningful displacement.
The double EMA smoothing ($-12$ dB/octave rolloff) attenuates noise more aggressively than a single EMA of equivalent period, at the cost of additional group delay. This makes SMI better at filtering whipsaws than raw Stochastic while remaining responsive enough for momentum detection.
Two `MonotonicDeque` instances track the sliding highest-high and lowest-low over `kPeriod` bars. Circular buffers (`_hBuf`, `_lBuf`) store raw H/L values for deque rebuild on bar correction.
**Blau path**: Computes `raw = 100 * (close - mid) / rh`, then applies two cascaded EMAs with the same alpha (kSmooth), followed by an EMA with dSmooth alpha for the signal line.
Each EMA stage uses exponential warmup compensators ($e_t = d \cdot e_{t-1}$, $c_t = 1/(1 - e_t)$) that correct initialization bias. The compensator converges to 1.0 as $e_t \to 0$, after which the hot path skips compensation for performance.
- **K/D crossover**: K crossing above D signals bullish momentum shift; K crossing below D signals bearish shift.
- **Zero-line crossover**: K crossing above zero confirms upward momentum; crossing below confirms downward.
- **Divergence**: Price makes new highs while K makes lower highs (bearish) or price makes new lows while K makes higher lows (bullish).
### Practical Notes
- **Blau** (default): Better for trend-following. Smoother output, fewer whipsaws. The ratio compression during high volatility acts as a natural dampener.
- **Chande/Kroll**: Better for mean-reversion. Preserves component oscillation sensitivity. More responsive during volatile reversals but noisier in trends.
2.**Ignoring the method parameter**: Blau and Chande/Kroll produce meaningfully different results. Switching methods mid-analysis invalidates comparisons.
3.**Zero range handling**: When $HH = LL$, `rangeHalf` is zero. The division guard returns $0$, but sustained zero readings may mask meaningful price action outside the deque window.
4.**Cascaded EMA warmup**: Three EMA stages each need convergence time. The first values after `IsHot` are less reliable than values after the full warmup period.
5.**Parameter interaction**: `kPeriod` controls reference range width; `kSmooth` controls noise filtering; `dSmooth` controls signal line lag. Increasing `kPeriod` without adjusting smoothing produces a wider reference range with insufficient filtering.
6.**Bar correction cost**: `isNew=false` triggers O(kPeriod) deque rebuild. Infrequent in normal streaming but visible with rapid corrections.
## FAQ
**Q: Should I use Blau or Chande/Kroll?**
A: Blau (default) for trend-following. Chande/Kroll for mean-reversion in volatile markets. Blau compresses extreme ratio values through smoothing; Chande/Kroll preserves component oscillation by smoothing numerator and denominator independently.
**Q: Why does SMI use ±40 thresholds instead of 20/80?**
A: Because SMI is centered on zero with range $[-100, +100]$. The ±40 thresholds correspond to approximately the same distance from neutral as 20/80 in classic Stochastic's $[0, 100]$ range.
**Q: How does SMI compare to Stochastic for crossover signals?**
A: SMI's zero-centered output produces cleaner crossovers because the neutral point is semantically meaningful (close equals range midpoint). Classic Stochastic's 50 level has no equivalent semantic clarity.