TVPVARResult#

class cultivars.multivariate.nonlinear.time_varying.TVPVARResult(*, endog, names, order, trend, training, nobs, beta_mean, beta_low, beta_high, beta_draws, state_cov, sigma_u, resid, fittedvalues, n_draws, n_burn, thin)[source]#

A fitted time-varying-parameter VAR, homoskedastic innovations.

The posterior of

\[y_t = X_t' \beta_t + u_t, \qquad u_t \sim N(0, \Sigma), \qquad \beta_t = \beta_{t-1} + \eta_t, \qquad \eta_t \sim N(0, Q),\]

with \(X_t\) the Kronecker-stacked design and \(\beta_t\) the \(D = k\,w\) coefficients of all equations stacked equation-major, reached by Gibbs sampling: each coefficient path is one Durbin-Koopman simulation-smoother draw given \((Q, \Sigma)\), and the two covariances are conjugate inverse-Wishart draws given the path. Every coefficient is a path: the posterior over \(\beta_t\) is summarized by its mean and a 68% band, with the kept draws retained so downstream consumers – the structural wrapper, custom summaries – can propagate posterior uncertainty rather than plugging in a point.

Deliberately absent: llf, n_params, information criteria. A Gibbs posterior has none of them, and this result will not counterfeit the comparison surface of a likelihood fit.

Note

The first training rows calibrated the priors – the initial state from their OLS estimate, the drift covariance \(Q\) from k_drift times that estimate’s covariance – and were then discarded, so every path here is indexed on the nobs rows that follow. How much the coefficients are allowed to move is a prior choice, not a finding: under Primiceri’s default k_drift = 0.01 a slow deterministic drift of several tenths over two hundred observations is shrunk to a few hundredths, and the drift note in the summary compares the posterior mean’s movement with its band for that reason. The point summaries (sigma_u, state_cov, resid, fittedvalues) are at posterior means. The draws are a Markov chain; convergence() reads them.

Variables:
  • endog – The observed panel.

  • names – Variable labels, in column order.

  • order – Autoregressive order.

  • trend – Deterministic specification.

  • training – Rows consumed by the training prior and then discarded.

  • nobs – Estimation rows after the training split.

  • beta_mean – (nobs, D) posterior mean coefficient path, stacked equation-major.

  • beta_low – (nobs, D) posterior 16th percentile path.

  • beta_high – (nobs, D) posterior 84th percentile path.

  • beta_draws – (S, nobs, D) kept coefficient-path draws.

  • state_cov – (D, D) posterior mean drift covariance Q.

  • sigma_u – (k, k) posterior mean innovation covariance.

  • resid – Residuals at the posterior mean path.

  • fittedvalues – One-step means at the posterior mean path.

  • n_draws – Total sampler iterations.

  • n_burn – Burn-in discarded.

  • thin – Post-burn thinning.

See also

  • TVPVAR – the model that produces this record.

  • TVPVARSVResult – the same paths with drifting volatility.

  • TVPSVAR – the recursive structural reading of either.

  • BVARResult – the constant-coefficient posterior these paths relax.

References

Primiceri, G. E. (2005). Time varying structural vector autoregressions and monetary policy. Review of Economic Studies, 72(3), 821-852.

Cogley, T., & Sargent, T. J. (2005). Drifts and volatilities: Monetary policies and outcomes in the post WWII US. Review of Economic Dynamics, 8(2), 262-302.

Example

A bivariate system whose first own-lag coefficient drifts linearly from 0.2 to 0.8; with a loose drift prior the posterior mean path climbs by several tenths, its band brackets the path throughout, and the local companion root rises with it:

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> y = np.zeros((240, 2))
>>> phi = np.linspace(0.2, 0.8, 240)
>>> for t in range(1, 240):
...     y[t, 0] = phi[t] * y[t - 1, 0] + rng.standard_normal()
...     y[t, 1] = 0.4 * y[t - 1, 1] + 0.3 * y[t - 1, 0] + rng.standard_normal()
>>> res = TVPVAR(y, order=1, training=40).fit(
...     n_draws=60, n_burn=20, k_drift=0.3, seed=0
... )
>>> res.training, res.nobs, res.n_kept, res.beta_mean.shape, res.beta_draws.shape
(40, 199, 20, (199, 6), (20, 199, 6))
>>> path = res.coefficient_path("y1", "y1.L1")
>>> bool(path[-1, 1] - path[0, 1] > 0.25), bool(np.all(path[:, 0] < path[:, 2]))
(True, True)
>>> roots = res.stability_path()
>>> bool(roots[-1] > roots[0]), bool(roots.max() < 1.0)
(True, True)
>>> res.sigma_u.shape, res.state_cov.shape
((2, 2), (6, 6))

Attributes#

endog

The observed panel, (nobs_total, k), training rows included.

names

Variable labels, in column order.

order

The autoregressive order p.

trend

"n", "c" or "ct".

training

Rows split off the front to calibrate the priors, then discarded.

nobs

Estimation rows after the training split and the p presample rows.

beta_mean

(nobs, D) posterior mean coefficient path, equation-major.

beta_low

(nobs, D) posterior 16th-percentile path.

beta_high

(nobs, D) posterior 84th-percentile path.

beta_draws

(S, nobs, D) kept coefficient-path draws.

state_cov

(D, D) posterior mean drift covariance Q.

sigma_u

(k, k) posterior mean innovation covariance.

resid

(nobs, k) residuals at the posterior mean path.

fittedvalues

(nobs, k) one-step means at the posterior mean path.

n_draws

Total sampler iterations, burn-in included.

n_burn

Iterations discarded from the start.

thin

Every thin-th post-burn iteration is kept.

k_endog

Number of endogenous variables.

n_kept

Posterior draws retained after burn-in and thinning.

Methods#

coefficient_path(equation, regressor)

One coefficient's posterior path: 16th percentile, mean, 84th.

coefficients_at(t)

The posterior mean lag stack A_1..A_p prevailing at date t.

convergence(*chains[, include, exclude, ...])

Assess the sampler's convergence over the retained draws.

stability_path()

Largest companion-root modulus of the posterior mean VAR at each date.

summary()

The estimation summary, renderable as text, HTML, or a dataframe.