FactorSV#

class cultivars.multivariate.large_dim.factor_volatility.FactorSV(panel, *, n_factors, series_names=None)[source]

Bases: _FactorVolatilityModel[FactorSVResult]

Factor stochastic volatility, Chib-Nardari-Shephard.

\[y_t = \Lambda f_t + \varepsilon_t, \qquad f_{jt} = e^{h_{jt}/2}\,u_{jt}, \quad \varepsilon_{it} = e^{\eta_{it}/2}\,v_{it},\]

with a log-AR(1) variance on every factor and every idiosyncratic error, so a wide panel’s time-varying covariance \(\Lambda H_t \Lambda' + D_t\) is built from \(k + r\) volatility paths and one loading matrix rather than the \(O(k^2)\) parameters a multivariate GARCH needs. Estimation is by an exact Gibbs sampler and the result is a posterior, not a point estimate: FactorSVResult holds the retained draws of the loadings, the factors and every volatility path.

Identification is the triangular convention: \(\Lambda\) is lower triangular with a unit diagonal in its leading \(r\) rows, so factor \(j\) is measured in the units of series \(j\) and signed by it. The ordering of the panel’s columns is therefore a modelling decision – the first n_factors series anchor the factors – and the posterior is not invariant to it. The sample mean of each series is removed before sampling and kept on the result as means.

Variables:
  • _panel – The validated (nobs, k) panel as a float array.

  • _n_factors – The number of latent factors.

  • _series_names – One label per column.

Parameters:
  • panel (ArrayLike) – The observed (nobs, k) panel (returns, typically); the sample mean of each series is removed.

  • n_factors (int) – Number of latent factors, at least one and below k.

  • series_names (Sequence[str] | None) – One label per series. Defaults to x1 ... xk. The first n_factors series scale and sign the factors, so put the series that should anchor each factor first.

Raises:
  • SpecificationError – If n_factors is not a positive integer or series_names does not have one entry per column.

  • DimensionError – If the panel is not two-dimensional, has fewer than 50 rows, or has no more columns than n_factors.

See also

  • FactorSVResult – the posterior record fit returns.

  • DFM – the constant-variance factor model.

  • SV – the univariate volatility law every path follows.

  • VolatilityPrior – the prior on that law.

References

Chib, S., Nardari, F., & Shephard, N. (2006). Analysis of high dimensional multivariate stochastic volatility models. Journal of Econometrics, 134(2), 341-371.

Pitt, M. K., & Shephard, N. (1999). Time-varying covariances: A factor stochastic volatility approach. In Bayesian Statistics 6 (pp. 547-570). Oxford University Press.

Example

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> n, k = 300, 5
>>> h = np.zeros(n)
>>> for t in range(1, n):
...     h[t] = 0.95 * h[t - 1] + 0.3 * rng.standard_normal()
>>> f = np.exp(h / 2) * rng.standard_normal(n)
>>> lam = np.array([1.0, 0.8, 0.6, 0.4, 0.2])
>>> y = np.outer(f, lam) + 0.5 * rng.standard_normal((n, k))
>>> res = FactorSV(y, n_factors=1).fit(n_draws=300, n_burn=100, seed=0)
>>> res.loadings.shape
(5, 1)
>>> bool(res.communality()[0] > res.communality()[-1])
True
>>> FactorSV(y, n_factors=5)
Traceback (most recent call last):
cultivars.exceptions.DimensionError: n_factors (5) must be below the number of series (5).