Heteroskedasticity-Based Identification
Heteroskedasticity-based SVAR identification exploits time-varying second moments to recover the structural impact matrix $B_0$ without distributional assumptions on shocks. When structural shock variances change across regimes while $B_0$ remains constant, each regime provides a separate covariance equation, generating enough restrictions to identify the structural parameters.
- Markov-switching: Hamilton (1989) filter with EM algorithm estimates regime-specific covariances endogenously
- GARCH: GARCH(1,1) conditional heteroskedasticity provides continuous time-varying identification (Normandin & Phaneuf 2004)
- Smooth transition: Logistic transition function allows gradual regime shifts (Lutkepohl & Netsunajev 2017)
- External volatility: Known regime indicators (NBER recessions, financial crises) provide the simplest sample-split approach (Rigobon 2003)
using MacroEconometricModels, Random
Random.seed!(42)<< @setup-block not executed in draft mode >>Quick Start
Recipe 1: Markov-switching identification
fred = load_example(:fred_md)
Y = to_matrix(apply_tcode(fred[:, ["INDPRO", "CPIAUCSL", "FEDFUNDS"]]))
Y = Y[all.(isfinite, eachrow(Y)), :]
model = estimate_var(Y, 2)
ms = identify_markov_switching(model; n_regimes=2)
report(ms)<< @example-block not executed in draft mode >>Recipe 2: GARCH-based identification
garch = identify_garch(model)
report(garch)<< @example-block not executed in draft mode >>Recipe 3: Smooth transition identification
# Lagged industrial production as the transition variable
s = Y[2:end, 1]
st = identify_smooth_transition(model, s)
report(st)<< @example-block not executed in draft mode >>Recipe 4: External volatility instruments
# Known regimes: split sample at midpoint
T_obs = size(model.U, 1)
regime = vcat(fill(1, T_obs ÷ 2), fill(2, T_obs - T_obs ÷ 2))
ev = identify_external_volatility(model, regime)
report(ev)<< @example-block not executed in draft mode >>Recipe 5: IRF via heteroskedasticity identification
irfs = irf(model, 20; method=:markov_switching)
report(irfs)<< @example-block not executed in draft mode >>Eigendecomposition Identification
The core insight (Rigobon 2003): when $B_0$ is constant across regimes but shock variances change, multiple covariance equations arise:
\[\Sigma_k = B_0 \Lambda_k B_0', \quad k = 1, \ldots, K\]
where:
- $\Sigma_k$ is the $n \times n$ reduced-form covariance matrix in regime $k$
- $B_0$ is the $n \times n$ structural impact matrix (constant across regimes)
- $\Lambda_k = \text{diag}(\lambda_{1k}, \ldots, \lambda_{nk})$ contains the regime-specific shock variances
Given two regime covariance matrices, the eigendecomposition of $\Sigma_1^{-1}\Sigma_2$ recovers the structural parameters:
\[\Sigma_1^{-1}\Sigma_2 = V D V^{-1}\]
where:
- $V$ contains the eigenvectors identifying the columns of $B_0$ up to scaling
- $D = \text{diag}(d_1, \ldots, d_n)$ contains the relative variance ratios $d_j = \lambda_{j2} / \lambda_{j1}$
- $B_0 = \Sigma_1^{1/2} V$ after normalization
Identification condition: The eigenvalues $d_j$ must be distinct. With $K \geq 2$ regimes providing distinct eigenvalues, $B_0$ is identified up to column permutation and sign.
The implementation uses safe_cholesky for $\Sigma_1^{1/2}$ and polar decomposition to enforce orthogonality of the rotation matrix $Q = L^{-1} B_0$. A positive-diagonal sign convention normalizes the result.
Markov-Switching Volatility
Markov-switching identification (Lanne & Lutkepohl 2008) estimates regime-specific covariance matrices via the Hamilton (1989) filter and EM algorithm. The latent state $S_t \in \{1, \ldots, K\}$ follows a first-order Markov chain with transition matrix $P$ where $P_{ij} = P(S_t = j \mid S_{t-1} = i)$.
\[f(u_t \mid S_t = k) = (2\pi)^{-n/2} |\Sigma_k|^{-1/2} \exp\!\left(-\tfrac{1}{2} u_t' \Sigma_k^{-1} u_t\right)\]
where:
- $u_t$ is the $n \times 1$ vector of reduced-form residuals
- $\Sigma_k$ is the $n \times n$ covariance matrix for regime $k$
The EM algorithm iterates:
E-step: Hamilton (1989) forward filter computes filtered probabilities $\xi_{t|t}(k)$. Kim (1994) backward smoother produces smoothed probabilities $\xi_{t|T}(k)$.
M-step: Updates regime covariances as weighted sample covariances. Updates the transition matrix using Kim (1994) joint smoothed probabilities $\xi_{t,t-1|T}(i,j)$.
The transition matrix update uses $\xi_{t,t-1|T}(i,j) = \xi_{t|T}(j) \cdot P_{ij} \cdot \xi_{t-1|t-1}(i) / \xi_{t|t-1}(j)$ rather than the naive product of marginal smoothed probabilities. This accounts for serial dependence in regime assignments and produces unbiased transition matrix estimates.
ms = identify_markov_switching(model; n_regimes=2)
report(ms)<< @example-block not executed in draft mode >>High persistence in the transition matrix diagonal indicates well-separated regimes, strengthening identification. Smoothed probabilities in ms.regime_probs reveal the timing and duration of volatility regimes.
| Keyword | Type | Default | Description |
|---|---|---|---|
n_regimes | Int | 2 | Number of volatility regimes |
max_iter | Int | 500 | Maximum EM iterations |
tol | Real | $10^{-6}$ | Convergence tolerance for log-likelihood |
Return value (MarkovSwitchingSVARResult):
| Field | Type | Description |
|---|---|---|
B0 | Matrix{T} | Structural impact matrix |
Q | Matrix{T} | Rotation matrix |
Sigma_regimes | Vector{Matrix{T}} | Covariance per regime |
Lambda | Vector{Vector{T}} | Relative variances per regime |
regime_probs | Matrix{T} | Smoothed regime probabilities ($T \times K$) |
transition_matrix | Matrix{T} | Markov transition probabilities ($K \times K$) |
loglik | T | Log-likelihood |
converged | Bool | Convergence status |
n_regimes | Int | Number of regimes |
GARCH-Based Identification
GARCH-based identification (Normandin & Phaneuf 2004) uses conditional heteroskedasticity in the structural shocks. Each shock follows a GARCH(1,1) process:
\[h_{j,t} = \omega_j + \alpha_j \varepsilon_{j,t-1}^2 + \beta_j h_{j,t-1}\]
where:
- $h_{j,t}$ is the conditional variance of shock $j$ at time $t$
- $\omega_j > 0$, $\alpha_j \geq 0$, $\beta_j \geq 0$ with $\alpha_j + \beta_j < 1$
The structural impact matrix $B_0$ is estimated by maximizing:
\[\ell(B_0) = -\frac{1}{2} \sum_{t=1}^{T} \left[ n \ln(2\pi) + \sum_{j=1}^{n} \ln h_{j,t} + \sum_{j=1}^{n} \frac{\varepsilon_{j,t}^2}{h_{j,t}} \right] + T \ln|\det(B_0^{-1})|\]
where $\varepsilon_t = B_0^{-1} u_t$ and each $h_{j,t}$ follows the GARCH recursion. The estimation iterates: (1) initialize $B_0$ from Cholesky, (2) fit GARCH(1,1) to each shock, (3) re-estimate $B_0$ via Givens rotation optimization, (4) repeat until convergence.
garch = identify_garch(model)
report(garch)<< @example-block not executed in draft mode >>Large $\alpha$ values indicate strong ARCH effects, strengthening identification. The conditional variances in garch.cond_var trace time-varying volatility per shock.
Return value (GARCHSVARResult):
| Field | Type | Description |
|---|---|---|
B0 | Matrix{T} | Structural impact matrix |
Q | Matrix{T} | Rotation matrix |
garch_params | Matrix{T} | $n \times 3$ matrix: $[\omega, \alpha, \beta]$ per shock |
cond_var | Matrix{T} | $T \times n$ conditional variances |
shocks | Matrix{T} | Structural shocks |
loglik | T | Log-likelihood |
converged | Bool | Convergence status |
Smooth Transition
Smooth-transition identification (Lutkepohl & Netsunajev 2017) allows gradual volatility shifts via a logistic transition function:
\[\Sigma_t = B_0 \bigl[I + G(s_t)(\Lambda - I)\bigr] B_0'\]
where:
- $G(s_t) = 1 / (1 + \exp(-\gamma(s_t - c)))$ is the logistic transition function
- $s_t$ is an observable transition variable
- $\gamma > 0$ controls transition speed (large $\gamma$ approximates a discrete switch)
- $c$ is the threshold location
- $\Lambda = \text{diag}(\lambda_1, \ldots, \lambda_n)$ contains relative variances in the second regime
When $G = 0$ the covariance equals $B_0 B_0'$; when $G = 1$ it equals $B_0 \Lambda B_0'$.
s = Y[2:end, 1]
st = identify_smooth_transition(model, s)
report(st)<< @example-block not executed in draft mode >>Return value (SmoothTransitionSVARResult):
| Field | Type | Description |
|---|---|---|
B0 | Matrix{T} | Structural impact matrix |
Q | Matrix{T} | Rotation matrix |
Sigma_regimes | Vector{Matrix{T}} | Covariance matrices for extreme regimes |
Lambda | Vector{Vector{T}} | Relative variances per regime |
gamma | T | Transition speed parameter |
threshold | T | Transition location parameter |
G_values | Vector{T} | Evaluated transition function $G(s_t)$ |
loglik | T | Log-likelihood |
converged | Bool | Convergence status |
External Volatility Instruments
When volatility regimes are known a priori (NBER recessions, financial crises, policy regime changes), external volatility identification (Rigobon 2003) splits the sample and estimates regime-specific covariance matrices directly. This is the simplest heteroskedasticity method –- no latent state estimation or iterative optimization.
T_obs = size(model.U, 1)
regime = vcat(fill(1, T_obs ÷ 2), fill(2, T_obs - T_obs ÷ 2))
ev = identify_external_volatility(model, regime)
report(ev)<< @example-block not executed in draft mode >>Return value (ExternalVolatilitySVARResult):
| Field | Type | Description |
|---|---|---|
B0 | Matrix{T} | Structural impact matrix |
Q | Matrix{T} | Rotation matrix |
Sigma_regimes | Vector{Matrix{T}} | Covariance per regime |
Lambda | Vector{Vector{T}} | Relative variances per regime |
regime_indices | Vector{Vector{Int}} | Observation indices per regime |
loglik | T | Log-likelihood |
Complete Example
# Step 1: Markov-switching identification
ms = identify_markov_switching(model; n_regimes=2)
report(ms)<< @example-block not executed in draft mode >># Step 2: Check convergence and regime structure
println("Converged: ", ms.converged)
println("Transition matrix:")
println(round.(ms.transition_matrix, digits=3))
# Step 3: Inspect relative variance ratios
for k in 1:ms.n_regimes
println("Regime $k variances: ", round.(ms.Lambda[k], digits=3))
end<< @example-block not executed in draft mode >># Step 4: Compare with GARCH identification
garch = identify_garch(model)
report(garch)<< @example-block not executed in draft mode >># Step 5: Structural IRFs and FEVD
irfs = irf(model, 20; method=:markov_switching)
report(irfs)<< @example-block not executed in draft mode >>decomp = fevd(model, 20; method=:markov_switching)
report(decomp)<< @example-block not executed in draft mode >>Common Pitfalls
Indistinct eigenvalues: If two shocks experience identical proportional variance changes, their columns in $B_0$ are not separately identified. Check that
ms.Lambdavectors show distinct values. Usetest_identification_strengthfrom the Identification Testing page.EM convergence to local optima: The Markov-switching EM algorithm is sensitive to initialization. If
ms.converged == false, increasemax_iteror re-run with different random seeds.Short regimes: Regime-specific covariance estimation requires at least $n + 1$ observations per regime. External volatility falls back to the full-sample covariance for undersized regimes.
GARCH stationarity: The constraint $\alpha + \beta < 1$ is enforced via log-transforms. Near-IGARCH behavior can produce boundary solutions. Inspect
garch.garch_paramsto verify interior estimates.Labeling problem: All methods identify $B_0$ up to column permutation and sign. Economic reasoning is needed to label shocks. The package normalizes by positive diagonal.
References
Rigobon, Roberto. 2003. "Identification through Heteroskedasticity." Review of Economics and Statistics 85 (4): 777–792. DOI
Lanne, Markku, and Helmut Lutkepohl. 2008. "Identifying Monetary Policy Shocks via Changes in Volatility." Journal of Money, Credit and Banking 40 (6): 1131–1149. DOI
Normandin, Michel, and Louis Phaneuf. 2004. "Monetary Policy Shocks: Testing Identification Conditions under Time-Varying Conditional Volatility." Journal of Monetary Economics 51 (6): 1217–1243. DOI
Lutkepohl, Helmut, and Aleksei Netsunajev. 2017. "Structural Vector Autoregressions with Smooth Transition in Variances." Journal of Economic Dynamics and Control 84: 43–57. DOI
Lewis, Daniel J. 2021. "Identifying Shocks via Time-Varying Volatility." Review of Economic Studies 88 (6): 3086–3124. DOI
Hamilton, James D. 1989. "A New Approach to the Economic Analysis of Nonstationary Time Series and the Business Cycle." Econometrica 57 (2): 357–384. DOI
Kim, Chang-Jin. 1994. "Dynamic Linear Models with Markov-Switching." Journal of Econometrics 60 (1–2): 1–22. DOI