PanelVARResult#

class cultivars.multivariate.reduced_form.panel.PanelVARResult(*, endog, names, order, trend, sigma_u, sigma_ml, resid, fittedvalues, design, llf, nobs, n_params, posterior=None, prior_label='none', coefficients, deterministic, unit_names, unit_lengths, effects)[source]

Bases: _VectorResult, _SummaryMixin, _ComparisonMixin, _VectorInferenceMixin, _VectorPropagationMixin

A fitted panel vector autoregression with pooled slopes.

Every unit \(i\) shares the autoregressive matrices and the innovation covariance and differs only in its intercept,

\[y_{it} = \mu_i + \sum_{l=1}^{p} A_l\, y_{i,t-l} + u_{it}, \qquad u_{it} \sim (0, \Sigma_u), \qquad i = 1, \dots, N,\]

estimated by least squares on the stacked panel with one dummy per unit (effects="unit") or with a single pooled deterministic block (effects="none"). Lags are built inside each unit, so the effective sample is \(\sum_i (T_i - p)\) and no regressor crosses a unit boundary.

The residual matrix is a stack of units rather than one series, and every inherited method that reads residual history reads it through _sample_blocks, so no lagged cross-product and no shock propagation ever crosses a unit boundary. irf, fevd, and stability_check depend only on the pooled matrices and are unqualified.

forecast() is unit-specific and says so: the slopes are pooled but the intercept and the lag history are not, so there is no single path to return.

Note

Two biases bracket this estimator and the summary names the one that applies. With unit dummies the lag coefficients carry the Nickell bias, of order \(1/T\) in the shortest unit and downward for a positive own-lag; it does not shrink as units are added. Without them, heterogeneous intercepts load onto the lags and the pooled slopes are biased toward persistence – on a panel whose units differ in level, effects="none" can nearly double an own-lag coefficient. The first bias is the price of removing the second, and the GMM-in-differences estimators that avoid both are not implemented here. Pooling itself is the stronger assumption: heterogeneous dynamics estimated as if common do not average to the mean dynamics.

Variables:
  • endog – Every unit stacked, in the order given. Not a time series.

  • names – Variable labels, in Cholesky order.

  • unit_names – Unit labels.

  • unit_lengths – Observations per unit before lags are taken.

  • effects – "unit" or "none".

  • order – Autoregressive order, common to all units.

  • trend – Deterministic specification, meaningful only under "none".

  • coefficients – (p, k, k) stack of pooled A_1, ..., A_p.

  • deterministic – One row per unit under fixed effects, otherwise one row per deterministic term.

  • sigma_u – Pooled residual covariance with the degrees-of-freedom correction, which counts the unit indicators.

  • sigma_ml – Pooled residual covariance divided by the effective sample.

  • resid – Residuals, stacked in unit order.

  • fittedvalues – One-step conditional means, stacked in unit order.

  • design – The regressor matrix as estimated.

  • llf – Gaussian log-likelihood.

  • nobs – Effective sample size, the sum of T_i - p.

  • n_params – Free parameters, covariance included.

See also

  • PanelVAR – the model whose fit() returns this record.

  • VARResult – the single-unit case, whose surface this record inherits.

  • GVARResult – the other many-unit system in the package, which lets every unit keep its own dynamics and links them instead of pooling.

References

Holtz-Eakin, D., Newey, W., & Rosen, H. S. (1988). Estimating vector autoregressions with panel data. Econometrica, 56(6), 1371-1395.

Nickell, S. (1981). Biases in dynamic models with fixed effects. Econometrica, 49(6), 1417-1426.

Canova, F., & Ciccarelli, M. (2013). Panel vector autoregressive models: A survey. In VAR Models in Macroeconomics – New Developments and Applications (Advances in Econometrics, Vol. 32, pp. 205-246). Emerald.

Example

Six units of unequal length share one autoregression around unit means two standard deviations apart. With unit effects the pooled slopes land near the truth and the own-lag of the second variable shows the downward Nickell bias; without them the level differences masquerade as persistence:

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> A = np.array([[0.5, 0.2], [0.1, 0.4]])
>>> units = []
>>> for i in range(6):
...     mu = rng.normal(0.0, 2.0, size=2)
...     y = np.zeros((80 + 10 * i, 2))
...     y[0] = mu
...     for t in range(1, y.shape[0]):
...         y[t] = mu + A @ (y[t - 1] - mu) + rng.standard_normal(2)
...     units.append(y)
>>> res = PanelVAR(units, order=1).fit()
>>> res.n_units, res.unit_lengths, res.nobs, res.min_time_dimension
(6, (80, 90, 100, 110, 120, 130), 624, 80)
>>> res.coefficients[0].round(2)
array([[0.53, 0.22],
       [0.14, 0.33]])
>>> pooled = PanelVAR(units, order=1, effects="none", trend="c").fit()
>>> bool(pooled.coefficients[0, 0, 0] > 0.8), bool(pooled.coefficients[0, 1, 1] > 0.55)
(True, True)
>>> sorted(res.unit_effects)[:2], res.forecast(3, unit="unit2").shape
(['unit1', 'unit2'], (3, 2))

Private attributes#

_sample_blocks

One half-open residual span per unit, in stacking order.

Private methods#

_comparison_label()

Short specification label for a ranking table.

_deterministic_labels()

One intercept name per unit under fixed effects, otherwise the trend block.

_from_fit(fit, model)

Assemble the public result from the internal fit and its model.

_summary_table()

Build the structured summary.

_unit_index(unit)

Position of a unit, or a failure naming the ones that exist.