cultivars.multivariate.structural#

Structural identification: what the data cannot supply, declared or tested.

A fitted closed system delivers its innovation covariance \(\Sigma_u\) and nothing more about the shocks behind it; every factorization \(\Sigma_u = B B'\) is a different economic story, and choosing one is the whole of structural analysis. Each module here is one way of choosing, and the package is organized by where the identifying information comes from. Declared zeros are zero_restrictions – a causal ordering on impact, an ordering of permanence at the long run, an AB pattern anywhere, or zeros split across the two horizons – and they point-identify. Declared signs are sign_restrictions and set_identification: they set-identify, and the two modules report the set honestly in two different ways, sampled under a named prior or bounded exactly with none. Outside series are external_instruments, a proxy that identifies one column and reports its own strength. Statistical properties of the shocks are heteroskedacity, stochastic_volatility and non_gaussian – declared variance regimes, estimated variance paths, and independence with non-Gaussianity – which identify without any economic restriction and return shocks labelled by statistics, never by economics. A larger information set is factor_augmented, the FAVAR, where the structural shock propagates through a panel. And a model is perturbation, where the structure is a DSGE solved to first or second order and estimated by likelihood, rather than restrictions laid over a reduced form.

Every scheme that point-identifies returns the one SVARResult, with exactly as many shock columns as it identified and the identifying assumption restated in its summary; every scheme that set-identifies returns the set itself, as draws or as bounds; every scheme whose identification is a statistical condition tests that condition on the data and prints the verdict, because the posterior or the point estimate alone cannot certify it. The package re-exports modules only: import a scheme from its module.

Example

>>> import numpy as np
>>> from cultivars.multivariate.reduced_form.vector_autoregression import VAR
>>> from cultivars.multivariate.structural import zero_restrictions, sign_restrictions
>>> rng = np.random.default_rng(0)
>>> B = np.array([[1.0, 0.0], [0.5, 1.0]])
>>> y = np.zeros((402, 2))
>>> for t in range(1, 402):
...     y[t] = 0.4 * y[t - 1] + B @ rng.standard_normal(2)
>>> res = VAR(y, order=1, names=("r", "x")).fit()
>>> point = zero_restrictions.RecursiveSVAR(res).identify()
>>> point.scheme, point.is_complete, point.impact.round(2).tolist()
('recursive', True, [[1.0, 0.0], [0.5, 1.0]])
>>> signs = {"demand": {"r": "+", "x": "+"}}
>>> sset = sign_restrictions.SignRestrictedSVAR(res, signs, draws=100, seed=0).identify()
>>> sset.n_accepted, sset.shock_names
(100, ('demand', 'unrestricted1'))

Modules#

external_instruments

External-instrument identification: one shock, named from outside the system.

factor_augmented

Structural identification on a factor block: one shock, hundreds of answers.

heteroskedacity

Identification through heteroskedasticity: the data identify, the user labels.

non_gaussian

Non-Gaussian identification: independence does what zeros used to.

perturbation

Likelihood estimation of perturbation-solved DSGE models.

set_identification

Set identification: the bounds of the set, not a prior's summary of it.

sign_restrictions

Sign-restriction identification: a set of models, reported as a set.

stochastic_volatility

Identification through stochastic volatility: the regimes nobody has to declare.

zero_restrictions

Zero-restriction identification: triangularity on impact or in the long run.