edgekit

Extreme value theory

The central limit theorem governs averages, and averages are not what kill trading accounts — single worst days are. Extreme value theory is the branch of statistics built for the tail itself: it says what the distribution of maxima and threshold exceedances must look like, gives the tail a one-parameter fingerprint , and lets you estimate a 99.9% VaR from a sample that has never seen a 1-in-1000 day. This chapter builds the two limit theorems, the Hill estimator and its honesty problem, and the EVT formulas for VaR and expected shortfall.

Intuition — why the CLT says nothing about your worst day

The CLT is a statement about sums: add enough independent returns and the total is approximately normal near its centre. Convergence in the tails is agonisingly slow, and more fundamentally, your risk is not a sum — it is a maximum. “What is my worst day in the next four years?” is a question about , and the CLT is silent about it. The right question is: does the maximum, suitably rescaled, converge to anything? It does — and the answer is one of the cleanest results in probability.

Fisher–Tippett–Gnedenko: three tails, one family#

Let be i.i.d. losses and their maximum. The Fisher–Tippett–Gnedenko theorem says: if there exist normalising sequences such that converges to a non-degenerate distribution, that distribution must be the generalised extreme value (GEV) family:

with the case read as the limit . One parameter sorts every distribution into three domains of attraction:

  • Gumbel (): light, exponential-type tails — the normal and log-normal live here. Extremes exist at every size but become rare very fast.
  • Fréchet (): heavy power-law tails — Student-t, Pareto, and, empirically, financial returns. Extremes are polynomially likely; some moments are infinite.
  • Weibull (): bounded tails with a hard upper endpoint — relevant for capped payoffs, not for market losses.

This is the tail-side analogue of the CLT: just as sums forget their parent distribution and become normal, maxima forget theirs and become GEV. The parent only survives through one number, .

A normal density overlaid with a fat-tailed return distribution on log scale, the fat tail sitting orders of magnitude above the Gaussian in the extremes
Why the domain matters: on a log scale, a fat (Fréchet-domain) tail sits orders of magnitude above the Gaussian at extreme levels. A risk model that assumes xi = 0 when the data has xi > 0 is not slightly wrong in the tail — it is wrong by factors of hundreds.

Peaks over threshold and the GPD#

Fitting a GEV to block maxima (one worst day per year, say) wastes data. The modern route keeps every loss beyond a high threshold and models the excesses . The Pickands–Balkema–de Haan theorem is the licence: for any distribution in a GEV domain of attraction, as rises the conditional distribution of excesses converges to the generalised Pareto distribution (GPD),

with scale and the same shape as the GEV. So the recipe — peaks over threshold (POT) — is: pick (a high sample quantile, e.g. the 95th), collect the exceedances, fit , and you own a parametric model of the tail beyond your data.

Empirical survival function of large losses on log-log axes with a fitted generalised Pareto tail extending smoothly beyond the largest observed loss
A GPD fitted to losses beyond the 95% threshold. The fitted curve tracks the empirical tail through the data and then keeps going — a principled extrapolation to loss levels the sample never reached, which is exactly what a 99.9% VaR requires.
ξ is the tail's fingerprint — and it kills moments
For the GPD tail decays like a power law, , so moments of order are infinite. At the variance does not exist; at even the mean is gone. Equity index returns typically fit around — variance exists, but the fourth moment (kurtosis) is on the edge, which is why sample kurtosis never converges and why backtest statistics built on it are so unstable.

Block maxima or threshold exceedances?#

The two theorems suggest two workflows, and the choice is mostly settled in POT’s favour for financial data:

  • Block maxima (GEV):split the sample into blocks (years), keep each block’s worst day, fit the GEV to those maxima. Clean theory, brutal data efficiency — 8 years of daily data yields 8 observations, and the second-worst day of a bad year is discarded even if it dwarfs the worst day of a calm year.
  • Peaks over threshold (GPD): keep every loss beyond — typically 5% of the sample rather than one point per year. Same shape parameter, an order of magnitude more tail data, and a direct route to VaR via the survival-function decomposition below.

The price POT pays is the threshold choice: too low and the GPD limit has not kicked in (bias), too high and the fit starves (variance). It is the same bias-variance dial as the Hill estimator’s , and the honest response is the same — show the estimate’s sensitivity to the dial, not a single number.

The Hill estimator — and Hill-plot honesty#

For Fréchet-domain data there is a beautifully direct estimator of the tail index . Sort the losses, , take the top , and average the log-spacings:

