RSM Regime-Switching Models
Formal frameworks for markets that change their mind
Learning Objectives
- •Understand Hidden Markov Models (HMMs) for financial regime detection
- •Implement and interpret transition matrices
- •Compare HMMs to simpler regime identification methods
- •Build a practical regime-switching strategy
Explain Like I'm 5
A Hidden Markov Model assumes the market is always in one of a few hidden states, and you can't see the state directly — you can only infer it from what the market does.
Think of It This Way
Imagine you can hear someone in the next room but can't see them. By listening to the sounds they make, you infer what they're doing. HMMs do the same with market observables — you hear the returns, but the regime is hidden.
1The HMM Framework
2Transition Matrix Insights
3HMM vs. Simple Methods
4Building a Regime-Switching Strategy
5Practical Regime-Switching Insights
Key Formulas
HMM Transition Matrix
Probability of transitioning from state i to state j, with rows summing to 1
Expected Regime Duration
Expected number of periods in state i given self-transition probability p_ii
Hands-On Code
Simple Regime Detection (No Library Required)
import numpy as np
def rolling_regime_detector(returns, vol_window=60, n_regimes=3):
"""Simple regime detection using rolling stats + percentile bins."""
n = len(returns)
rolling_vol = np.array([
np.std(returns[max(0,i-vol_window):i]) * np.sqrt(252)
for i in range(vol_window, n)
])
# Classify using percentile-based boundaries
vol_pctile = np.percentile(rolling_vol, [33, 67])
regimes = []
for i in range(len(rolling_vol)):
vol = rolling_vol[i]
if vol <= vol_pctile[0]:
regime = 0 # Low volatility
elif vol >= vol_pctile[1]:
regime = 2 # High volatility
else:
regime = 1 # Normal
regimes.append(regime)
regimes = np.array(regimes)
# Compute transition matrix
transitions = np.zeros((n_regimes, n_regimes))
for i in range(len(regimes) - 1):
transitions[regimes[i], regimes[i+1]] += 1
row_sums = transitions.sum(axis=1, keepdims=True)
transition_matrix = transitions / np.maximum(row_sums, 1)
return {
'current_regime': int(regimes[-1]),
'regime_labels': ['low_vol', 'normal', 'high_vol'],
'transition_matrix': transition_matrix.round(3).tolist(),
'expected_durations': [
round(1 / (1 - transition_matrix[i,i]), 1)
for i in range(n_regimes)
]
}Implements regime detection using rolling volatility and return statistics with percentile-based boundaries, computing a transition matrix and expected regime durations.
Knowledge Check
Q1.In an HMM with self-transition probability p_ii = 0.95, the expected duration in state i is:
Q2.What is the primary practical advantage of simple indicators (Hurst, ADX) over HMMs?
Assignment
Implement a 2-state regime detector for EUR/USD using (a) a rolling Hurst + volatility approach and (b) a simple HMM (e.g., using hmmlearn). Compare the regime classifications — when do they agree? When they disagree, which was more predictive of forward 20-day returns?