B5 volatility & bands batch (423 -> 429) (#189)
Adds six **Volatility & Bands** indicators (Part B5 of the expansion roadmap), 423 → 429. | Indicator | Input → Output | Summary | |-----------|----------------|---------| | `EwmaVolatility` | `f64` → `f64` | RiskMetrics exponentially-weighted volatility (λ decay) | | `Garch11` | `f64` → `f64` | GARCH(1,1) conditional volatility with a long-run-variance anchor | | `BipowerVariation` | `f64` → `f64` | jump-robust realized bipower variation (π/2 · Σ\|rₜ\|\|rₜ₋₁\|) | | `VolatilityRatio` | `Candle` → `f64` | Schwager's true range over the EMA of prior true ranges (>2 = wide-ranging day) | | `VolatilityCone` | `Candle` → `VolatilityConeOutput` | current realized volatility within its min/median/max envelope + percentile | | `VolatilityOfVolatility` | `f64` → `f64` | sample stddev of a rolling realized-volatility series | ### Notes - Two B5 roadmap items were dropped as duplicates/by-construction: `RealizedVolatility` already ships (v0.5.4); `Downside Semi-Deviation` is internal to Sortino. `Bipower Variation` confirmed distinct from `JumpIndicator` (a ±1 flag, not a variance measure). - `VolatilityRatio` implements the widely-charted EMA-of-true-range convention (denominator excludes the current bar so the 2.0 threshold means "twice typical"), distinct from the existing pairwise `variance_ratio`. - `Garch11` mean-reverts to `ω/(1−β)` on a flat series (does not decay to 0 like EWMA) — pinned by a dedicated test. ### Coverage / verification - Full core + Python/Node/WASM bindings, fuzz drivers (scalar + candle), registries, CHANGELOG, README + docs counter sync. - 100% unit-test coverage per indicator (every branch). - Green locally: `cargo clippy --workspace --all-targets --all-features -D warnings`, core lib (3479) + doc (387), node (504), python (830). Deep-dive docs for all six are staged for `wickra-docs` and pushed after release (gated).
This commit is contained in:
@@ -28,6 +28,10 @@ function num(v) {
|
||||
// --- Scalar indicators: update(value) vs batch(prices) ---
|
||||
|
||||
const scalarFactories = {
|
||||
BipowerVariation: () => new wickra.BipowerVariation(20),
|
||||
VolatilityOfVolatility: () => new wickra.VolatilityOfVolatility(20, 20),
|
||||
Garch11: () => new wickra.Garch11(0.000002, 0.1, 0.88),
|
||||
EwmaVolatility: () => new wickra.EwmaVolatility(0.94),
|
||||
PpoHistogram: () => new wickra.PpoHistogram(3, 6, 3),
|
||||
MacdHistogram: () => new wickra.MacdHistogram(3, 6, 3),
|
||||
TsfOscillator: () => new wickra.TsfOscillator(3),
|
||||
@@ -350,6 +354,7 @@ const candleScalar = {
|
||||
IMI: { make: () => new wickra.IMI(14), step: (ind, i) => ind.update(open[i], high[i], low[i], close[i]), batch: (ind) => ind.batch(open, high, low, close) },
|
||||
TTM_TREND: { make: () => new wickra.TTM_TREND(6), step: (ind, i) => ind.update(high[i], low[i], close[i]), batch: (ind) => ind.batch(high, low, close) },
|
||||
Qstick: { make: () => new wickra.Qstick(10), step: (ind, i) => ind.update(open[i], close[i]), batch: (ind) => ind.batch(open, close) },
|
||||
VolatilityRatio: { make: () => new wickra.VolatilityRatio(14), step: (ind, i) => ind.update(high[i], low[i], close[i]), batch: (ind) => ind.batch(high, low, close) },
|
||||
};
|
||||
|
||||
for (const [name, d] of Object.entries(candleScalar)) {
|
||||
@@ -436,6 +441,7 @@ const multi = {
|
||||
QQE: { make: () => new wickra.QQE(14, 5, 4.236), fields: ['rsiMa', 'trailingLine'], step: (ind, i) => ind.update(close[i]), batch: (ind) => ind.batch(close) },
|
||||
GatorOscillator: { make: () => new wickra.GatorOscillator(13, 8, 5), fields: ['upper', 'lower'], step: (ind, i) => ind.update(high[i], low[i], close[i]), batch: (ind) => ind.batch(high, low, close) },
|
||||
KasePermissionStochastic: { make: () => new wickra.KasePermissionStochastic(9, 3), fields: ['fast', 'slow'], step: (ind, i) => ind.update(high[i], low[i], close[i]), batch: (ind) => ind.batch(high, low, close) },
|
||||
VolatilityCone: { make: () => new wickra.VolatilityCone(20, 60), fields: ['current', 'min', 'median', 'max', 'percentile'], step: (ind, i) => ind.update(high[i], low[i], close[i]), batch: (ind) => ind.batch(high, low, close) },
|
||||
};
|
||||
|
||||
for (const [name, d] of Object.entries(multi)) {
|
||||
|
||||
Reference in New Issue
Block a user