garch_volatility

Defined in fynance.features.garch

garch_volatility(returns, refit=None, min_train=250, model='garch', dist='normal')[source]

Causal GARCH-family conditional-volatility feature.

Fits a GARCH(1,1)-family model on a training prefix and forward-filters the conditional volatility \(\sigma_t\) over the whole series. The first min_train values are NaN (the warmup whose parameters would be in-sample).

Parameters:
returnsarray-like

One-dimensional return series.

refitint, optional

Refit the parameters on the expanding window every refit steps (each block uses parameters fit strictly on its own past). If None (default), the parameters are fit once on returns[:min_train].

min_trainint, optional

Length of the initial training prefix; values before it are NaN. Default 250.

model{‘garch’, ‘gjr’, ‘egarch’}, optional

Conditional-variance specification. Default 'garch'.

dist{‘normal’, ‘t’}, optional

Innovation density. Default 'normal'.

Returns:
numpy.ndarray

Conditional volatility \(\sigma_t\), same length as returns, NaN on the warmup.

Raises:
ValueError

If min_train is not in [2, len(returns)).

Notes

With the defaults (model='garch', dist='normal') the estimation path is the historical one: each block is fit with the ARMA-GARCH likelihood (fynance.estimator.estimator.target_function), so its output is bit-for-bit unchanged. Any non-default model / dist routes each block through fynance.estimator.fit_volatility (which demeans the training prefix, fits by maximum likelihood, then the fitted parameters forward-filter the demeaned full series). Both paths stay strictly causal: the training mean and the parameters depend only on the block’s own past.

Examples

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> r = rng.standard_normal(400) * 0.01
>>> sigma = garch_volatility(r, min_train=200)
>>> sigma.shape
(400,)
>>> bool(np.all(np.isnan(sigma[:200])))
True
>>> bool(np.all(sigma[200:] >= 0))
True