VECMXResult.to_varx#

VECMXResult.to_varx()[source]#

The conditional levels form this error-correction model implies.

Not to_var(), which stays unavailable: that would be a closed system and this specification has none. What is recoverable is the unit’s own equations in levels – how its variables respond to their own past and to the foreign block – and that is exactly what a global system consumes when it links units together. The distinction is the difference between “no law of motion for x” and “no equations at all”.

Splitting \(\Pi = \alpha\beta'\) and each \(\Gamma_i\) into their own and foreign columns and undoing the differencing gives

\[\Phi_1 = I + \Pi_y + \Gamma_{1,y}, \quad \Phi_i = \Gamma_{i,y} - \Gamma_{i-1,y}, \quad \Phi_p = -\Gamma_{p-1,y},\]

and the same recursion for the foreign lags with \(\Lambda_1 = \Pi_x - \Lambda_0 + \Gamma_{1,x}\), so that \(y_t = \sum_i \Phi_i y_{t-i} + \Lambda_0 x_t + \sum_i \Lambda_i x_{t-i} + \mu_t + u_t\) reproduces every fitted value exactly.

Return type:

_ConditionalLevels

Returns:

A _ConditionalLevels record with phi of shape (p, k_y, k_y), impact of (k_y, k_x) and exog_lags of (p, k_y, k_x).

Example

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> x = np.cumsum(rng.standard_normal(300))
>>> y = (x + rng.standard_normal(300))[:, None]
>>> res = VECMX(y, x[:, None], order=2, rank=1).fit()
>>> levels = res.to_varx()
>>> levels.phi.shape, levels.impact.shape, levels.exog_lags.shape
((2, 1, 1), (1, 1), (2, 1, 1))
>>> own = y[1:-1] @ levels.phi[0].T + y[:-2] @ levels.phi[1].T
>>> foreign = levels.impact[0, 0] * x[2:] + levels.exog_lags[0, 0, 0] * x[1:-1]
>>> foreign = foreign + levels.exog_lags[1, 0, 0] * x[:-2]
>>> fitted = own[:, 0] + foreign + levels.deterministic[0, 0]
>>> bool(np.allclose(y[2:, 0], fitted + res.resid[:, 0]))
True