SetIdentifiedSVAR.identify#

SetIdentifiedSVAR.identify()[source]#

Build the identified set’s geometry and precompute its faces.

Takes the Cholesky factor of the innovation covariance, stacks the zero-restricted response rows and the sign-restricted ones out of the moving-average representation, reduces to the null space of the zeros, enumerates the face bases of the sign cone, and evaluates the impact bounds once so that an empty set surfaces here rather than at the first query.

Return type:

SetIdentifiedSVARResult

Returns:

The bounds result, with impact bounds ready in its summary and arbitrary-horizon bounds available as queries.

Raises:
  • SpecificationError – If the zero restrictions leave no direction, or the face count exceeds the enumeration cap.

  • NumericalError – If the innovation covariance is not positive definite, or the declared restrictions are infeasible – the identified set is empty at this reduced form.

Example

On a system whose responses alternate in sign, requiring one variable to rise at both leads zero and one, with the other variable’s impact pinned to zero, leaves no admissible column; and signs on a six-variable system over many horizons exceed the face cap:

>>> import numpy as np
>>> from cultivars.multivariate.reduced_form.vector_autoregression import VAR
>>> rng = np.random.default_rng(0)
>>> B = np.array([[1.0, 0.5], [0.3, 1.0]])
>>> y = np.zeros((402, 2))
>>> for t in range(1, 402):
...     y[t] = -0.5 * y[t - 1] + B @ rng.standard_normal(2)
>>> res = VAR(y, order=1, names=("gdp", "infl")).fit()
>>> feasible = SetIdentifiedSVAR(res, {"gdp": "+"}, zeros={"infl": [0]}).identify()
>>> feasible.irf(1)[:, 0, :].round(3).tolist()
[[0.816, 0.816], [-0.38, -0.38]]
>>> SetIdentifiedSVAR(
...     res, {"gdp": "+"}, zeros={"infl": [0]}, horizons=(0, 1)
... ).identify()
Traceback (most recent call last):
cultivars.exceptions.NumericalError: no rotation column satisfies the declared ...
>>> wide = VAR(rng.standard_normal((300, 6)), order=1).fit()
>>> SetIdentifiedSVAR(
...     wide, {name: "+" for name in wide.names}, horizons=tuple(range(8))
... ).identify()
Traceback (most recent call last):
cultivars.exceptions.SpecificationError: 48 sign restrictions in dimension 6 ...