MarkovSwitchingVARResult#
- class cultivars.multivariate.regime_switching.markov_switching.MarkovSwitchingVARResult(*, endog, names, order, trend, n_regimes, switching_mean, switching_ar, switching_variance, transition, regimes, filtered_prob, predicted_prob, smoothed_prob, ergodic_prob, expected_durations, fittedvalues, resid, llf, nobs, n_params, label_ordering, n_iter, converged)[source]
Bases:
_SummaryMixin,_ComparisonMixinA fitted Markov-switching vector autoregression.
Conditional on a latent first-order Markov chain \(S_t \in \{0, \dots, M-1\}\) with transition matrix \(P\), the panel follows
\[y_t = D_{S_t} d_t + \sum_{i=1}^{p} A_{i, S_t}\, y_{t-i} + u_t, \qquad u_t \mid S_t = m \sim N(0, \Sigma_m),\]with each of the three blocks either switching with the chain or held common across regimes. The chain is never observed: the record carries its filtered, predicted and smoothed posteriors, and every quantity that depends on the regime – fitted values, residuals, the regime a date “is in” – is an expectation under the smoothed posterior.
Note
Two consequences of the mixture form are enforced here rather than left to the reader. The likelihood is invariant to relabelling the regimes, so a sorting convention is imposed and
label_orderingnames it; without it two runs of the same model could not be compared coefficient by coefficient. And the number of regimes cannot be tested by a likelihood ratio: under the null of fewer regimes the extra regime’s parameters are unidentified and its transition probabilities lie on the boundary, solikelihood_ratio_test()refuses any comparison that changesMwhile allowing those that hold it fixed.- Variables:
endog – The observed
(n, k)panel.names – Variable labels, in column order.
order – Autoregressive order
pwithin each regime.trend –
"n","c"or"ct".n_regimes – Number of latent regimes
M.switching_mean – Whether the deterministic block switches.
switching_ar – Whether the lag coefficients switch.
switching_variance – Whether the innovation covariance switches.
transition – Row-stochastic
(M, M)matrix,transition[i, j] = Pr(S_t = j | S_{t-1} = i).regimes – One closed-system view per regime, in label order; the composition hook the structural layer consumes.
filtered_prob –
Pr(S_t = m | y_1..t), shape(nobs, M).predicted_prob –
Pr(S_t = m | y_1..t-1), shape(nobs, M).smoothed_prob –
Pr(S_t = m | y_1..T), shape(nobs, M).ergodic_prob – Stationary distribution of
transition.expected_durations –
1 / (1 - P_mm), in periods.fittedvalues –
(nobs, k)posterior-weighted one-step means.resid –
(nobs, k)residuals against those weighted means.llf – Log-likelihood from the final filter pass.
nobs – Effective sample size
n - p.n_params – Free parameters:
M (M - 1)transitions, the coefficient blocks counted once per regime that switches them, and the covariance block(s).label_ordering – Which quantity regimes were sorted by, ascending.
n_iter – EM iterations used by the refining run.
converged – Whether the refining run met its tolerance.
See also
MarkovSwitchingVAR– the model whosefit()returns this record.MarkovSwitchingSVAR– one identification scheme applied to everyregime()view.MarkovSwitchingAR– the scalar family on the same filter and smoother.TVAR– the regime computed from an observable instead of inferred.
References
Hamilton, J. D. (1990). Analysis of time series subject to changes in regime. Journal of Econometrics, 45(1-2), 39-70.
Kim, C.-J. (1994). Dynamic linear models with Markov-switching. Journal of Econometrics, 60(1-2), 1-22.
Krolzig, H.-M. (1997). Markov-Switching Vector Autoregressions. Springer. Chapters 6 and 9.
Example
Two regimes that differ in their intercepts and scales around a common lag block. EM recovers the means, the transition matrix and the regime path, and the fitted values are the smoothed-posterior mixture of the two regimes’ conditional means:
>>> import numpy as np >>> rng = np.random.default_rng(0) >>> p = np.array([[0.97, 0.03], [0.05, 0.95]]) >>> mu = np.array([[-1.0, -0.5], [1.5, 1.0]]) >>> s, y = np.zeros(600, dtype=int), np.zeros((600, 2)) >>> for t in range(1, 600): ... s[t] = np.searchsorted(np.cumsum(p[s[t - 1]]), rng.random()) ... y[t] = mu[s[t]] + 0.3 * y[t - 1] + 0.4 * rng.standard_normal(2) >>> res = MarkovSwitchingVAR(y, order=1, n_regimes=2).fit(seed=0, n_init=3) >>> res.specification, res.converged, res.nobs, res.n_params ('MSIH(2)-VAR(1)', True, 599, 16.0) >>> np.vstack([view.deterministic[0] for view in res.regimes]).round(1) array([[-1. , -0.5], [ 1.5, 1. ]]) >>> bool(np.abs(res.transition - p).max() < 0.03) True >>> bool((res.most_likely_regime == s[1:]).mean() > 0.98) True >>> mixture = sum( ... res.smoothed_prob[:, [m]] * (v.deterministic[0] + y[:-1] @ v.coefficients[0].T) ... for m, v in enumerate(res.regimes) ... ) >>> bool(np.allclose(mixture, res.fittedvalues)) True
Private methods#
Short specification label for a ranking table. |
|
|
One regime's one-step conditional means over the effective sample. |
|
Assemble the public result, building one stable view per regime. |
|
Block only the comparison that changes the number of regimes. |
Structured summary rendered by every display path. |