Identification through heteroskedasticity¶

Vector autoregressions, Part 10: letting the volatility do the identifying¶

Every structural VAR so far bought identification with an assumption: a recursive timing zero (Part 2, Part 8a), a sign restriction (Part 8b), an external instrument or a long-run neutrality (Part 2), an elasticity bound or prior (Part 8b). Each is an economic belief imposed from outside. Rigobon (2003) showed there is a route that needs none of them: if the structural shock variances change over time while the contemporaneous structure stays put, the structure is identified by the change in volatility alone — a purely statistical identification. This closes the loop with Part 4: the stochastic volatility we modelled there as a nuisance to be captured turns out to be exactly the variation that identifies the shocks. This notebook builds it from scratch on the same monetary VAR, and uses it to test — rather than assume — the recursive ordering.

The idea¶

Write the structural VAR with impact matrix $B_0=A_0^{-1}$ and structural shocks $u_t$ of diagonal variance $D$: $$\varepsilon_t = B_0\,u_t,\qquad \operatorname{Var}(u_t)=D\ \text{diagonal}\quad\Rightarrow\quad \Sigma=\operatorname{Var}(\varepsilon_t)=B_0\,D\,B_0'.$$ A single reduced-form covariance $\Sigma$ gives $m(m{+}1)/2$ equations for the $m^2$ elements of $B_0$ (plus $D$): short by $m(m{-}1)/2$ — the reason every scheme above adds exactly that many restrictions.

Rigobon's observation. Suppose the sample splits into two volatility regimes with the same $B_0$ but different structural variances $D_1,D_2$: $$\Sigma_1=B_0 D_1 B_0',\qquad \Sigma_2=B_0 D_2 B_0'.$$ Two covariances double the equations, and now $B_0$ is identified (up to labelling and sign) with no restriction at all — provided the variance ratios on the diagonal of $D_2 D_1^{-1}$ are distinct (each shock's variance must change by a different proportion). The solution is a simultaneous diagonalisation: whiten by $\Sigma_1$ and take the eigenvectors of $\Sigma_1^{-1/2}\Sigma_2\Sigma_1^{-1/2}$; then $B_0=\Sigma_1^{1/2}W$ diagonalises both regimes at once (a generalised eigenproblem).

The link to stochastic volatility. Two regimes are the minimal case; the continuous version uses the full stochastic-volatility process of Part 4 as the identifying heteroskedasticity (Lewis 2021; Lütkepohl-Netšunajev 2017). Here we take the cleanest cut — the Great Moderation: the shock variances fell sharply around 1984, and if they fell by different amounts, that alone identifies the structural shocks. We use the Part 4 monetary system (bvar_sv_data.csv: GDP growth, inflation, the funds rate; FRED-QD, quarterly 1959–2019) and a diffuse inverse-Wishart posterior over the two regime covariances for bands.

In [1]:
import numpy as np, pandas as pd, matplotlib.pyplot as plt
import hetid as HI

d = pd.read_csv("bvar_sv_data.csv", index_col=0, parse_dates=True)
vlab = ["GDP growth", "inflation", "funds rate"]; Y = d[["gdp_growth", "inflation", "tbill"]].values
dates = d.index; p = 2; H = 20
fit = HI.fit_var(Y, p); tdates = dates[p:]
reg = np.asarray(tdates < pd.Timestamp("1984-01-01"))             # regime 1 = pre-Great-Moderation (high vol)

B0, lam = HI.rigobon(fit["resid"], reg)                          # simultaneous diagonalisation of the two regimes
Bref = HI.label(B0); chol = np.linalg.cholesky(fit["Sigma"])
print("regimes: pre-1984 n=%d, post-1984 n=%d" % (reg.sum(), (~reg).sum()))
print("structural-shock variance ratios post/pre-1984:", np.round(np.sort(lam), 2), " (distinct => identified)")
print("het-ID impact matrix (labelled):\n", np.round(Bref, 2))
print("recursive Cholesky impact:\n", np.round(chol, 2))

het, cho = HI.posterior_irf(fit, reg, H, ndraw=1500, seed=1)     # posterior het-ID vs recursive IRFs
b01 = het[:, 0, 0, 1]                                            # contemporaneous effect of the inflation shock on GDP
print("het-ID contemporaneous effect of the inflation shock on GDP: %.2f  [%.2f, %.2f]  (Cholesky imposes 0)"
      % (np.median(b01), np.percentile(b01, 16), np.percentile(b01, 84)))
# figure: het-ID vs recursive IRF of the three variables to the monetary (funds-rate) shock
shock = 2                                                        # labelled: shock 2 loads on the funds rate
q = lambda A: (np.median(A, 0), np.percentile(A, 16, 0), np.percentile(A, 84, 0))
hz = range(H + 1)
fig, ax = plt.subplots(1, 3, figsize=(14, 3.8))
for r in range(3):
    hm, hlo, hhi = q(het[:, :, r, shock]); cm, clo, chi = q(cho[:, :, r, shock])
    ax[r].fill_between(hz, hlo, hhi, color="firebrick", alpha=.15)
    ax[r].plot(hm, color="firebrick", lw=1.8, label="heteroskedasticity-ID")
    ax[r].fill_between(hz, clo, chi, color="navy", alpha=.12)
    ax[r].plot(cm, color="navy", lw=1.6, ls="--", label="recursive (Cholesky)")
    ax[r].axhline(0, color="k", lw=.5); ax[r].set_title(vlab[r] + " response", fontsize=10)
    ax[r].set_xlabel("quarters"); ax[r].grid(alpha=.25)
