Models¶
The sampling model determines both the prior specification and the estimation algorithm. Every model is a subclass of SamplingModel and owns the complete estimation pipeline — prior construction, data-matrix assembly, dummy-observation stacking, and posterior sampling.
Selecting a Model¶
| Model | Prior structure | Estimation | Marginal likelihood |
|---|---|---|---|
NaturalConjugate |
\(\text{vec}(A) \mid \Sigma \sim \mathcal{N}(\beta_0,\, \Sigma \otimes V_A^{-1})\), \(\Sigma \sim \mathcal{IW}(S_0, \nu_0)\) | Direct (no MCMC) | ✔ |
IndependentNIW |
\(\beta \sim \mathcal{N}(\beta_0, V_\beta)\) independently of \(\Sigma \sim \mathcal{IW}(S_0, \nu_0)\) | Gibbs sampler | ✘ |
The Marginal likelihood column indicates whether optimise_hyperparameters with optimisation_method="ml" is supported. IndependentNIW (✘) has no closed-form marginal likelihood, and its Gibbs sampler has no closed-form point estimate, so neither "ml" nor "cross_validation" is available for it — passing either raises ValueError. Use optimisation_method="none" and set hyperparameters manually.
Use NaturalConjugate for most applications: it runs faster without burn-in, supports marginal-likelihood hyperparameter optimisation, and covers the standard Minnesota / SOC / SUR prior setup. Use IndependentNIW when you need a full \((nk \times nk)\) prior precision matrix that scales cross-variable shrinkage independently of \(\Sigma\).
Usage¶
import bvar as bv
# Natural conjugate (fast, supports ML optimisation)
model = bv.NaturalConjugate(
minnesota=True,
soc=True,
sur=True,
covid=False,
)
bvar = bv.BVAR(n_lags=4, model=model, stationary=False)
bvar.optimise_hyperparameters(data)
bvar.sample(data, N_draws=5000)
# Independent NIW (full-system prior precision, Gibbs sampler)
model = bv.IndependentNIW(
c2=0.5, # cross-variable shrinkage
minnesota=True,
soc=False,
sur=False,
)
bvar = bv.BVAR(n_lags=4, model=model, stationary=False, optimisation_method="none")
bvar.sample(data, N_draws=5000)
Base Class¶
bvar.models.SamplingModel ¶
SamplingModel(minnesota: bool = True, soc: bool = True, sur: bool = True, covid: bool = False, covid_dates: Optional[list] = None)
Abstract base class for BVAR estimation models.
Each subclass owns the entire estimation pipeline and the prior hyperparameters that drive it. Common prior flags (minnesota, soc, sur, covid) and the shared hyperparameter infrastructure live here; subclasses add model-specific parameters.
| PARAMETER | DESCRIPTION |
|---|---|
minnesota
|
Apply Minnesota shrinkage to the coefficient prior. Default
TYPE:
|
soc
|
Add sum-of-coefficients dummy observations. Default
TYPE:
|
sur
|
Add a single-unit-root dummy observation. Default
TYPE:
|
covid
|
Include COVID-19 outlier dummies. Default
TYPE:
|
covid_dates
|
Two-element list
TYPE:
|
| ATTRIBUTE | DESCRIPTION |
|---|---|
requires_burnin |
TYPE:
|
supports_ml |
TYPE:
|
supports_point_only |
TYPE:
|
supports_gaussian_predictive |
TYPE:
|
supports_girf |
TYPE:
|
set_priors ¶
set_priors(c1: float = 0.2, c3: float = 2.0, lambda_constant: float = 10.0, mu: float = 1.0, theta: float = 1.0, lambda_covid: float = 10000.0, c1_mode: float = 0.2, c1_sd: float = 0.4, c3_mode: float = 2.0, c3_sd: float = 0.5, mu_mode: float = 1.0, mu_sd: float = 1.0, theta_mode: float = 1.0, theta_sd: float = 1.0) -> None
Set prior hyperparameters.
Subclasses may override to accept model-specific parameters
(e.g. c2 for :class:IndependentNIW).
fill_in_from_vector ¶
Update hyperparameters from an optimisation vector.
The vector layout is [c1, c3, ...] followed by mu (if SOC)
and theta (if SUR). Subclasses may override to insert
model-specific hyperparameters.
hyperparameter_grid ¶
Return default grid arrays for cross-validation.
The order matches :meth:fill_in_from_vector.
sample
abstractmethod
¶
sample(data: ndarray, n_lags: int, covid_indices: ndarray, vars_in_levels: ndarray, N_draws: int, point_only: bool = False, progressbar: bool = True, soc: Optional[bool] = None, sur: Optional[bool] = None, rng: Optional[Generator] = None) -> SamplingResult
Run the full estimation pipeline and return posterior draws.
During estimation, store the prior mean
(self.beta_0) and prior precision (self.V_A_inv)
so that :meth:sample_posterior_state can reuse them.
| PARAMETER | DESCRIPTION |
|---|---|
data
|
Raw data array with shape
TYPE:
|
n_lags
|
Number of VAR lags.
TYPE:
|
covid_indices
|
Observation indices for COVID dummy variables.
TYPE:
|
vars_in_levels
|
Boolean array with shape
TYPE:
|
N_draws
|
Total number of posterior draws to generate, including draws that the caller will discard as burn-in.
TYPE:
|
point_only
|
If
TYPE:
|
progressbar
|
Whether to display a progress bar.
TYPE:
|
soc
|
Effective sum-of-coefficients flag for this fit. The flag records
whether the code stacks SOC dummy observations. It defaults to
TYPE:
|
sur
|
Effective single-unit-root flag for this fit, analogous to
TYPE:
|
rng
|
Generator for the posterior draws. Defaults to a fresh
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
SamplingResult
|
Dataclass containing posterior draws. |
sample_posterior_state
abstractmethod
¶
sample_posterior_state(Y: ndarray, Z: ndarray, current_state: PosteriorState, rng: Optional[Generator] = None) -> PosteriorState
Return the next posterior state given the current one.
This is the sole posterior-update extension point: called each
iteration by Forecasting._conditional_forecast, which threads a
:class:PosteriorState through its Gibbs chain (seeded from a copy
of BVAR.posterior_state_point) to re-sample parameters after
augmenting the data with constrained forecasts, so model-owned
extras persist across iterations. The method uses
self.beta_0, self.V_A_inv, and self.pars (S_0, nu_0)
that :meth:sample stored.
| PARAMETER | DESCRIPTION |
|---|---|
Y
|
Dependent-variable matrix (with dummies already stacked if applicable).
TYPE:
|
Z
|
Regressor matrix (with dummies already stacked if applicable).
TYPE:
|
current_state
|
The previous draw's state. Direct samplers (e.g.
:class:
TYPE:
|
rng
|
Generator for the draw. Defaults to a fresh
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
PosteriorState
|
The next draw's state. |
sample_innovations ¶
sample_innovations(state: PosteriorState, H: int, rng: Optional[Generator] = None, point_only: bool = False) -> ndarray
Draw reduced-form forecast innovations for a complete posterior state.
Dispatched once per retained draw by
Forecasting.recursive_forecast and
Forecasting._unconditional_forecast, passing the draw's complete
:class:PosteriorState (beta/sigma/extras) so models
that carry auxiliary predictive state in extras (e.g. a sampled
degrees of freedom parameter for a Student-t model) can shape the
innovation distribution accordingly. The default implementation
below only uses state.sigma and draws Gaussian reduced-form
innovations ~ N(0, Sigma) -- the existing behaviour for every
current model, which ignores extras. Models that need a
different predictive distribution should override this method.
| PARAMETER | DESCRIPTION |
|---|---|
state
|
Complete posterior draw state for this draw (or
TYPE:
|
H
|
Forecast horizon (number of steps ahead).
TYPE:
|
rng
|
Generator for the draw. Defaults to a fresh
TYPE:
|
point_only
|
If
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ndarray
|
Reduced-form innovations, one row per forecast step. |
| RAISES | DESCRIPTION |
|---|---|
NotImplementedError
|
If |
sample_conditional_forecast ¶
sample_conditional_forecast(state: PosteriorState, C: ndarray, f: ndarray, Sigma_f: ndarray, shape_f: ndarray, last_p_obs: ndarray, p: int, n: int, h: int, H: int, point_only: bool, constraint_sampler: Optional[Callable] = None, method: str = 'andersson_et_al', rng: Optional[Generator] = None) -> ndarray
Draw a constrained forecast for a complete posterior state.
Dispatched once per Gibbs iteration by
Forecasting._conditional_forecast, passing the iteration's
complete :class:PosteriorState (beta/sigma/extras) so
models that carry auxiliary predictive state in extras can
shape the constrained-forecast distribution accordingly. The
default implementation below only uses state.beta/
state.sigma and routes to the existing
:func:~bvar.forecast.conditional.draw_constrained_forecasts
algorithm -- the existing behaviour for every current model, which
ignores extras. Models that need a different predictive
distribution should override this method.
| PARAMETER | DESCRIPTION |
|---|---|
state
|
Complete posterior draw state for this Gibbs iteration.
TYPE:
|
C
|
Constraint-selection matrix, as returned by
:func:
TYPE:
|
f
|
Constraint locations with shape
TYPE:
|
Sigma_f
|
Constraint scale matrix with shape
TYPE:
|
shape_f
|
Constraint shape parameters with shape
TYPE:
|
last_p_obs
|
Last p observations before the forecast period, with shape
TYPE:
|
p
|
Number of lags.
TYPE:
|
n
|
Number of variables.
TYPE:
|
h
|
Number of COVID dummies.
TYPE:
|
H
|
Forecast horizon.
TYPE:
|
point_only
|
If
TYPE:
|
constraint_sampler
|
Custom function to sample from the constraint distribution.
TYPE:
|
method
|
Algorithm:
TYPE:
|
rng
|
Generator for the draw. Defaults to a fresh
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ndarray
|
Forecast values (flattened), with shape |
| RAISES | DESCRIPTION |
|---|---|
NotImplementedError
|
If |
predictive_logpdf ¶
predictive_logpdf(state: PosteriorState, observation: ndarray, mean: ndarray, covariance: ndarray) -> float
Evaluate the log predictive density of an out-of-sample observation.
Dispatched by GridSearch.marginal_likelihood_H for each
rolling-window out-of-sample point, passing the fitted model's
posterior_state_point so models that carry auxiliary predictive
state in extras can shape the predictive distribution
accordingly. The default implementation below only uses mean and
covariance and evaluates the Gaussian
scipy.stats.multivariate_normal.logpdf -- the existing
behaviour for every current model, which ignores state.extras.
Models that need a different predictive distribution should
override this method.
| PARAMETER | DESCRIPTION |
|---|---|
state
|
Complete posterior state (typically
TYPE:
|
observation
|
The realised out-of-sample observation with shape
TYPE:
|
mean
|
Predictive mean at the forecast horizon with shape
TYPE:
|
covariance
|
Predictive covariance at the forecast horizon with shape
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Log predictive density of observation. |
| RAISES | DESCRIPTION |
|---|---|
NotImplementedError
|
If |
bvar.models.SamplingResult
dataclass
¶
SamplingResult(beta_draws: ndarray, sigma_draws: ndarray, beta_point: ndarray, sigma_point: ndarray, extras_point: Optional[Any] = None, extras_draws: Optional[list] = None)
Container for the output of a model's sample() method.
| ATTRIBUTE | DESCRIPTION |
|---|---|
beta_draws |
Posterior draws of VAR coefficients (vectorised), with shape
TYPE:
|
sigma_draws |
Posterior draws of the covariance matrix (flattened), with shape
TYPE:
|
beta_point |
Posterior point estimate of VAR coefficients, with shape
TYPE:
|
sigma_point |
Posterior point estimate of the covariance matrix, with shape
TYPE:
|
extras_point |
Model-owned auxiliary state accompanying the point estimate, or
TYPE:
|
extras_draws |
Model-owned auxiliary state for each retained draw, one entry per
row of
TYPE:
|
state_point
property
¶
state_point: PosteriorState
PosteriorState view of the posterior point estimates.
Built on demand rather than stored, so models that do not use
extras_point incur no extra allocation.
__post_init__ ¶
Validate draw counts are consistent across beta/sigma/extras.
Catching a misalignment here -- rather than later, when forecasting
indexes a row/entry by draw number -- turns a confusing
IndexError/broadcasting error deep in the forecast loop into an
immediate, clear ValueError.