5D Library › Credit Cycles, Self-Organised Criticality and the Statistical Physics of Market Phase Transitions · 中文

Chapter 4 Volatility Clustering and GARCH

Large moves follow large moves

In 1963 Mandelbrot studied changes in cotton prices and found that their distribution had much fatter tails than a normal distribution; he also noted that large changes tend to be followed by large changes (of either sign) and small changes by small changes (Mandelbrot 1963). This is volatility clustering.

Cont summed up regularities of this kind in asset returns as a set of “stylized facts”, among them: returns themselves show almost no autocorrelation (a rise today does not predict a rise tomorrow); the tails of returns are fatter than normal; and the absolute values or squares of returns show clear, slowly decaying autocorrelation, that is, volatility clustering (Cont 2001). These hold at the same time: the direction is hard to predict, but whether there will be a large move is predictable to some degree.

ARCH and GARCH

In 1982 Engle proposed the autoregressive conditional heteroscedasticity (ARCH) model (Engle 1982): today’s variance of returns depends on the squares of the last few days’ returns. He first used it to study inflation in the United Kingdom; it later became a basic tool of financial econometrics, and Engle received the 2003 Nobel Prize in Economics for the method. In 1986 Bollerslev generalised it to the GARCH model (Bollerslev 1986), most commonly GARCH(1,1):

σt2=ω+αrt−12+βσt−12,rt=σtzt\sigma_t^2 = \omega + \alpha\, r_{t-1}^2 + \beta\, \sigma_{t-1}^2, \qquad r_t = \sigma_t z_t

α\alpha measures how much yesterday’s shock affects today’s volatility and β\beta the persistence of volatility itself; the closer α+β\alpha + \beta is to 1, the more slowly a volatility shock fades. Even if ztz_t is normal, rtr_t has fat tails, because it is a mixture of many normal distributions with different variances.

Calculation

Simulate 5,000 trading days (about 20 years) of GARCH(1,1) returns with α=0.10\alpha = 0.10 and β=0.88\beta = 0.88, typical of estimates for daily stock-index returns, and a long-run daily volatility of 1 %. Then look at three things: tails and kurtosis; the autocorrelation of returns and of squared returns; and the performance of a 99 % one-day value at risk (VaR) computed from a constant-volatility normal model.

# GARCH(1,1) (Engle 1982; Bollerslev 1986): today's variance depends on yesterday's squared return
#   s2[t] = omega + alpha * r[t-1]^2 + beta * s2[t-1],   r[t] = s[t] * z[t],  z ~ N(0, 1)
# alpha = 0.10, beta = 0.88 are typical of daily stock-index estimates; omega gives a long-run daily
# sd of 1 %. Twenty simulated years (5,000 days) - not real data.
import math, random, statistics as st
rnd = random.Random(2)
a, b = 0.10, 0.88
om = 1e-4 * (1 - a - b)
s2, r, sig = 1e-4, [], []
for t in range(5000):
    s = math.sqrt(s2); x = s * rnd.gauss(0, 1)
    r.append(x); sig.append(s)
    s2 = om + a * x * x + b * s2

def acf(x, k):
    m = st.fmean(x); v = sum((u - m) ** 2 for u in x)
    return sum((x[i] - m) * (x[i + k] - m) for i in range(len(x) - k)) / v

sd = st.pstdev(r)
kurt = st.fmean([(u / sd) ** 4 for u in r]) - 3
theory = 3 * (1 - (a + b) ** 2) / (1 - (a + b) ** 2 - 2 * a * a) - 3
print(f"daily sd {sd:.2%}; excess kurtosis {kurt:.2f} (theory for these parameters {theory:.2f}; normal 0)")
print(f"autocorrelation at lag 1: returns {acf(r, 1):+.3f}, squared returns {acf([u * u for u in r], 1):+.3f};"
      f" squared returns at lag 20 {acf([u * u for u in r], 20):+.3f}")
big = sum(1 for u in r if abs(u) > 4 * sd)
print(f"days beyond 4 sd: {big}; a normal distribution predicts {5000 * math.erfc(4 / math.sqrt(2)):.2f}")
# 99 % one-day value at risk from a constant-sd normal model, estimated on the whole sample
var = 2.326 * sd
hits = [u < -var for u in r]
qs = sorted(sig); lo, hi = qs[1250], qs[3750]
rate = lambda sel: sum(h for h, s in zip(hits, sig) if sel(s)) / sum(1 for s in sig if sel(s))
print(f"constant-sd 99 % VaR = {var:.2%}: breached on {sum(hits) / 50:.2f} % of days overall,"
      f" {rate(lambda s: s >= hi):.2%} in the most volatile quarter, {rate(lambda s: s <= lo):.2%} in the calmest")
w = max(sum(hits[i:i + 20]) for i in range(len(hits) - 19))
print(f"most breaches in any 20-day window: {w} (with independent 1 % breaches, 4 or more in a given window"
      f" has probability {1 - sum(math.comb(20, k) * 0.01 ** k * 0.99 ** (20 - k) for k in range(4)):.1e})")
