Add Markov Switching GARCH volatility model
Summary: Introduces MS GARCH to arch.univariate, supporting multiple regimes with separate GARCH(p,q) processes per regime.
Implementation: The MS-GARCH model is implemented to closely match the structure and API of other Volatility Process models. It supports 2 regimes and is estimated via Maximum Likelihood Estimation (MLE), without MCMC fitting (for now). Starting values for the MLE are obtained via a gaussian mixture approximation of the returns. The loglikelihood is computed using the Hamilton filter to account for regime probabilities. Conditional variances at each time step are calculated as the probability weighted average of the per regime GARCH variances. One step ahead forecasting is implemented through the analytic forecast function. All model parameters are constrained to ensure positivity and stationarity where apt.
Testing: I added some basic tests to make sure the MS GARCH model runs, parameters look sensible, forecasts and variances are positive, and filtered probabilities sum to 1. Definitely open to suggestions on extra checks or better ways to test it.
Possible Improvements: During testing, the optimiser often raises a ConvergenceWarning (code 4: inequality constraints incompatible).Despite this warning, the fitted parameters and log likelihoods appear reasonable and don’t violate the constraints. I’ve investigated but haven’t pinpointed the cause, I’m open to suggestions on how to address or better understand this issue. Implementing Bayesian estimation for more robust inference. Currently limited to 2 regimes with p=q=1 chosen to provide a simple baseline model that integrates cleanly and is easy to test. This could be extended to more regimes, higher order GARCH processes, or non zero mean terms in the future. Forecasting currently returns a weighted average of the conditional volatilities across regimes. Optionally, it could allow forecasts conditional on a single regime. The GARCH recursion is the main computational bottleneck. performance could be improved with e.g. Numba or Cython.
This is my first contribution to the arch library so I’m happy to receive feedback. Thanks for maintaining such a great library, its been a great way to improve my knowledge of financial econometrics + coding! Let me know if there are any issues or you would need more for a first working version of MS GARCH functionality.
Codecov Report
:x: Patch coverage is 17.18750% with 212 lines in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 88.29%. Comparing base (6cacadd) to head (39ff059).
Additional details and impacted files
@@ Coverage Diff @@
## main #791 +/- ##
===========================================
- Coverage 99.70% 88.29% -11.41%
===========================================
Files 76 76
Lines 15740 15981 +241
Branches 1288 1303 +15
===========================================
- Hits 15694 14111 -1583
- Misses 17 1797 +1780
- Partials 29 73 +44
| Flag | Coverage Δ | |
|---|---|---|
| adder | 88.26% <17.18%> (-11.41%) |
:arrow_down: |
| subtractor | 88.26% <17.18%> (-11.41%) |
:arrow_down: |
Flags with carried forward coverage won't be shown. Click here to find out more.
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
Just following up on this PR about the MSGARCH subclass. I’m still unsure how best to handle the likelihood override. loglikelihood lives in ARCHModel, while MSGARCH is a VolatilityProcess subclass, so overriding it cleanly seems tricky.
I’m sure you're busy, but any guidance on the best approach would be much appreciated. Also, let me know if there are other fixes or improvements you’d like me to make before a full review.
Thanks!
Can you rebase on the latest main? I've changed the build system since you started this work, and it would be good to know things are up to date. I'll give it a thorough pass tomorrow.
@bashtage done, thanks!