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.5 KiB
TRIX
Triple-EMA percent rate of change — applies three EMAs in sequence to smooth out short-term noise, then reports the one-bar percent change of the resulting series.
Quick reference
| Field | Value |
|---|---|
| Family | Trend & Directional |
| Input type | f64 (close) |
| Output type | f64 |
| Output range | unbounded (typically a few percent, centred on 0) |
| Default parameters | none — period is required in every binding |
| Warmup period | 3 · period − 1 (44 for period = 15) |
| Interpretation | zero-line crossings as trend-change cues; magnitude as momentum |
Formula
Let EMA_n(·) denote Wickra's EMA over n periods (seeded from the
simple mean of the first n inputs, then recursive with α = 2/(n+1)).
For each input close, build a triple-smoothed series:
TR_t = EMA_period( EMA_period( EMA_period( close ) ) )_t
Then TRIX is the one-bar percent rate of change of TR:
TRIX_t = 100 · (TR_t − TR_{t-1}) / TR_{t-1}
When TR_{t-1} == 0 exactly, the implementation returns 0.0 rather
than dividing by zero.
Parameters
| Name | Type | Default | Valid range | Description |
|---|---|---|---|---|
period |
usize |
required | >= 1 |
Period shared by all three EMAs. |
Trix::new(0) returns Error::PeriodZero (via the inner Ema::new).
The Python and Node bindings expose no default for period; you must
pass it explicitly.
Inputs / Outputs
From impl Indicator for Trix:
type Input = f64;
type Output = f64;
fn update(&mut self, input: f64) -> Option<f64>;
Python's TRIX.batch(prices) returns a 1-D float64 np.ndarray
(warmup → NaN). Node's TRIX.batch(prices) returns a flat
number[] (warmup → NaN). Both also expose streaming update(price).
Warmup
warmup_period() returns 3 · period − 1. Three stacked EMAs of the
same period seed at input 3 · period − 2; once TR exists, TRIX
itself needs one more input to form the TR_t − TR_{t-1} difference,
which lands at input 3 · period − 1. For period = 15 this is
3 · 15 − 1 = 44, verified above.
Edge cases
- Constant input. All three EMAs converge to the constant value, so
TR_t − TR_{t-1} == 0and TRIX returns0(testconstant_series_yields_zero_trix). TR_{t-1} == 0. The implementation returns0rather than producingNaN/±∞. This is theSome(_)branch withprev != 0.0-failed inTrix::update.- Reset.
reset()resets all three EMAs and clearsprev_tr.
Examples
Rust
use wickra::{BatchExt, Indicator, Trix};
let prices: Vec<f64> = (1..=50).map(|i| i as f64).collect();
let mut trix = Trix::new(15)?;
let out = trix.batch(&prices);
println!("row 43 = {}", out[43].unwrap());
println!("row 49 = {}", out[49].unwrap());
# Ok::<(), wickra::Error>(())
Verified output:
row 43 = 4.545454545454546
row 49 = 3.5714285714285716
(The series decays toward zero as a ramp gets longer because the percent change of an arithmetic ramp shrinks as the level grows.)
Python
import wickra as ta
trix = ta.TRIX(15)
print('warmup:', trix.warmup_period())
vals = []
for i in range(1, 51):
vals.append(trix.update(float(i)))
print('vals[43]:', vals[43])
print('vals[49]:', vals[49])
Verified output:
warmup: 44
vals[43]: 4.545454545454546
vals[49]: 3.5714285714285716
Node
const wickra = require('wickra');
const trix = new wickra.TRIX(15);
console.log('warmup:', trix.warmupPeriod());
const vals = [];
for (let i = 1; i <= 50; i++) vals.push(trix.update(i));
console.log('vals[43]:', vals[43]);
console.log('vals[49]:', vals[49]);
Verified output:
warmup: 44
vals[43]: 4.545454545454546
vals[49]: 3.5714285714285716
Interpretation
- Zero-line cross. TRIX crossing above zero suggests the triple-smoothed trend is turning up; crossing below, turning down. Because of the triple smoothing, these crosses are deliberately late and deliberately stable.
- Magnitude. A larger absolute TRIX value means the smoothed series is changing faster per bar. There is no canonical "overbought" band — TRIX is interpreted by its sign and slope, not by threshold.
- Compare to MACD. Both are EMA-based momentum oscillators on a zero-centred scale. MACD reacts faster (two EMAs, one diff); TRIX reacts slower (three EMAs, one rate of change), making it a cleaner long-horizon trend filter.
Common pitfalls
- Long warmup.
3 · period − 1is one of the largest warmups in the library (44 for the canonicalperiod = 15). Sizing your input buffer toperiodand expecting values immediately will hand youNone/NaNfor a full 44 bars. - Triple smoothing kills small wiggles. TRIX deliberately ignores short-term noise. Do not use it for entry-timing inside a fast oscillator strategy; use it as a long-term trend filter on top of a faster signal.
References
- Jack Hutson, "Good TRIX", Technical Analysis of Stocks & Commodities, July 1983 — the original publication popularising the triple-EMA rate-of-change oscillator.
See also
- Indicator: MacdIndicator — faster EMA-based momentum oscillator, useful as a confirmation against TRIX zero-line crosses.
- Indicator: Roc — the raw, one-stage rate of change TRIX is built on top of.
- Warmup Periods —
3 · period − 1entry.