ax[0].legend(fontsize=8, frameon=False)
fig.suptitle("Response to the monetary (funds-rate) shock: heteroskedasticity-ID (red) vs recursive ordering (navy)", y=1.03)
fig.tight_layout(); plt.show()
regimes: pre-1984 n=97, post-1984 n=144
structural-shock variance ratios post/pre-1984: [0.11 0.26 0.44]  (distinct => identified)
het-ID impact matrix (labelled):
 [[ 3.81  1.14  0.19]
 [-0.4   1.07  0.25]
 [ 0.2   0.06  1.15]]
recursive Cholesky impact:
 [[3.05 0.   0.  ]
 [0.01 0.96 0.  ]
 [0.19 0.14 0.77]]
het-ID contemporaneous effect of the inflation shock on GDP: 1.19  [0.38, 1.97]  (Cholesky imposes 0)
No description has been provided for this image

Reading the identification¶

  • The Great Moderation identifies the model. The three structural-shock variances fell to 0.11, 0.26 and 0.44 of their pre-1984 levels — three different proportions. Because the ratios are distinct, Rigobon's condition holds and $B_0$ is identified with no economic restriction. (Had all variances fallen by the same factor, the volatility change would have been uninformative.)
  • The data reject the recursive ordering. The heteroskedasticity-identified impact matrix is not lower-triangular: the contemporaneous effect of the inflation shock on GDP growth is 1.19, with a 68% band [0.38, 1.97] that excludes zero — yet a recursive (Cholesky) scheme with output ordered first forces that element to be exactly 0. The volatility change says that timing zero is wrong. Where the recursive and heteroskedasticity-identified monetary responses (figure) diverge, it is the recursive assumption, not the data, doing the work.
  • The identified monetary shock still raises the funds rate and its dynamic effects are broadly conventional — but the contemporaneous structure the data prefer is genuinely non-recursive.
In [2]:
# The complete structural VAR, identified with NO restriction, over the inverse-Wishart posterior.
# het has shape (ndraw, H+1, 3, 3): [draw, horizon, response, shock].  -> hetid_2.png
print("full structural IRFs identified through heteroskedasticity (68% posterior bands) — see figure")

q = lambda A: (np.median(A, 0), np.percentile(A, 16, 0), np.percentile(A, 84, 0))
hz = range(H + 1)
fig, ax = plt.subplots(3, 3, figsize=(13, 8.5), sharex=True)
for r in range(3):
    for s in range(3):
        m50, l16, h84 = q(het[:, :, r, s])
        a = ax[r, s]
        a.fill_between(hz, l16, h84, color="firebrick", alpha=.15)
        a.plot(m50, color="firebrick", lw=1.5); a.axhline(0, color="k", lw=.5); a.grid(alpha=.25)
        if r == 0: a.set_title(vlab[s] + " shock", fontsize=10)
        if s == 0: a.set_ylabel(vlab[r] + " response", fontsize=9)
ax[2, 1].set_xlabel("quarters")
fig.suptitle("Structural impulse responses identified through heteroskedasticity (68% posterior bands)", y=1.005)
fig.tight_layout(); plt.show()
full structural IRFs identified through heteroskedasticity (68% posterior bands) — see figure
No description has been provided for this image

Results — identification without belief¶

  • A fourth kind of identification. Alongside recursive zeros, sign restrictions, external instruments and long-run neutrality, heteroskedasticity gives a restriction-free structural VAR: the entire $3\times3$ contemporaneous impact matrix and all impulse responses are pinned down by the statistical fact that volatility changed across regimes — no timing, sign, or elasticity assumption anywhere.
  • It turns identification into a testable question. Because the scheme imposes nothing, it can check the assumptions the other schemes impose. Here it finds the recursive ordering of the monetary VAR is not supported — the contemporaneous inflation-to-GDP link the Cholesky zeroes out is real and sizable. This is the natural, honest counterpart to the oil-market debate of Part 8b: rather than argue over which prior to hold, let the second moments identify the structure.
  • Volatility is signal, not just nuisance. Part 4 modelled the changing variances to get calibrated uncertainty; the same heteroskedasticity, it turns out, is enough to identify the shocks. The continuous version simply replaces the two Great-Moderation regimes with the full stochastic-volatility path — uniting the identification thread (Part 2) and the volatility thread (Part 4) in one estimator. The R cross-check reproduces $B_0$ from the same generalised eigenproblem.

References¶

  • Rigobon, R. (2003). Identification through heteroskedasticity. Review of Economics and Statistics 85, 777–792.
  • Rigobon, R. & Sack, B. (2004). The impact of monetary policy on asset prices. J. Monetary Economics 51, 1553–1575.
  • Lewis, D. J. (2021). Identifying shocks via time-varying volatility. Review of Economic Studies 88, 3086–3124.
  • Lütkepohl, H. & Netšunajev, A. (2017). Structural vector autoregressions with heteroskedasticity. J. Empirical Finance 42, 77–92.

Next: hetid_R.ipynb — the R cross-check (base-R generalised eigenproblem).