Monte Carlo · Return processes
Regime-Switching Bootstrap
regime_bootstrap
Markets do not alternate between calm and crisis at random. Turbulence arrives and then stays for months. This process fits a Markov-switching model to your portfolio's history, gives every simulated path its own regime chain, and resamples days from whichever state that path is currently in.
Why a regime layer exists
The critique is Lopez de Prado's and it is hard to argue with: a single covariance matrix estimated over two decades cannot encode the fact that the econometric relationship between assets changes. The 2008 correlation structure is not the 2017 correlation structure, and averaging them produces a matrix that describes neither.
The regime process does not estimate a global covariance matrix at all. Returns are drawn from regime-labeled historical rows, and the chain carries the dynamics: persistence, crisis clustering, and conditioning on where the market is today. Those are exactly the features a static cannot represent.
Compared with the plain block bootstrap, which treats every historical day as equally likely to be tomorrow, this adds two things: multi-month persistence of stressed conditions, and the ability to start the simulation in a chosen state.
Fitting the regimes
A Hamilton (1989) Markov-switching model with switching variance is fitted to the portfolio-level daily return series, using the same estimation machinery that already backs the HMM Regime MVO optimization method in production. The latent state follows a first-order Markov chain,
with either 2 or 3. The fit hands the sampler four things:
- Per-day regime labels from filtered probabilities. The filtering recursion at day uses observations only through day , though the parameters themselves are estimated on the full calibration sample. This is retrospective calibration, not an out-of-sample fit, and the docs say so rather than implying a live forecast.
- The transition matrix , oriented row-stochastic, whose diagonal controls how long each state persists. The implied mean duration of state is .
- Two start distributions: the filtered probabilities at the last observation, which is “today's regime” and the default, and the chain's stationary distribution.
- The bear state, identified as the highest-variance regime. Identifying by a fitted moment rather than by label sidesteps the EM label-switching ambiguity entirely.
The fit is deterministic given the data. The optimizer runs from the library default start plus a fixed set of seeded perturbed starts, and the best-likelihood converged candidate wins, so reproducibility from the echoed configuration is preserved.
Sampling inside a regime
Each path carries a latent regime advanced daily by . While the state holds, sampling advances along true calendar order inside one contiguous historical episode of that regime, with geometric block restarts as in the plain bootstrap. A block ends when any of three things happens:
- the Markov chain switches state;
- a geometric restart fires;
- the current contiguous episode of that regime ends in history.
The third condition is what keeps the process honest. Without it, a path could step from the last day of one bear episode straight to the first day of a different bear episode years later and emit them as adjacent observations. Because continuation stops at episode boundaries, two nonconsecutive historical days are never presented as consecutive. Regime persistence is carried by the Markov chain, not by splicing unrelated rows together.
As with the plain bootstrap, whole rows are sampled, so cross-asset correlation, skew and kurtosis are preserved exactly, and the sampled global row indices are reported so calendar-aligned CPI reuse still works.
Documented deviations from the plain bootstrap
Realized blocks are shorter than nominal. Blocks are truncated at episode boundaries, so in regimes made of short episodes the realized average block length falls below the nominal .
Block length is selected on the full series, not per regime. A regime's row list stitches non-contiguous historical episodes together, which corrupts the autocovariances the Politis-White selector needs, and short regimes leave too few rows for a stable estimate. The cost is one shared restart rate that may over-block a fast-mixing regime. That is an accepted v1 tradeoff, not an oversight.
No stratification and no weighted starts.First starts are drawn uniformly within the opening regime's rows, so the variance-reduction stratification does not apply and the 2008_repeat and covid_repeat window scenarios remain exclusive to block_bootstrap.
Admission checks and fallback
A regime model that has not actually found regimes is worse than no regime model, because it dresses estimation noise as structure. Six checks must pass, and the run needs at least 252 observations to attempt the fit at all. If any check fails, the engine falls back to the plain stationary bootstrap and reports the reason in the result's regime block. It never fails silently and it never presents a rejected fit as if it had succeeded.
| Check | Rejects when |
|---|---|
| Convergence | No candidate fit converged. Non-convergence is enforced, not ignored. |
| Model selection | A single-state Gaussian beats the switching model on BIC: there is no regime structure to exploit. |
| State-count parsimony | A two-state model beats a requested three-state model on BIC. |
| Label credibility | Posterior state entropy is so high that hard day-level labels are not defensible. |
| Absorbing states | A near-absorbing regime whose implied duration exceeds what the data can support. |
| Regime thickness | The thinnest regime has fewer than 60 labeled days, too few to bootstrap blocks from. |
Start-state conditioning and the bear scenario
By default every path opens from today's filtered regime probabilities. Because the model parameters were estimated on the full frozen calibration window, this is not a live out-of-sample regime forecast, and it should not be described as one. It is a statement about where the fitted model places the most recent observation.
The bear_regime_start scenario forces every path to open in the highest-variance state. This is the canonical stress test for any withdrawal plan, because sequence-of-returns risk does its damage precisely when a poor stretch lands early: selling units into a drawdown to fund withdrawals permanently removes capital that a later recovery cannot restore. That scenario is available only under this process, since no other one has a regime to force.
When to choose it
Choose it when persistence is the point. Withdrawal and retirement plans are the clearest case: what breaks them is not a single bad day but a bad stretch early in the horizon, and a process with explicit state persistence generates those stretches at a realistic rate rather than as an accident of block length.
Also choose it when you specifically want a conditional answer, either “starting from where the market is now” or, via the bear scenario, “starting from trouble”.
Prefer the plain bootstrap when you need the 2008 or COVID window stresses, when your history is under 252 rows, or when you want the fewest possible fitted parameters between your data and your answer.
References
- Hamilton, J. D. (1989). A New Approach to the Economic Analysis of Nonstationary Time Series and the Business Cycle. Econometrica, 57(2), 357–384.
- Hamilton, J. D. (1994). Time Series Analysis, Chapter 22. Princeton University Press.
- Ang, A., & Bekaert, G. (2002). International Asset Allocation with Regime Shifts. Review of Financial Studies, 15(4), 1137–1187.
- Lopez de Prado, M. (2018). Advances in Financial Machine Learning. Wiley.
See also HMM Regime MVO, which applies the same regime machinery to weight estimation rather than to forward simulation.