g = sum(1 for u, s in zip(r, sig) if u < -2.326 * s) / 50
print(f"VaR using the true GARCH sd of each day: breached on {g:.2f} % of days")
# daily sd 0.95%; excess kurtosis 1.25 (theory for these parameters 3.06; normal 0)
# autocorrelation at lag 1: returns +0.026, squared returns +0.201; squared returns at lag 20 +0.123
# days beyond 4 sd: 7; a normal distribution predicts 0.32
# constant-sd 99 % VaR = 2.21%: breached on 1.58 % of days overall, 4.72% in the most volatile quarter, 0.00% in the calmest
# most breaches in any 20-day window: 7 (with independent 1 % breaches, 4 or more in a given window has probability 4.3e-05)
# VaR using the true GARCH sd of each day: breached on 1.06 % of days
Simulated GARCH(1,1) daily returns (first 2,000 days). The dashed line is a constant 99 % value at risk computed from the full-sample standard deviation; the dots mark days on which the return fell below it, and they come in clusters during volatile periods.

The results show several things.

Fat tails. There are 7 days beyond 4 standard deviations, where a normal distribution expects 0.3.

Clustering. The lag-1 autocorrelation of returns themselves is close to zero (+0.03), while that of squared returns is about +0.20 and still about +0.12 at lag 20: the direction cannot be predicted, the size of moves partly can.

Kurtosis is hard to measure. The theoretical excess kurtosis for these parameters is about 3.1, but 20 years of simulated data measure only about 1.3. The reason is that kurtosis is determined by a very few extreme days, and 20 years contain too few of them. This is itself a consequence of fat tails: even “how fat the tails are” is hard to measure from finite data.

A constant-volatility value at risk fails just when it is needed. The 99 % VaR computed from the full-sample standard deviation is about 2.2 %. Overall it is breached on 1.58 % of days, only somewhat more than the intended 1 %, so it looks “roughly usable”; but on the most volatile quarter of days it is breached about 4.7 % of the time, and on the calmest quarter never. Breaches come in clusters: one 20-day window contains 7 of them, whereas if breaches were independent with probability 1 %, the chance of 4 or more in a given window would be about 4 in 100,000. Computing the VaR with each day’s true GARCH volatility brings the breach rate back to about 1.06 %.

Note

GARCH is not the end of the story either. A GARCH model with normal ztz_t usually still underestimates the tails of real returns, so in practice fatter-tailed shocks such as the tt distribution are often used instead; the autocorrelation of volatility in GARCH(1,1) decays exponentially, whereas in real data it often decays more slowly. Parameters estimated in calm periods may no longer apply in a crisis. The point of this section is not “use GARCH and you are safe”, but that a constant-volatility normal assumption systematically underestimates risk in turbulent periods, and the underestimation is concentrated.

Hypothesis · not established

Conditional-coverage hypothesis for risk reporting (not yet established). If risk figures shown to individual investors (for example “maximum likely loss”) are computed with constant volatility, then in periods when volatility is above its long-run average, actual losses will exceed the reported figure markedly more often than the nominal rate. This can be tested with published risk statements of funds or products and their subsequent actual performance. If the rate of exceedance in high-volatility periods does not differ from the nominal rate, the hypothesis is weakened.

Summary

The direction of asset returns is hard to predict, but the size of moves comes in clusters and the distribution has fat tails. The GARCH(1,1) model reproduces these features with very few parameters. Simulation shows that kurtosis is markedly underestimated in finite samples, and that a value at risk computed from a constant-volatility normal model looks close to its nominal level overall yet is breached frequently and in clusters during volatile periods. The next chapter looks at how the market prices these tail risks, through option prices.

References

Bollerslev, Tim. 1986. “Generalized Autoregressive Conditional Heteroskedasticity.” Journal of Econometrics 31 (3): 307–27.
Cont, Rama. 2001. “Empirical Properties of Asset Returns: Stylized Facts and Statistical Issues.” Quantitative Finance 1 (2): 223–36.
Engle, Robert F. 1982. “Autoregressive Conditional Heteroscedasticity with Estimates of the Variance of United Kingdom Inflation.” Econometrica 50 (4): 987–1007.
Mandelbrot, Benoit. 1963. “The Variation of Certain Speculative Prices.” Journal of Business 36 (4): 394–419.

Fan, Y. (2026). Credit Cycles, Self-Organised Criticality and the Statistical Physics of Market Phase Transitions: From Minsky's Financial Instability Hypothesis and Sandpile Power-Law Avalanches to Implied-Volatility Skew, Read Beside Classical Chinese Thought on Rise and Decline [信贷周期、自组织临界性与市场相变的统计物理] (Version 1.0.0). 5D Library. https://doi.org/10.5281/zenodo.23754711 · Licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0).