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
HistoricalVolatility
Historical Volatility — the annualised standard deviation of log returns, the realised volatility used to price options and size risk.
Quick reference
| Field | Value |
|---|---|
| Family | Volatility & Bands |
| Input type | f64 (single close) |
| Output type | f64 |
| Output range | [0, ∞) (annualised percent) |
| Default parameters | (period = 20, trading_periods = 252) (Python) |
| Warmup period | period + 1 |
| Interpretation | Annualised volatility of returns, in percent. |
Formula
r_t = ln(price_t / price_{t−1})
HV = stddev_sample(r over period) · √trading_periods · 100
The log returns over the window are measured with the sample standard
deviation (divisor n − 1, Bessel's correction — the unbiased volatility
estimator), then annualised by √trading_periods and expressed as a
percentage. trading_periods is the number of bars in a year for the
data's frequency: 252 for daily bars, 52 for weekly, 12 for
monthly.
Parameters
| Name | Type | Default | Valid range | Description |
|---|---|---|---|---|
period |
usize |
20 (Python) |
>= 2 |
Number of log returns in the window. 0 errors with Error::PeriodZero; 1 with Error::InvalidPeriod (the sample stddev needs two returns). |
trading_periods |
usize |
252 (Python) |
>= 1 |
Annualisation factor. 0 errors with Error::PeriodZero. |
The Python binding defaults the pair to (20, 252). The periods
property returns (period, trading_periods).
Inputs / Outputs
From crates/wickra-core/src/indicators/historical_volatility.rs:
impl Indicator for HistoricalVolatility {
type Input = f64;
type Output = f64;
// update(&mut self, input: f64) -> Option<f64>
}
A single f64 close in, an Option<f64> out. Python maps this to
float | None / numpy.ndarray (NaN warmup); Node to number | null /
Array<number> (NaN warmup).
Warmup
warmup_period() == period + 1. The first log return needs a previous
price, and the window must then hold period returns — so the first
non-None output lands on input period + 1.
Edge cases
- Constant series. A flat price series has all log returns equal to
0, so volatility is0.0(constant_series_yields_zeropins this). - Geometric series. A constant growth factor produces a constant
log return; its standard deviation — and so HV — is
0(geometric_series_yields_zeropins this). - Non-positive prices. A log return is undefined when either price is
<= 0; that return is treated as0. - Non-negative. Volatility is a standard deviation and is never
negative (
output_is_non_negativepins this). - NaN / infinity inputs. Non-finite inputs are silently dropped.
- Reset.
hv.reset()clears the previous price, the window and the running sums.
Examples
Rust
use wickra::{BatchExt, Indicator, HistoricalVolatility};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 20-bar window, 252 trading days per year.
let mut hv = HistoricalVolatility::new(20, 252)?;
let prices: Vec<f64> = (0..40).map(|i| 100.0 * 1.01_f64.powi(i)).collect();
let out = hv.batch(&prices);
println!("warmup_period = {}", hv.warmup_period());
// A perfectly geometric series has constant returns -> zero volatility.
println!("last = {:?}", out.last().unwrap());
Ok(())
}
Output:
warmup_period = 21
last = Some(0.0)
Python
import numpy as np
import wickra as ta
hv = ta.HistoricalVolatility() # (period=20, trading_periods=252)
prices = np.full(40, 100.0) # flat series
print(hv.batch(prices)[-1]) # no return variation -> 0
Output:
0.0
Node
const ta = require('wickra');
// 52 trading periods per year for weekly bars.
const hv = new ta.HistoricalVolatility(20, 52);
const prices = Array.from({ length: 60 }, (_, i) => 100 + Math.sin(i * 0.3) * 5);
console.log('warmupPeriod:', hv.warmupPeriod());
Interpretation
HistoricalVolatility is the realised-volatility number quoted in
options and risk work — "this stock has been running at 30 % annualised
vol". Compare it against an option's implied volatility to judge whether
options are cheap or rich, feed it into position-sizing (smaller size as
HV rises), or track its own trend: volatility clusters, so a rising HV
tends to keep rising.
Always match trading_periods to your bar frequency — annualising daily
bars with 252, weekly with 52, monthly with 12. Using the wrong
factor rescales every reading.
Common pitfalls
- Mismatched
trading_periods. Annualising weekly data with252inflates HV by√(252/52) ≈ 2.2×. - Confusing it with
StdDev.StdDevis the population dispersion of prices;HistoricalVolatilityis the sample (n − 1) dispersion of log returns, annualised.
References
Historical (realised) volatility is the standard √252-annualised
standard deviation of log returns; the unbiased n − 1 estimator is the
conventional choice for volatility estimation.
See also
- Indicator-StdDev.md — population dispersion of raw prices.
- Indicator-Natr.md — range-based volatility as a percentage.
- Indicators-Overview.md — the full taxonomy.