MixedSVAR#

class cultivars.multivariate.structural.zero_restrictions.MixedSVAR(result, *, impact=None, long_run=None, shock_names=None)[source]

Bases: _IdentificationModel[SVARResult]

Zero restrictions split across impact and the long run, Galí (1999).

The scheme that needs both horizons at once: a technology shock is the only one moving productivity forever – a long-run zero – while a policy shock is barred from moving output on impact – a short-run zero. Neither ShortRunSVAR nor LongRunSVAR can say both; this model takes a pattern for each matrix and finds the one factorization satisfying every declared cell. The search runs where the problem lives, over rotations of the Cholesky factor,

\[B = L Q, \qquad Q' Q = I, \qquad B_{ij} = c_{ij} \;\text{(impact cells)}, \qquad (F B)_{ij} = d_{ij} \;\text{(long-run cells)},\]

so the innovation covariance is reproduced identically at every candidate and the restrictions are the only thing being solved for. A rotation has exactly \(k(k-1)/2\) degrees of freedom, which is why exactly that many restrictions are required – fewer is an under-identified pattern, more is an over-identified one whose restricted covariance estimation this model deliberately does not attempt.

Parameters:
  • result (ClosedSystemResult) – The fitted closed, stationary reduced-form result to identify.

  • impact (ArrayLike | None) – (k, k) pattern on the impact matrix, nan for a free cell and a finite value – almost always zero – for a fixed one. None fixes nothing on impact.

  • long_run (ArrayLike | None) – (k, k) pattern on the cumulated long-run matrix, same convention. Required: with nothing fixed at the long run, ShortRunSVAR is that model.

  • shock_names (Sequence[str] | None) – One label per shock column. Defaults to the variable names.

Raises:

SpecificationError – If the result is not a closed system or not stationary, the long-run pattern is omitted, a pattern is malformed, or the restriction count differs from k (k - 1) / 2.

Variables:
  • _source – The closed reduced-form result being identified.

  • _impact_cells – The fixed impact cells as (row, column, value).

  • _long_cells – The fixed long-run cells as (row, column, value).

  • _labels – The shock labels.

See also

  • SVARResult – the complete result returned.

  • LongRunSVAR – all zeros at the long run, in closed form.

  • ShortRunSVAR – all zeros on impact, with over-identification allowed.

References

Galí, J. (1999). Technology, employment, and the business cycle: Do technology shocks explain aggregate fluctuations? American Economic Review, 89(1), 249-271.

Example

Three variables, three restrictions: the technology shock alone moves productivity in the long run (two long-run zeros) and the policy shock cannot move productivity on impact (one short-run zero). The system is built with exactly those properties, and the rotation recovers the impact matrix and the shocks:

>>> import numpy as np
>>> from cultivars.multivariate.reduced_form.vector_autoregression import VAR
>>> rng = np.random.default_rng(0)
>>> A = np.array([[0.5, 0.1, 0.0], [0.0, 0.4, 0.1], [0.1, 0.0, 0.3]])
>>> F = np.array([[1.0, 0.0, 0.0], [0.5, 1.0, 0.0], [0.3, 0.2, 1.0]])
>>> B = (np.eye(3) - A) @ F
>>> eps = rng.standard_normal((802, 3))
>>> y = np.zeros((802, 3))
>>> for t in range(1, 802):
...     y[t] = A @ y[t - 1] + B @ eps[t]
>>> res = VAR(y, order=1, names=("prod", "hours", "rate")).fit()
>>> nan = np.nan
>>> model = MixedSVAR(
...     res,
...     impact=[[nan, nan, 0.0], [nan, nan, nan], [nan, nan, nan]],
...     long_run=[[nan, 0.0, 0.0], [nan, nan, nan], [nan, nan, nan]],
...     shock_names=("technology", "demand", "policy"),
... )
>>> model.n_restrictions
3
>>> svar = model.identify()
>>> svar.scheme, svar.shock_names, dict(svar.diagnostics)["Identification"]
('mixed', ('technology', 'demand', 'policy'), 'exact')
>>> svar.impact.round(2).tolist()
[[0.45, -0.09, 0.0], [0.26, 0.57, -0.05], [0.08, 0.07, 0.73]]
>>> svar.long_run_impact[0].round(2).tolist()
[1.02, 0.0, -0.0]
>>> bool(np.corrcoef(svar.structural_shocks()[:, 0], eps[1:, 0])[0, 1] > 0.95)
True

Private attributes#

Private methods#

_fixed_cells(pattern, size, label)

The declared restrictions of one pattern, as (row, column, value).