Skip to main content
QuantDXB

Data and machine learning · 12 min read

Returns, volatility and fat tails

How real returns differ from the normal distribution: extreme days far more often than predicted, and volatility that comes in clusters.

Before you start

  • How sure is an average?
  • Time series with pandas

By the end you'll be able to

  • Measure fat tails with kurtosis and tail frequencies
  • Model fat-tailed returns with the Student-t distribution
  • Detect volatility clustering with autocorrelation of absolute returns
  • Explain and simulate a GARCH(1,1) model

Many textbook models assume daily returns are independent draws from a normal distribution. Real returns break that assumption in two specific ways: extreme days happen far more often than a normal distribution allows, and calm and turbulent days come in runs. Both matter for risk, pricing and backtests. This lesson measures each one and shows the standard models for them.

TermMeaning
fat tailsExtreme values more common than under a normal distribution
kurtosisThe fourth standardised moment; 3 for a normal. Excess kurtosis subtracts 3
Student-t, ν\nuA bell-shaped distribution with fatter tails; fewer degrees ν\nu means fatter
kσk\sigma moveA move of kk standard deviations
autocorrelationCorrelation between a series and itself kk days earlier
GARCHA model in which today's variance depends on recent returns

How often is a 4σ day?

Under a normal distribution, a daily move beyond 4 standard deviations happens with probability 6.3×10−56.3 \times 10^{-5}: about once in 60 years of trading. Equity markets have had dozens of such days in recent decades, and a few beyond 10σ, which a normal distribution puts at once in many times the age of the universe. The model isn't slightly off; for extreme moves it is wrong by orders of magnitude.

The Student-t distribution is the simplest fix. It has one extra parameter, the degrees of freedom ν\nu: small ν\nu gives fat tails, and as ν→∞\nu \to \infty it becomes the normal. Rescaled to the same variance, a tt distribution puts more weight both in the centre (many quiet days) and in the tails (a few huge ones), and less in the shoulders.

Pick a distribution below. Every sample has the same standard deviation; only the shape changes.

Distribution
Days beyond 4σ
0
in 0 days
Expected in 10 years
12.1
If returns were normal
0.16
Excess kurtosis
∞
Every sample has the same volatility. What changes is the shape: with few degrees of freedom, most days are calmer than normal and a few are far wilder. A normal distribution expects a 4σ day about once in 60 years; real markets deliver several a decade.

With ν=4\nu = 4, 4σ days are about 76 times as likely as under the normal: about 12 per decade instead of one every 60 years. The log scale in the lower panel shows the gap widening the further out you look. For ν≤4\nu \le 4 the kurtosis is infinite: the fourth moment doesn't exist, and sample kurtosis never settles, however much data you collect.

Key idea. Volatility alone doesn't describe risk. Two return series with the same standard deviation can have very different chances of a catastrophic day; the tail shape is a separate, essential property.

Calm and wild days come in runs

Look at a chart of daily returns from any real market and the big days aren't spread evenly: they cluster, in crises and around news, separated by long quiet stretches. This is volatility clustering, and it coexists with returns being nearly unpredictable in direction.

Autocorrelation makes this precise. The autocorrelation of returns themselves is close to zero: yesterday's direction doesn't predict today's. The autocorrelation of their size, ∣rt∣\lvert r_t \rvert or rt2r_t^2, is clearly positive and dies away slowly over weeks: a big move today means another big move, in either direction, is more likely tomorrow.

The standard model is GARCH(1,1):

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

Today's variance is a weighted mix of a long-run level, yesterday's squared return (a shock raises volatility), and yesterday's variance (volatility persists). With α+β\alpha + \beta close to 1, as fitted values usually are, shocks take weeks to fade. The long-run variance is ω/(1−α−β)\omega / (1 - \alpha - \beta).

Returns
Autocorrelation of returns, lag 1
–
Autocorrelation of |returns|, lag 1
–
Excess kurtosis
–
Both series have the same average volatility. Under GARCH, calm and wild days come in runs: tomorrow's direction is unpredictable, but its size is not. Independent returns show neither pattern. The shaded band is ±2/√n, where noise alone would land.

