hmm_forecast
HMM forecasting and diagnostics: state/vol/probability forecasts, pseudo-residuals, decode stats.
Visual Example

Post-fit analytics: π_{t+h|t}=π_t·Γ^h state forecasts and mixture volatility from filtered state weights.
Description
Post-fit HMM analytics aligned with ldhmm / SSRN 2979516: multi-step state probability forecasts (π_{t+h|t} = π_t · Γ^h), mixture volatility forecasts using lambda-aware emission variances, pseudo-residuals for model checking via the probability integral transform, and decode_stats_history (per-bar weighted mean, vol, λ).
Apply after fitting a gaussian_hmm or lambda_hmm model. Polars exposes .hmm_forecast_vol, .hmm_pseudo_residuals, and .hmm_decode_stats; Python exposes gaussian_hmm_diagnostics and point forecast helpers. Gold-standard parity on hmm_lambda_2state.json locks forecast_state, vol, and pseudo-residuals. Use pseudo-residuals to assess calibration; under a well-specified model they should be approximately standard normal.
Formula / Specification
Implementation (quantwave-core/src/regimes/hmm_forecast.rs):
See the Next<T> implementation and METADATA in the core module.
Gold-standard parity vectors: quantwave-core/tests/gold_standard/hmm_lambda_2state.json.
Parameters
| Parameter | Default | Description |
|---|---|---|
horizon |
1 | Forecast horizon h (bars ahead). |
Usage Examples
Python (diagnostics bundle after fit)
import quantwave as qw
fit = qw.fit_gaussian_hmm(returns, n_states=2, max_iter=100, fit_lambdas=True)
diag = qw.gaussian_hmm_diagnostics(fit.params, returns)
vol_h1 = qw.gaussian_hmm_forecast_vol(fit.params, diag.forecast_state_h1, horizon=1)
Polars
df = (
df.lazy()
.ta()
.hmm_forecast_vol("returns", n_states=2, max_iter=100, fit_lambdas=True, horizon=1)
.hmm_pseudo_residuals("returns", n_states=2, max_iter=100, fit_lambdas=True)
.hmm_decode_stats("returns", n_states=2, max_iter=100, fit_lambdas=True)
.collect()
)
Rust
use quantwave_core::regimes::hmm_forecast::{forecast_state, forecast_volatility, pseudo_residuals};
let decode = params.decode(&observations)?;
let last = decode.forward_filter.iter().map(|row| row[n - 1]).collect();
let pi_h1 = forecast_state(¶ms, &last, 1)?;
let vol_h1 = forecast_volatility(¶ms, &last, 1)?;
Edge Cases & Limitations
- Warm-up: first
1bars may return NaN or partial state per implementation. - Parameter sensitivity: smaller periods increase noise; larger periods increase lag.
- Sudden gaps or bad ticks can distort rolling windows — consider pre-filtering.
- Single-series indicators ignore volume unless otherwise documented.
- Validated via proptests against gold-standard vectors where available.
- No look-ahead bias; streaming and Polars batch paths are bit-identical.
Boundary Behavior
| Condition | Behavior |
|---|---|
| Warm-up | Leading bars return NaN until warmup_bars is satisfied. |
| period > len | When period exceeds series length, output is all NaN. |
| NaN inputs | NaN in input propagates to output (NaN out). |
| Invalid params | Non-positive period or missing required params raise ValueError. |
| Empty data | Empty input returns an empty result series. |
Related Indicators & See Also
Sources & References
Primary Source: references/ldhmm/ldhmm-cran-reference.pdf; references/ldhmm/ssrn-2979516.pdf
Implementation: quantwave-core/src/indicators/hmm_forecast.rs (HMM_FORECAST / HMM_FORECAST_METADATA).
Parity: quantwave-core/tests/gold_standard/hmm_lambda_2state.json
Provenance: Standards bulk upgrade 2026-07-04 IST — see docs/DOCUMENTATION_STANDARDS.md.