MFVARResult#

class cultivars.multivariate.reduced_form.mixed_frequency.MFVARResult(*, observed, endog, latent_cov, coefficients, deterministic, sigma_u, resid, loglikelihood, kinds, period, names, order, trend, nobs, weights=None)[source]

Bases: _SummaryMixin, _VectorPropagationMixin

The latent high-frequency path implied by a mixed-frequency sample.

The model lives at the high frequency,

\[z_t = c + \sum_{i=1}^{p} A_i\, z_{t-i} + u_t, \qquad u_t \sim N(0, \Sigma_u),\]

and a variable of kind "high" is observed as \(z_{it}\) every period, a "stock" as \(z_{it}\) at the end of each low-frequency period, and a "flow" as the weighted sum \(\sum_{j=0}^{m-1} w_j z_{i,t-j}\) over the \(m\) sub-periods ending at \(t\); every other entry of the sample is nan. With \((A, \Sigma_u, c)\) taken as given, the Kalman smoother over a state stacking \(\max(p, m)\) lags returns the conditional mean and covariance of the whole latent path given every reading in the sample, and this record is that path dressed as a VAR result.

Note

Nothing here was estimated. coefficients, sigma_u and deterministic are the inputs to MFVAR echoed back, so there are no standard errors, no information criteria and no comparison surface, and loglikelihood is the likelihood of the observed entries at those parameters – a diagnostic for comparing parameter sets, not a fit statistic. What the record does carry is the full propagation surface, because the smoothed path is complete: forecasts, impulse responses and decompositions read endog and resid exactly as a VAR result reads its data, with the caveat that resid are innovations of the smoothed path, smoother than the true innovations where a variable was not observed.

Variables:
  • observed – The mixed-frequency sample as supplied, nan preserved.

  • endog – The inferred latent path, (nobs, k) and complete. Named endog rather than smoothed_state on purpose: it is what the propagation surface consumes, so forecasting and impulse responses work here unchanged, reading the inferred path exactly as a VAR result reads its data.

  • latent_cov – Smoothed state covariances of the contemporaneous block, (nobs, k, k).

  • coefficients – The (order, k, k) coefficients used, as supplied.

  • deterministic – Deterministic coefficients, one row per term; the supplied intercept, or zero rows when there was none.

  • sigma_u – The (k, k) innovation covariance used, as supplied.

  • resid – Innovations of the inferred path over the effective sample: z_t - c - A_1 z_{t-1} - ... - A_p z_{t-p} evaluated on the smoothed path. This is what the historical decomposition and the structural shocks consume.

  • loglikelihood – Log-likelihood of the observed entries.

  • kinds – The frequency role of each variable.

  • weights – Explicit per-variable sub-period weights, when supplied.

  • period – Sub-periods per low-frequency period.

  • names – Variable labels.

  • order – Autoregressive order.

  • trend – Deterministic specification implied by the intercept.

  • nobs – Effective sample size, the rows of resid.

See also

  • MFVAR – the model whose smooth() returns this record and whose docstring records why it does not estimate.

  • MIDASVARResult – the low-frequency alternative, which is estimated.

  • VARResult – the estimated high-frequency result whose parameters MFVAR.from_result carries here.

References

Mariano, R. S., & Murasawa, Y. (2003). A new coincident index of business cycles based on monthly and quarterly series. Journal of Applied Econometrics, 18(4), 427-443.

Durbin, J., & Koopman, S. J. (2012). Time Series Analysis by State Space Methods (2nd ed.). Oxford University Press.

Example

A monthly bivariate VAR(1) in which the second variable is seen only as a quarterly average. The smoothed path recovers it to about half its standard deviation, the pointwise uncertainty is lowest in the middle month of each quarter, where both neighbours are tied to the same reading, the implied quarterly readings reproduce the ones observed, and the propagation surface runs on the inferred path:

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> A = np.array([[[0.5, 0.2], [0.1, 0.6]]])
>>> S = np.array([[1.0, 0.3], [0.3, 1.0]])
>>> z = np.zeros((240, 2))
>>> for t in range(1, 240):
...     z[t] = A[0] @ z[t - 1] + rng.multivariate_normal(np.zeros(2), S)
>>> y = z.copy()
>>> y[:, 1] = np.nan
>>> for t in range(2, 240, 3):
...     y[t, 1] = z[t - 2 : t + 1, 1].mean()
>>> res = MFVAR(A, S, kinds=["high", "flow"], period=3).smooth(y)
>>> res.endog.shape, res.nobs, res.observed_fraction.round(3)
((240, 2), 239, array([1.   , 0.333]))
>>> error = res.endog[:, 1] - z[:, 1]
>>> bool(np.sqrt(np.mean(error**2)) < 0.5 * z[:, 1].std())
True
>>> se = res.latent_stderr[:, 1]
>>> bool(se[4] < se[3]) and bool(se[4] < se[5])
True
>>> implied = res.implied_low_frequency()
>>> bool(np.allclose(implied[2::3, 1], y[2::3, 1]))
True
>>> res.forecast(2).shape, res.irf(4).shape, res.is_stable
((2, 2), (5, 2, 2), True)

Private methods#

_summary_table()

Build the structured summary.