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:
@@ -45,6 +45,10 @@ def ohlcv() -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
|
||||
# --- Scalar (f64 -> f64) indicators ---------------------------------------
|
||||
|
||||
SCALAR = [
|
||||
(ta.BipowerVariation, (20,)),
|
||||
(ta.VolatilityOfVolatility, (20, 20)),
|
||||
(ta.Garch11, (0.000002, 0.1, 0.88)),
|
||||
(ta.EwmaVolatility, (0.94,)),
|
||||
(ta.PpoHistogram, (3, 6, 3)),
|
||||
(ta.MacdHistogram, (3, 6, 3)),
|
||||
(ta.TsfOscillator, (3,)),
|
||||
@@ -361,6 +365,7 @@ def test_relative_strength_streaming_matches_batch():
|
||||
# 6-tuple candle; the batch helper takes only the columns it needs.
|
||||
|
||||
CANDLE_SCALAR = {
|
||||
"VolatilityRatio": (lambda: ta.VolatilityRatio(14), lambda ind, h, l, c, v: ind.batch(h, l, c)),
|
||||
"TTM_TREND": (lambda: ta.TTM_TREND(6), lambda ind, h, l, c, v: ind.batch(h, l, c)),
|
||||
"StochasticCCI": (lambda: ta.StochasticCCI(14), lambda ind, h, l, c, v: ind.batch(h, l, c)),
|
||||
# Per-bar OHLC transforms (open matters). The streaming harness feeds
|
||||
@@ -899,6 +904,11 @@ def test_candle_scalar_streaming_matches_batch(name, ohlcv):
|
||||
# --- Candle-input, multi-output indicators --------------------------------
|
||||
|
||||
MULTI = {
|
||||
"VolatilityCone": (
|
||||
lambda: ta.VolatilityCone(20, 60),
|
||||
lambda ind, h, l, c, v: ind.batch(h, l, c),
|
||||
5,
|
||||
),
|
||||
"KasePermissionStochastic": (
|
||||
lambda: ta.KasePermissionStochastic(9, 3),
|
||||
lambda ind, h, l, c, v: ind.batch(h, l, c),
|
||||
@@ -2890,6 +2900,24 @@ def test_ppo_histogram_reference():
|
||||
assert t.update(100.0 + i * 2.0) is None
|
||||
assert t.update(100.0 + 7 * 2.0) == pytest.approx(-0.052098, abs=1e-6)
|
||||
|
||||
|
||||
def test_ewma_volatility_reference():
|
||||
t = ta.EwmaVolatility(0.94)
|
||||
assert t.update(100.0) is None
|
||||
assert t.update(110.0) == pytest.approx(0.09531017980432493)
|
||||
assert t.update(99.0) == pytest.approx(0.0959428936787596)
|
||||
|
||||
|
||||
def test_garch11_reference():
|
||||
t = ta.Garch11(0.000002, 0.1, 0.88)
|
||||
assert t.update(100.0) is None
|
||||
assert t.update(110.0) == pytest.approx(0.009999999999999995)
|
||||
assert t.update(99.0) == pytest.approx(0.031597516317477786)
|
||||
|
||||
|
||||
def test_volatility_cone_reference():
|
||||
t = ta.VolatilityCone(20, 60)
|
||||
|
||||
# --- Lifecycle ------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user