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]
Bases:
_SummaryMixin,_ConvergenceMixinA 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
trainingrows calibrated the priors – the initial state from their OLS estimate, the drift covariance \(Q\) fromk_drifttimes that estimate’s covariance – and were then discarded, so every path here is indexed on thenobsrows that follow. How much the coefficients are allowed to move is a prior choice, not a finding: under Primiceri’s defaultk_drift = 0.01a 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 covarianceQ.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))
Private attributes#
Deterministic columns per equation. |
|
Regressors per equation, |
Private methods#
One line on how much the coefficients actually moved. |
|
|
Specification stem for display. |
Per-equation regressor labels, in design order. |
|
Build the structured summary. |