Switch between GARCH and independent returns with the same average volatility. Both look like noise in direction, with returns autocorrelations inside the shaded noise band. Only GARCH shows the green bars standing well clear of it: clustering. GARCH also produces fat tails on its own, with perfectly normal shocks ZtZ_t, because mixing calm and wild periods gives more extreme days than a single normal distribution. That is why its excess kurtosis readout is positive.

Key idea. The direction of tomorrow's return is close to unpredictable; its size is not. Volatility forecasting works because volatility clusters.

In code

python
import numpy as np

rng = np.random.default_rng(11)
days = 2520 * 100  # 100 simulated decades, to measure rare events reliably

# Normal returns, and Student-t returns with 4 degrees of freedom rescaled to the same variance.
normal = rng.standard_normal(days)
t4 = rng.standard_t(4, days) / np.sqrt(4 / (4 - 2))

for name, x in (("normal", normal), ("t(4)", t4)):
    beyond = np.mean(np.abs(x) > 4) * 2520
    kurt = np.mean((x - x.mean()) ** 4) / x.var() ** 2 - 3
    print(f"{name:>6}: sd {x.std():.3f}, days beyond 4 sd per decade {beyond:5.2f}, excess kurtosis {kurt:5.1f}")

# GARCH(1,1): variance reacts to yesterday's squared return.
omega, alpha, beta = 2e-6, 0.08, 0.90
n = 5000
r = np.empty(n)
var = omega / (1 - alpha - beta)
for t in range(n):
    r[t] = np.sqrt(var) * rng.standard_normal()
    var = omega + alpha * r[t] ** 2 + beta * var

def autocorr(x, lag):
    x = x - x.mean()
    return np.sum(x[lag:] * x[:-lag]) / np.sum(x * x)

print("returns   lag 1, 5, 20:", [round(float(autocorr(r, k)), 3) for k in (1, 5, 20)])
print("|returns| lag 1, 5, 20:", [round(float(autocorr(np.abs(r), k)), 3) for k in (1, 5, 20)])

Both distributions have a standard deviation of 1.00. The normal sample has 0.18 days beyond 4σ per decade (theory 0.16); the t(4)t(4) sample has 12.36 (theory 12.1), and a sample excess kurtosis of 11.1, a number that would keep changing with more data because the true value is infinite.

For the GARCH series, the returns' autocorrelations at lags 1, 5 and 20 are −0.035-0.035, 0.0130.013 and −0.029-0.029: noise, for 5,000 days the band is about ±0.03\pm 0.03. The autocorrelations of their sizes are 0.1660.166, 0.1080.108 and 0.1070.107: clear clustering, still strong a month later.

Where this shows up in quant work

  • Risk. Value-at-risk and stress tests built on normal returns understate the chance of large losses. Risk teams use fat-tailed distributions, historical scenarios and volatility forecasts.
  • Volatility forecasting. GARCH and its relatives, and simpler versions like the EWMA in the pandas lesson, forecast tomorrow's volatility for position sizing and option pricing.
  • Options. Fat tails are why out-of-the-money options trade at higher implied volatilities than at-the-money ones (the volatility smile): the market prices extreme moves as more likely than Black–Scholes would.
  • Backtests. A strategy tested on a calm decade can look safe because the tail event never arrived. Ask how it would have done in the worst historical periods.

Exercises

  • Using the tail explorer's readouts, how much more likely is a 5σ day under t(3)t(3) than under the normal? Why does the ratio grow with kk?
  • Fit GARCH(1,1) by hand: simulate a series with known parameters, then search a grid of α\alpha and β\beta (with ω\omega set from the sample variance) for the values that maximise the normal log-likelihood. How close do you get?
  • Compute the 99% one-day value-at-risk (the loss exceeded 1% of the time) of the t(4)t(4) sample and of the normal sample. Then compare the 99.9% levels. Which gap is bigger?

Key takeaways

  • Real returns have fat tails: 4σ days happen many times more often than a normal distribution predicts. The Student-t with few degrees of freedom is a simple model of this.
  • Returns are close to uncorrelated in direction, but their sizes are strongly autocorrelated: volatility clusters.
  • GARCH(1,1) captures clustering, and produces fat tails even from normal shocks.
  • Risk measured with a normal distribution and a single volatility number understates the risk of extreme days.