9d822d26aa
RollingVwap is a separate public type (pub struct RollingVwap in vwap.rs) and Indicator-Vwap.md already documents it in a full "## RollingVwap (finite window)" section, but it was not directly reachable: the Overview row added in E12 pointed at a #rollingvwap anchor that does not exist. Fix the Overview link to the real #rollingvwap-finite-window anchor and add a jump-to note at the top of Indicator-Vwap.md so both public types are reachable in one click.
204 lines
14 KiB
Markdown
204 lines
14 KiB
Markdown
# Indicators Overview
|
||
|
||
Wickra ships 25 indicators, organised in source under the four classical
|
||
families — trend, momentum, volatility, volume — that map directly to the
|
||
directory structure of `crates/wickra-core/src/indicators/`. The same family
|
||
labels are used here, plus a second-level grouping that reflects how the
|
||
indicators actually behave (which output range they live in, what data they
|
||
need, what question they answer).
|
||
|
||
Every indicator is an O(1) state machine that consumes one input at a time
|
||
and produces either `Option<f64>` (Rust), `float | None` (Python), or
|
||
`number | null` (Node). Inputs are either a `f64` close price or an OHLCV
|
||
`Candle` (Rust) / dict-or-tuple (Python) / column arrays (Node). The full
|
||
trait surface and warmup-period semantics are covered in
|
||
[Quickstart: Rust](Quickstart-Rust.md) and [Warmup Periods](Warmup-Periods.md).
|
||
|
||
The "Output range" column below is the value bounds an indicator emits once
|
||
warm. "unbounded" means it tracks the price scale of the input. The
|
||
"Warmup" column quotes `warmup_period()` as the indicator reports it; this
|
||
is the **exact** first-emission index for every indicator — the first
|
||
non-`None` output lands on input `warmup_period()` (index
|
||
`warmup_period() - 1`).
|
||
|
||
## Trend
|
||
|
||
Trend indicators smooth the price series to surface direction. They are
|
||
all single-input, single-output (`f64 → f64`).
|
||
|
||
### Simple averages
|
||
|
||
Pure linear weighting. Mostly used as fast baselines or as comparison
|
||
benchmarks against fancier averages.
|
||
|
||
| Indicator | One-liner | Input | Output | Range | Defaults | Warmup | Deep dive |
|
||
|-----------|-----------|-------|--------|-------|----------|--------|-----------|
|
||
| `Sma` | Equal-weighted rolling mean over `period` closes. | `f64` | `f64` | unbounded (price scale) | `period` (no default in core; Python defaults vary by binding) | `period` | [Indicator-Sma.md](indicators/trend/Indicator-Sma.md) |
|
||
| `Wma` | Linear weights `1, 2, …, period` so the newest bar matters most. | `f64` | `f64` | unbounded (price scale) | `period` | `period` | [Indicator-Wma.md](indicators/trend/Indicator-Wma.md) |
|
||
|
||
### Exponential family
|
||
|
||
Recursive smoothing with one or more chained EMAs. Lag reduction grows as
|
||
you stack more EMAs, but so does responsiveness to noise.
|
||
|
||
| Indicator | One-liner | Input | Output | Range | Defaults | Warmup | Deep dive |
|
||
|-----------|-----------|-------|--------|-------|----------|--------|-----------|
|
||
| `Ema` | EMA with `α = 2 / (period + 1)`, seeded from the SMA of the first `period` inputs. | `f64` | `f64` | unbounded (price scale) | `period` | `period` | [Indicator-Ema.md](indicators/trend/Indicator-Ema.md) |
|
||
| `Dema` | Mulloy's `2·EMA − EMA(EMA)`; removes first-order EMA lag. | `f64` | `f64` | unbounded (price scale) | `period` | `2·period − 1` | [Indicator-Dema.md](indicators/trend/Indicator-Dema.md) |
|
||
| `Tema` | Mulloy's `3·EMA − 3·EMA(EMA) + EMA(EMA(EMA))`; removes more lag than DEMA. | `f64` | `f64` | unbounded (price scale) | `period` | `3·period − 2` | [Indicator-Tema.md](indicators/trend/Indicator-Tema.md) |
|
||
|
||
`Trix` is also built from a triple-smoothed EMA, but it is a *momentum
|
||
oscillator* — it emits the rate of change of that EMA, not a price-scale
|
||
trend line — so it is listed under [Momentum](#momentum), matching the
|
||
`indicators/momentum/` source layout.
|
||
|
||
### Adaptive & hybrid
|
||
|
||
These two adjust their effective smoothing on the fly. They are the
|
||
"smart" trend filters; both also live in Trend by directory placement.
|
||
|
||
| Indicator | One-liner | Input | Output | Range | Defaults | Warmup | Deep dive |
|
||
|-----------|-----------|-------|--------|-------|----------|--------|-----------|
|
||
| `Hma` | Hull's `WMA(2·WMA(n/2) − WMA(n), √n)`; near-zero lag with a built-in noise filter. | `f64` | `f64` | unbounded (price scale) | `period` | `period + round(√period) − 1` (see notes) | [Indicator-Hma.md](indicators/trend/Indicator-Hma.md) |
|
||
| `Kama` | Kaufman's adaptive average: efficiency ratio picks an α between a fast and slow EMA per bar. | `f64` | `f64` | unbounded (price scale) | `(er_period=10, fast=2, slow=30)` | `er_period + 1` (see notes) | [Indicator-Kama.md](indicators/trend/Indicator-Kama.md) |
|
||
|
||
## Momentum
|
||
|
||
Momentum indicators measure the *rate* of price change, not the level.
|
||
Several are bounded by construction (0–100 oscillators); others are
|
||
unbounded; one (`Adx`) is directional and bundles three values.
|
||
|
||
### Bounded oscillators (0 – 100)
|
||
|
||
These all share the "overbought above 70/80, oversold below 30/20"
|
||
mental model, though the exact thresholds differ in the literature.
|
||
|
||
| Indicator | One-liner | Input | Output | Range | Defaults | Warmup | Deep dive |
|
||
|--------------|-----------|-------|--------|-------|----------|--------|-----------|
|
||
| `Rsi` | Wilder's RSI; smoothed `gain / (gain + loss) × 100`. | `f64` | `f64` | `[0, 100]` | `period = 14` (Python) | `period + 1` | [Indicator-Rsi.md](indicators/momentum/Indicator-Rsi.md) |
|
||
| `Stochastic` | `%K = (close − low_n)/(high_n − low_n) × 100`, smoothed into `%D`. | `Candle` | `(k, d)` | each in `[0, 100]` | `(k_period=14, d_period=3)` (Python) | `k_period + d_period − 1` | [Indicator-Stochastic.md](indicators/momentum/Indicator-Stochastic.md) |
|
||
| `Mfi` | "Volume-weighted RSI": Wilder smoothing of money-flow ratios. | `Candle` | `f64` | `[0, 100]` | `period = 14` (Python) | `period` | [Indicator-Mfi.md](indicators/momentum/Indicator-Mfi.md) |
|
||
| `Aroon` | Bars-since-high and bars-since-low scaled to `[0, 100]`. | `Candle` | `(up, down)` | each in `[0, 100]` | `period = 14` (Python) | `period + 1` | [Indicator-Aroon.md](indicators/momentum/Indicator-Aroon.md) |
|
||
|
||
### Unbounded oscillators
|
||
|
||
Centered on zero or driven by raw price differences; no fixed cap.
|
||
|
||
| Indicator | One-liner | Input | Output | Range | Defaults | Warmup | Deep dive |
|
||
|---------------------|-----------|-------|--------|-------|----------|--------|-----------|
|
||
| `MacdIndicator` | `EMA(fast) − EMA(slow)` plus a signal-line EMA and the difference histogram. | `f64` | `(macd, signal, histogram)` | unbounded around zero | `(fast=12, slow=26, signal=9)` (Python) | `slow + signal − 1` | [Indicator-MacdIndicator.md](indicators/momentum/Indicator-MacdIndicator.md) |
|
||
| `Cci` | `(typical − SMA(typical)) / (0.015 · mean_dev)`; unbounded but typically `±100`. | `Candle` | `f64` | unbounded (typically `±100` to `±200`) | `period = 20` (Python) | `period` | [Indicator-Cci.md](indicators/momentum/Indicator-Cci.md) |
|
||
| `Roc` | `(price − price_n) / price_n × 100`; raw percentage change over `period` bars. | `f64` | `f64` | unbounded around zero | `period` | `period + 1` | [Indicator-Roc.md](indicators/momentum/Indicator-Roc.md) |
|
||
| `AwesomeOscillator` | `SMA(median, fast) − SMA(median, slow)`; Bill Williams' zero-line crossover oscillator. | `Candle` | `f64` | unbounded around zero | `(fast=5, slow=34)` (Python) | `slow_period` | [Indicator-AwesomeOscillator.md](indicators/momentum/Indicator-AwesomeOscillator.md) |
|
||
| `WilliamsR` | `−100 × (high_n − close) / (high_n − low_n)`; same family as Stochastic but inverted to `[−100, 0]`. | `Candle` | `f64` | `[−100, 0]` | `period = 14` (Python) | `period` | [Indicator-WilliamsR.md](indicators/momentum/Indicator-WilliamsR.md) |
|
||
| `Trix` | `(EMA(EMA(EMA(price))).pct_change × 10000)`; oscillator built from a triple-smoothed EMA. | `f64` | `f64` | unbounded around zero | `period = 15` (Python) | `3·period − 1` | [Indicator-Trix.md](indicators/momentum/Indicator-Trix.md) |
|
||
|
||
### Directional
|
||
|
||
| Indicator | One-liner | Input | Output | Range | Defaults | Warmup | Deep dive |
|
||
|-----------|-----------|-------|--------|-------|----------|--------|-----------|
|
||
| `Adx` | Wilder's directional system: `+DI`, `−DI` (each `[0, 100]`) and `ADX` trend-strength index. | `Candle` | `(plus_di, minus_di, adx)` | each in `[0, 100]` | `period = 14` (Python) | `2·period` | [Indicator-Adx.md](indicators/momentum/Indicator-Adx.md) |
|
||
|
||
## Volatility
|
||
|
||
Volatility indicators sit in two functional groups: those that draw an
|
||
envelope around price, and those that report a scalar dispersion/range.
|
||
PSAR is a special case — a trailing-stop tracker rather than a width
|
||
measure — that lives in the volatility module by source convention.
|
||
|
||
### Envelopes
|
||
|
||
| Indicator | One-liner | Input | Output | Range | Defaults | Warmup | Deep dive |
|
||
|-------------------|-----------|-------|--------|-------|----------|--------|-----------|
|
||
| `BollingerBands` | SMA middle band with `±multiplier × population_stddev` upper/lower bands. | `f64` | `(upper, middle, lower, stddev)` | unbounded (price scale) | `(period=20, multiplier=2.0)` (Python) | `period` | [Indicator-BollingerBands.md](indicators/volatility/Indicator-BollingerBands.md) |
|
||
| `Keltner` | EMA middle band with `±multiplier × ATR` upper/lower bands. | `Candle` | `(upper, middle, lower)` | unbounded (price scale) | `(ema_period=20, atr_period=10, multiplier=2.0)` (Python) | `max(ema_period, atr_period)` | [Indicator-Keltner.md](indicators/volatility/Indicator-Keltner.md) |
|
||
| `Donchian` | Highest high and lowest low over `period` bars; middle = mean of the two. | `Candle` | `(upper, middle, lower)` | unbounded (price scale) | `period = 20` (Python) | `period` | [Indicator-Donchian.md](indicators/volatility/Indicator-Donchian.md) |
|
||
|
||
### Range-average
|
||
|
||
| Indicator | One-liner | Input | Output | Range | Defaults | Warmup | Deep dive |
|
||
|-----------|-----------|-------|--------|-------|----------|--------|-----------|
|
||
| `Atr` | Wilder-smoothed True Range; per-bar absolute volatility. | `Candle` | `f64` | `[0, ∞)` (price scale) | `period = 14` (Python) | `period` | [Indicator-Atr.md](indicators/volatility/Indicator-Atr.md) |
|
||
|
||
### Trailing stop
|
||
|
||
| Indicator | One-liner | Input | Output | Range | Defaults | Warmup | Deep dive |
|
||
|-----------|-----------|-------|--------|-------|----------|--------|-----------|
|
||
| `Psar` | Wilder's Parabolic Stop-and-Reverse; per-bar stop level that flips sides on price crossing. | `Candle` | `f64` | unbounded (price scale) | `(af_start=0.02, af_step=0.02, af_max=0.20)` (Python) | `2` | [Indicator-Psar.md](indicators/volatility/Indicator-Psar.md) |
|
||
|
||
## Volume
|
||
|
||
Volume indicators all take `Candle` input because they need `close` and
|
||
`volume` together (some also need `high`/`low`).
|
||
|
||
### Cumulative
|
||
|
||
| Indicator | One-liner | Input | Output | Range | Defaults | Warmup | Deep dive |
|
||
|---------------|-----------|-------|--------|-------|----------|--------|-----------|
|
||
| `Obv` | On-Balance Volume: cumulative signed volume driven by close-vs-prior-close sign. | `Candle` | `f64` | unbounded (drifts with cumulative volume) | (no parameters) | `1` | [Indicator-Obv.md](indicators/volume/Indicator-Obv.md) |
|
||
| `Vwap` | Cumulative volume-weighted average price from the start of the stream (intraday reset is your responsibility). | `Candle` | `f64` | unbounded (price scale) | (no parameters) | `1` | [Indicator-Vwap.md](indicators/volume/Indicator-Vwap.md) |
|
||
|
||
### Rolling
|
||
|
||
| Indicator | One-liner | Input | Output | Range | Defaults | Warmup | Deep dive |
|
||
|---------------|-----------|-------|--------|-------|----------|--------|-----------|
|
||
| `RollingVwap` | VWAP over a sliding window instead of since-start; useful for session-independent VWAP. | `Candle` | `f64` | unbounded (price scale) | `period` | `period` | [Indicator-Vwap.md → RollingVwap](indicators/volume/Indicator-Vwap.md#rollingvwap-finite-window) |
|
||
|
||
## Pick the right indicator for…
|
||
|
||
A short cheat-sheet of "I want X, which indicator?" answers, grounded in
|
||
what each indicator actually computes.
|
||
|
||
- **Fast trend filter, minimal lag, single line.** `Hma` for smoothness +
|
||
responsiveness, `Tema` for further lag reduction at the cost of more
|
||
noise. If you want adaptiveness instead of fixed lag, `Kama`.
|
||
- **Slow trend filter, smooth as glass.** `Sma` is the simplest; `Ema`
|
||
responds slightly faster with the same smoothness budget. For long
|
||
trend filters either is appropriate; the difference is mostly aesthetic.
|
||
- **Trend-following crossovers.** Two-line crossovers (`Ema(fast)` vs
|
||
`Ema(slow)`, or any of the trend pairs) are the textbook entry signal;
|
||
`MacdIndicator` packages the same idea with a signal line and histogram.
|
||
- **Trend strength (is there a trend at all?).** `Adx` is the canonical
|
||
answer: `adx > 25` is "trending", `adx < 20` is "ranging". `Aroon` is
|
||
a softer alternative when you want directional confirmation.
|
||
- **Overbought / oversold reversal candidate.** `Rsi` is the default;
|
||
`Stochastic` for faster signals; `WilliamsR` for the same logic with an
|
||
inverted scale; `Mfi` if you have volume and want a volume-aware RSI.
|
||
- **Volatility expansion / contraction.** `BollingerBands` width
|
||
(`upper − lower`) for relative volatility; `Atr` for absolute per-bar
|
||
volatility in price units; `Keltner` to compare price against an
|
||
ATR-scaled envelope.
|
||
- **Breakout level.** `Donchian` upper/lower bands are the textbook
|
||
Turtle-style breakout trigger.
|
||
- **Trailing stop.** `Psar` gives you a per-bar stop level that flips
|
||
sides as the trend reverses. `Atr · k` (compute `Atr` yourself, multiply
|
||
by your preferred `k`) is the common alternative.
|
||
- **Volume confirmation.** `Obv` is the simplest; `Mfi` adds price into
|
||
the equation; `Vwap` / `RollingVwap` give you the volume-weighted
|
||
reference price.
|
||
- **Bill Williams setups.** `AwesomeOscillator` for the zero-line cross /
|
||
twin-peaks pattern from his suite.
|
||
- **Rate-of-change scalar.** `Roc` is the unsmoothed percentage change;
|
||
`Trix` is the same idea but on a triple-smoothed EMA.
|
||
|
||
## Source-of-truth files
|
||
|
||
Every claim above can be checked against the source in
|
||
[`crates/wickra-core/src/indicators/`](https://github.com/kingchenc/wickra/tree/main/crates/wickra-core/src/indicators)
|
||
— one file per indicator. The Rust unit tests inside each module are the
|
||
ground truth for sample values. Python defaults (the `period = 14` etc. in
|
||
tables above) come from the `#[pyo3(signature = …)]` attributes in
|
||
[`bindings/python/src/lib.rs`](https://github.com/kingchenc/wickra/blob/main/bindings/python/src/lib.rs);
|
||
indicators not listed with a Python default require an explicit `period`
|
||
argument.
|
||
|
||
## See also
|
||
|
||
- [Warmup Periods](Warmup-Periods.md) — full verified table of every
|
||
indicator's `warmup_period()`.
|
||
- [Indicator Chaining](Indicator-Chaining.md) — combining indicators with
|
||
`Chain` and the stacked-warmup rule.
|
||
- [Quickstart: Rust](Quickstart-Rust.md), [Quickstart: Python](Quickstart-Python.md),
|
||
[Quickstart: Node](Quickstart-Node.md) — language-specific API surfaces.
|
||
- Source: <https://github.com/kingchenc/wickra>
|