fit_volatility

Defined in fynance.estimator

fit_volatility(y, model='garch', dist='normal', x0=None)[source]

Maximum-likelihood fit of a GARCH-family volatility model.

Demeans y (the sample mean is removed first) and maximises the GARCH-family log-likelihood (loglik_garch) with scipy.optimize.minimize (method='SLSQP'), under box bounds and stationarity constraints. The starting point is the variance-targeting heuristic (see Notes); an explicit x0 overrides it. Standard errors come from the inverse numerical Hessian of the negative log-likelihood.

Parameters:
yarray-like

One-dimensional return series (demeaned internally).

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

Conditional-variance specification. 'garch' is vanilla GARCH(1, 1); 'gjr' adds a leverage term; 'egarch' models the log-variance. Default is 'garch'.

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

Innovation density: Gaussian or standardized Student-t (nu > 2). Default is 'normal'.

x0array-like, optional

Explicit starting parameter vector (in the layout described in the module docstring). Overrides the variance-targeting heuristic.

Returns:
VolatilityResult

Fitted parameters, standard errors, information criteria, in-sample conditional volatility, standardized residuals, and forecasting / simulation methods.

Notes

The starting point uses variance targeting with alpha = 0.05, beta = 0.90, gamma = 0.05 and (for 't') nu = 8, and sets omega so the model’s unconditional variance matches the sample variance: omega = var * (1 - alpha - beta) for garch / gjr and, in log space, omega = ln(var) * (1 - beta) for egarch.

Information criteria are AIC = 2k - 2ll and BIC = k ln(n) - 2ll (k parameters, n observations, ll the maximised log-likelihood).

Examples

>>> import numpy as np
>>> from fynance.estimator import fit_volatility
>>> rng = np.random.default_rng(0)
>>> y = rng.standard_normal(300) * 0.02
>>> res = fit_volatility(y, model='garch', dist='normal')
>>> sorted(res.params)
['alpha', 'beta', 'omega']
>>> res.conditional_vol.shape
(300,)
>>> bool(np.isfinite(res.aic) and np.isfinite(res.bic))
True
>>> bool(np.all(res.forecast(5) > 0.0))
True