The original taxonomy was four classical families plus a statistics group, with the F1-F12 expansion slotted in as sub-categories. This regroups the whole 71-indicator catalogue into eight top-level families, each with at least five members: Moving Averages (12), Momentum Oscillators (13), Trend & Directional (9), Price Oscillators (5), Volatility & Bands (12), Trailing Stops (5), Volume (9), Price Statistics (7). - Wiki: docs/wiki/indicators/ reorganised into eight family folders; all 71 indicator pages moved with `git mv`. Every internal cross-link is normalised to `../<family>/Indicator-X.md`, each page's `Family` field is set to its new family, and two pre-existing `../Indicator-Chaining.md` links (should have been `../../`) are corrected. A link check confirms every relative wiki link resolves. - Indicators-Overview.md fully rewritten around the eight families; Home.md indicator reference and the README family table follow suit. - Warmup-Periods.md gains the eight F13 indicators; CHANGELOG records the 46-indicator expansion (25 -> 71) and the eight-family taxonomy. - Tests: Node indicators.test.js and Python test_new_indicators.py cover all eight new indicators (Node 91/91, Python 117/117 green). cargo fmt + clippy (core/wickra/data/wasm/node) clean; 508 core tests, 25 data tests and 74 doctests green.
5.4 KiB
MassIndex
Mass Index — Donald Dorsey's range-expansion indicator: it watches the high–low range widen and contract to anticipate reversals.
Quick reference
| Field | Value |
|---|---|
| Family | Trend & Directional |
| Input type | Candle (uses high, low) |
| Output type | f64 |
| Output range | > 0, oscillates around sum_period |
| Default parameters | (ema_period = 9, sum_period = 25) (Python) |
| Warmup period | 2·ema_period + sum_period − 2 |
| Interpretation | A rise above 27 then fall below 26.5 flags a reversal. |
Formula
range_t = high_t − low_t
single_t = EMA(range, ema_period)_t
double_t = EMA(single, ema_period)_t
ratio_t = single_t / double_t
MassIndex = Σ ratio over sum_period
The Mass Index ignores direction entirely — it tracks volatility shape.
When the high–low range widens, the single EMA pulls ahead of the double
EMA, the ratio climbs above 1, and the windowed sum rises. Dorsey's
"reversal bulge" is the classic pattern: the Mass Index rising above 27
and then falling back below 26.5 warns that a range expansion is about
to resolve — often into a trend reversal.
Parameters
| Name | Type | Default | Valid range | Description |
|---|---|---|---|---|
ema_period |
usize |
9 (Python) |
>= 1 |
Period of both EMAs in the cascade. 0 errors with Error::PeriodZero. |
sum_period |
usize |
25 (Python) |
>= 1 |
Length of the summation window. |
The Python binding defaults the pair to (9, 25). The periods property
returns (ema_period, sum_period).
Inputs / Outputs
From crates/wickra-core/src/indicators/mass_index.rs:
impl Indicator for MassIndex {
type Input = Candle;
type Output = f64;
// update(&mut self, input: Candle) -> Option<f64>
}
MassIndex is a candle-input indicator: it reads high and low. In
Python the streaming update accepts a 6-tuple or a dict; the batch
helper takes high and low numpy arrays. Node and WASM expose
update(high, low) and batch(high, low).
Warmup
warmup_period() == 2·ema_period + sum_period − 2. The first EMA seeds at
input ema_period; the second EMA, stacked on it, seeds at
2·ema_period − 1; the summation window then needs sum_period ratios.
For the default (9, 25) that is 41 bars.
Edge cases
- Constant range. When every bar has the same high–low range, both
EMAs converge to the same value, every ratio is
1, and the Mass Index equalssum_period(constant_range_sums_to_sum_periodpins this). - Zero-range market. A flat market (
high == low) drives both EMAs to0; the0 / 0is guarded with the neutral ratio1, so the Mass Index again equalssum_period(zero_range_market_sums_to_sum_periodpins this). - Candle validation.
Candle::newrejects invalid bars upstream. - Reset.
mi.reset()clears both EMAs, the window and the sum.
Examples
Rust
use wickra::{BatchExt, Candle, Indicator, MassIndex};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut mi = MassIndex::new(3, 4)?;
// Constant high-low range of 2.0; the Mass Index settles at sum_period.
let candles: Vec<Candle> = (0..40)
.map(|i| {
let mid = 100.0 + f64::from(i);
Candle::new(mid, mid + 1.0, mid - 1.0, mid, 1.0, i64::from(i)).unwrap()
})
.collect();
let out = mi.batch(&candles);
println!("warmup_period = {}", mi.warmup_period());
println!("last = {:?}", out.last().unwrap());
Ok(())
}
Output:
warmup_period = 8
last = Some(4.0)
A constant range makes every ratio 1, so the sum equals sum_period
(4). This matches the constant_range_sums_to_sum_period test in
crates/wickra-core/src/indicators/mass_index.rs.
Python
import numpy as np
import wickra as ta
mi = ta.MassIndex() # (ema_period=9, sum_period=25)
mid = np.arange(100.0, 160.0)
high = mid + 1.0
low = mid - 1.0
print(mi.batch(high, low)[-1]) # constant range -> 25
Output:
25.0
Node
const ta = require('wickra');
const mi = new ta.MassIndex(9, 25);
const mid = Array.from({ length: 60 }, (_, i) => 100 + i);
const high = mid.map((m) => m + 1);
const low = mid.map((m) => m - 1);
console.log(mi.batch(high, low).at(-1)); // 25
Interpretation
MassIndex is a reversal-warning tool, not a direction tool — it never
tells you which way price will go, only that a turn is likely. The textbook
use is the "reversal bulge" on the default (9, 25) settings: watch for
the index to push above 27, then act when it drops back under 26.5,
using a directional indicator (a moving average, ADX) to pick the side.
Common pitfalls
- Expecting a direction. The Mass Index is direction-blind; always pair it with a trend indicator.
- Feeding it scalar prices. It needs
high/low; it takes aCandle, not anf64.
References
Donald Dorsey, "The Mass Index", Technical Analysis of Stocks &
Commodities (1992). The double-EMA-of-range construction and the (9, 25) defaults follow Dorsey's original.
See also
- Indicator-Atr.md — directional-free volatility in price units.
- Indicator-BollingerBands.md — another range-expansion lens.
- Indicators-Overview.md — the full taxonomy.