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.
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, .

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.

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.

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:
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.

Worked scenario — extrapolating beyond the sample#
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.
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 = trustworthyAssumptions versus reality#
| EVT assumes | Reality | Consequence |
|---|---|---|
| i.i.d. observations | Volatility clusters — extremes arrive in bursts | Effective sample smaller; fit on residuals or accept wider error bands |
| Threshold u high enough for GPD limit | Finite samples force a bias-variance compromise | ξ estimates drift with u — report sensitivity, not one number |
| A stationary tail | Regimes change; microstructure and leverage evolve | Yesterday's ξ may not govern tomorrow's crash |
| Enough exceedances to fit (ξ, β) | The tail is, by definition, data-poor | Confidence intervals on 99.9% VaR are wide — honesty requires showing them |
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.



