FactorSV.fit#

FactorSV.fit(*, n_draws=3000, n_burn=1000, thin=1, prior=None, loading_prior_precision=1.0, seed=None)[source]#

Sample the posterior.

Every log-variance path carries the Kim-Shephard-Chib prior – Gaussian on the mean, Beta on \((\phi + 1) / 2\), inverse-gamma on the innovation variance – and each free loading an independent \(N(0, 1 / \text{precision})\) prior. One Gibbs sweep draws the factors (one Gaussian per period), the free loadings (one weighted regression per row), and every log-variance path with its three parameters through the mixture blocks; the first n_burn sweeps are discarded and every thin-th of the rest is kept, so (n_draws - n_burn) // thin draws come back. The same seed reproduces the chain exactly.

Parameters:
  • n_draws (int) – Total sampler iterations.

  • n_burn (int) – Burn-in discarded, below n_draws.

  • thin (int) – Keep every thin-th post-burn draw, at least 1.

  • prior (_VolatilityPrior | None) – The prior on each factor’s volatility law, an instance of VolatilityPrior or None to use the default Kim-Shephard-Chib prior.

  • loading_prior_precision (float) – Prior precision on each free loading, positive; larger shrinks the free loadings toward zero.

  • seed (int | Generator | None) – Seed or generator.

Return type:

FactorSVResult

Returns:

The FactorSVResult.

Raises:

SpecificationError – If n_burn is not below n_draws, thin is below 1, or loading_prior_precision is not positive.

Example

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> f = rng.standard_normal(200)
>>> y = np.outer(f, [1.0, 0.8, 0.6]) + 0.3 * rng.standard_normal((200, 3))
>>> model = FactorSV(y, n_factors=1)
>>> res = model.fit(n_draws=120, n_burn=40, thin=2, seed=0)
>>> res.n_kept, res.n_draws, res.n_burn, res.thin
(40, 120, 40, 2)
>>> again = model.fit(n_draws=120, n_burn=40, thin=2, seed=0)
>>> bool(np.array_equal(res.loading_draws, again.loading_draws))
True
>>> tight = model.fit(
...     n_draws=120, n_burn=40, thin=2, seed=0, loading_prior_precision=100.0
... )
>>> bool(abs(tight.loadings[1, 0]) < abs(res.loadings[1, 0]))
True
>>> model.fit(n_draws=100, n_burn=100)
Traceback (most recent call last):
cultivars.exceptions.SpecificationError: n_draws (100) must exceed n_burn (100).