StochasticVolatility#

class impulso.sv.spec.StochasticVolatility(*, name='sv', is_time_varying=True, dynamics='random_walk', prior='default')[source]#

Bases: ImpulsoBaseModel

Univariate stochastic volatility model.

Parameters:
  • name (Literal['sv'])

  • is_time_varying (bool)

  • dynamics (Literal['random_walk', 'ar1'] | ~impulso.sv.dynamics.SVDynamics)

  • prior (Literal['default'] | ~impulso.sv.priors.SVPrior)

name#

Discriminator key for the volatility-process registry (always “sv”).

Type:

Literal[‘sv’]

is_time_varying#

Always True — Σ_t evolves over t.

Type:

bool

dynamics#

Log-volatility dynamics. String shorthand (“random_walk” or “ar1”) or an explicit SVDynamics instance (e.g. RandomWalk(), AR1()).

Type:

Literal[‘random_walk’, ‘ar1’] | impulso.sv.dynamics.SVDynamics

prior#

Prior shorthand string or SVPrior instance.

Type:

Literal[‘default’] | impulso.sv.priors.SVPrior

Expand for references to impulso.sv.spec.StochasticVolatility

Stochastic volatility: modelling time-varying uncertainty / Why time-varying volatility matters

build_pymc_latent(n_vars, T, data=None)[source]#

Register the Clark-style multivariate SV latents.

For each i in 0..n_vars-1: per-variable priors are seeded from data[:, i] (typically VAR OLS residuals), then a log-vol path h_i,t is registered via the configured dynamics. The per-variable log-vol level comes from the dynamics’ own intercept when available (AR(1)’s alpha), else from an outer mu_i (random-walk has no intrinsic level). The shared mixing factor R_chol (a unit-diagonal lower-triangular n_vars x n_vars matrix) is registered once via the manual LKJ workaround. Note: pinning the diagonal of a Cholesky factor to 1 does not make R_chol @ R_chol.T a correlation matrix; the Gram-matrix diagonal is 1 + sum_j off[i,j]^2. The diagonal pin is an identifiability device: all volatility scaling lives in h, so R_chol is identified only up to its off-diagonal mixing entries. The manual assembly avoids PyMC’s LKJCholeskyCov / LKJCorr, which are broken on the supported dependency set; see docs/adr/0014-manual-cholesky-parameterisation.md.

Parameters:
  • n_vars (int) – Number of structural shocks / endogenous variables.

  • T (int) – Number of in-sample observations.

  • data (ndarray | None) – Per-variable series of shape (T, n_vars) used to seed per-variable priors. Required — the VAR pipeline passes OLS residuals; direct callers should do the same.

Returns:

L_t of shape (T, n_vars, n_vars) where L_t[t] = diag(exp(h_t / 2)) @ R_chol.

Return type:

pt.TensorVariable

cholesky_at(posterior, t)[source]#

Return L_t = diag(exp(h_t / 2)) @ R_chol for the requested t.

Parameters:
  • posterior (xr.Dataset) – An xarray Dataset containing h of shape (chains, draws, T, n_vars) and R_chol of shape (chains, draws, n_vars, n_vars).

  • t (int | None) – Time index. None defaults to the most recent (T-1).

Returns:

Cholesky factor at time t, shape (chains, draws, n_vars, n_vars).

Return type:

ndarray

cholesky_path(posterior, T)[source]#

Return the full L_t path for t in 0..T-1.

Parameters:
  • posterior (xr.Dataset) – An xarray Dataset containing h (chains, draws, T, n_vars) and R_chol (chains, draws, n_vars, n_vars).

  • T (int) – Expected length of the time axis. Must match h.shape[2].

Returns:

(chains, draws, T, n_vars, n_vars).

Return type:

ndarray

fit(data, sampler=None)[source]#

Fit the SV model via NUTS.

Parameters:
  • data (SVData) – SVData container.

  • sampler (Sampler | None) – Sampler instance. Defaults to _default_sampler() (cores=1, chains=4, target_accept=0.9).

Returns:

FittedSV with posterior draws.

Return type:

FittedSV

forecast_cholesky_path(posterior, steps, rng)[source]#

Forecast the per-t Cholesky factor for steps ahead.

Each variable’s log-vol is extrapolated independently using the configured dynamics with name_prefix=f"v{i}_" so the dynamics reads {prefix}h, {prefix}sigma_eta, and its own hyperparameters directly from the full posterior. The correlation Cholesky R_chol is held constant (Clark-style assumption).

The extrapolation reproduces the same composition build_pymc_latent used in sample: when the dynamics carries no intrinsic level (has_explicit_level is False, i.e. random walk) the per-variable level v{i}_mu is added back on, because forecast_log_vol only extrapolates the level-free v{i}_h. Omitting it scales every forecast standard deviation by exp(-mu_i / 2) while leaving the in-sample fit untouched (#241).

Parameters:
  • posterior (xr.Dataset) – Dataset with per-variable log-vol paths (h) and R_chol.

  • steps (int) – Forecast horizon.

  • rng (Generator) – Random number generator for the extrapolation innovations.

Returns:

(chains, draws, steps, n_vars, n_vars).

Return type:

ndarray

model_config = {'arbitrary_types_allowed': True, 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property resolved_dynamics: SVDynamics#

Resolve string shorthand to a concrete SVDynamics instance.

property resolved_prior: SVPrior#

Resolve string shorthand to a concrete SVPrior instance.