The catch is . Small uses only the deepest tail — low bias, huge variance. Large drags in observations from the body where the power law has not kicked in — small variance, growing bias. The honest practice is the Hill plot: draw against and look for a stable plateau. If there is no plateau, the data has not told you its tail index, and reporting a single number is theatre.

Hill estimator of the tail index plotted against the number of order statistics k, volatile for small k, flattening into a plateau, then drifting as bias takes over
The Hill plot: tail-index estimate versus k. Left edge: few exceedances, wild variance. Right edge: body contamination, systematic bias. The defensible estimate is the plateau in between — and if no plateau exists, no honest point estimate does either.

EVT-VaR and expected shortfall#

The payoff of POT is closed-form tail risk. With observations, exceedances of , and a fitted , the VaR at tail probability (e.g. 0.001) and its expected shortfall are:

Derivation — VaR from the GPD survival function

For a loss , decompose the survival probability and substitute the GPD for the conditional excess:

The VaR at level is the loss whose survival probability equals . Set the right-hand side to and solve for :

For the ES, use the GPD’s mean-excess property: beyond any higher threshold the excess is again GPD with the same and scale , so the expected excess over is . Adding the VaR back and simplifying gives the ES formula — finite only when , another way the shape parameter polices which risk numbers exist.

A loss distribution with the VaR quantile marked and the expected-shortfall region shaded beyond it
VaR is a quantile of the loss distribution; ES is the average loss beyond it. Empirical estimates of both stop at the edge of the sample — EVT replaces the empirical tail with a fitted GPD so both can be evaluated past the worst observed day.

Worked scenario — extrapolating beyond the sample#

Scenario — 8 years of daily returns, and a 1-in-1000-day question

You hold daily equity returns (~8 years). The empirical 99% VaR is easy: the 20th worst day, say . Now risk asks for the 99.9% VaR — a 1-in-1000-day loss. The empirical answer would be the 2nd worst observation: a sample statistic with catastrophic variance, and by construction it can never exceed your worst day. POT instead: threshold at the 95% quantile , so exceedances; the fit gives , . Plug into the formula with :

An one-day loss — plausibly worse than anything in the sample — with . A Gaussian fitted to the same data () would have said — less than half the EVT number. The Gaussian is not conservative in the tail; it is the most optimistic model you could legally write down.

evt_var.py
import edgekit as ek

r = prices.pct_change().dropna()             # daily returns, Series

# Fit the tail: losses beyond the 95% quantile, GPD via probability-weighted moments
fit = ek.risk.gpd_fit(-r, q=0.95)
print(fit)                                   # {"xi": ..., "beta": ..., "threshold": ..., "n_exceed": ...}

# EVT-based 99.9% VaR and expected shortfall (positive loss fractions)
var999, es999 = ek.risk.evt_var_es(r, alpha=0.001, q=0.95)
print(f"VaR 99.9%: {var999:.4f}, ES 99.9%: {es999:.4f}")

# Hill tail index for the honesty check — vary k, look for the plateau
for k in (25, 50, 100, 200):
    print(k, ek.risk.hill(-r, k=k))          # alpha = 1/xi; stable region = trustworthy

Assumptions versus reality#

EVT assumesRealityConsequence
i.i.d. observationsVolatility clusters — extremes arrive in burstsEffective sample smaller; fit on residuals or accept wider error bands
Threshold u high enough for GPD limitFinite samples force a bias-variance compromiseξ estimates drift with u — report sensitivity, not one number
A stationary tailRegimes change; microstructure and leverage evolveYesterday's ξ may not govern tomorrow's crash
Enough exceedances to fit (ξ, β)The tail is, by definition, data-poorConfidence intervals on 99.9% VaR are wide — honesty requires showing them
!EVT is disciplined extrapolation, not prophecy
The theorems earn EVT its extrapolation: if the tail is in a domain of attraction, its shape beyond the sample is pinned down by . But the fit still rides on ~100 tail points, the i.i.d. assumption is wrong in the small (use GARCH-filtered residuals when it matters), and no theorem covers a mechanism change. Treat EVT-VaR the way this course treats every estimate — as a distribution, not a number — and pair it with the resampling machinery of the Monte-Carlo chapter.

Next: EVT measures the fat tail; the natural follow-up is what generates it. Jump processes and stochastic volatility are the two standard mechanisms that turn Gaussian noise into Fréchet-domain returns — and they explain the option-market smile along the way. Jumps & stochastic volatility.