MarkovSwitchingDFM#
- class cultivars.multivariate.regime_switching.markov_switching.MarkovSwitchingDFM(panel, *, series_names=None)[source]
Bases:
objectMarkov-switching dynamic factor model, Kim-Nelson.
One factor, AR(1) with a two-state switching intercept; estimation by maximum likelihood through the continuous-state Kim filter. A fit costs tens of seconds rather than seconds – the filter runs four Kalman updates per period inside the optimizer – which is the known price of the model and is stated rather than hidden. The panel is standardized internally and every reported parameter is on that scale.
- Variables:
_panel – The validated
(nobs, n_series)panel, unstandardized._series_names – The resolved series labels.
See also
MarkovSwitchingDFMResult– the recordfit()returns.MarkovSwitchingVAR– the switching model without the factor structure, for a handful of series.
References
Kim, C.-J., & Nelson, C. R. (1998). Business cycle turning points, a new coincident index, and tests of duration dependence based on a dynamic factor model with regime switching. Review of Economics and Statistics, 80(2), 188-201.
Chauvet, M. (1998). An econometric characterization of business cycle dynamics with factor structure and regime switching. International Economic Review, 39(4), 969-996.
Example
Three coincident indicators loading on one factor whose intercept drops in a short-lived low state. The fit recovers the factor, the chronology and the asymmetric durations; about twenty-five seconds on this panel:
>>> import numpy as np >>> rng = np.random.default_rng(0) >>> p = np.array([[0.8, 0.2], [0.05, 0.95]]) >>> s, f = np.ones(120, dtype=int), np.zeros(120) >>> for t in range(1, 120): ... s[t] = np.searchsorted(np.cumsum(p[s[t - 1]]), rng.random()) ... f[t] = [-1.5, 0.5][s[t]] + 0.6 * f[t - 1] + 0.5 * rng.standard_normal() >>> x = np.outer(f, [1.0, 0.8, 1.2]) + rng.standard_normal((120, 3)) * [0.5, 0.7, 0.6] >>> res = MarkovSwitchingDFM(x, series_names=("ip", "emp", "sales")).fit() >>> res.converged, res.n_params, bool(res.mu[0] < res.mu[1]) (True, 11, True) >>> bool(np.corrcoef(res.factor, f)[0, 1] > 0.95) True >>> bool(((res.recession_probabilities() > 0.5) == (s == 0)).mean() > 0.95) True >>> bool(res.expected_durations()[0] < res.expected_durations()[1]) True
Private attributes#
Private methods#
|
The state space a parameter vector names. |