Free lesson · Risk
Expected shortfall and scenario risk
Open interactive lessonPractice calculationsExplore labs
Start with the idea
Expected shortfall describes the average of the worst tail fraction. Unlike a single VaR threshold, it asks how severe the tail losses are. A recovery calculation then connects any realised drawdown to the gain required to rebuild capital.
Symbols, units & horizon
- L: loss random variable, positive for a loss
- l: candidate loss threshold
- α: confidence level
- inf: smallest qualifying threshold
- VaRᵤ: loss quantile at probability u
- ES: expected shortfall, average upper-tail quantile
- ∫: integrate over probabilities α to 1
- μ_L, σ_L: mean and SD of loss
- φ (varphi): standard normal density
- Φ: standard normal cumulative probability
- Φ⁻¹: standard normal quantile
- d: fractional drawdown between 0 and 1
When and why to use this
Use ES beside VaR for tail budgeting and use recovery arithmetic to explain why deep losses constrain future growth. Both feed into liquidity and stress planning.
Average tail quantiles
- VaR is the smallest loss threshold with cumulative probability at least α. ES integrates quantiles from α to 1 and divides by their interval length 1−α.
- In an equally weighted sample with exactly k observations in that tail, ES is their arithmetic mean. Fractional boundary weight is needed if n(1−α) is not an integer.
Losses 1,2,3,4,10: the worst 40% consists of 4 and 10, so ES at 60%=7. This avoids incorrectly counting all observations tied at a boundary.
Here L is a positive loss, unlike a return or P&L. Expected shortfall averages the worst tail fraction and also handles distributions with mass at the VaR threshold. For a continuous loss distribution it equals the conditional mean beyond VaR. Historical estimates are only as representative as the observations available.
Derive normal expected shortfall
- For L=μ+σZ and z=Φ⁻¹(α), .
- The numerator is , because . Divide by tail probability 1−α.
α=.975 gives z≈1.96 and φ(z)≈.05844; multiplier=.05844/.025≈2.338. With μ=0 and σ=$1,000, ES≈$2,338.
The second formula assumes normal losses. At 97.5%, the multiplier is about 2.338, greater than the 1.960 VaR multiplier. Neither metric imposes a maximum possible loss. Examine concentration, stressed correlations, jumps and inability to trade.
Solve the required recovery return
- After drawdown d, wealth is . Recovery r must satisfy .
- Cancel E₀ and divide by 1−d: , for d<1.
A 30% drawdown needs .3/.7=42.857% growth. At a 100% loss, no finite percentage return on zero capital recovers the account.
A fractional drawdown d of 30% requires 42.86% growth to recover. There is no fixed drawdown-to-volatility ratio that holds across strategies, horizons and return distributions.
Research sources, review dates and limitations
Extend the research question
Stress collateral location as well as total portfolio P&L. Construct a path where a terminally hedged position is liquidated before convergence.
Continue with the connected research module →
Connect the ideas: Constraints and survival
Retrieve: A desired position must fit available capital and explicit limits.
Check the change: Portfolio weights, venue collateral, working orders and redemption obligations impose different constraints.
Portfolio construction → Optimization → Arbitrage → Crypto derivatives → Execution & microstructure → Fund operations & capstone
Self-assessed. Write your explanation before opening this comparison. No. Cash may be required before the hedge pays, or in another account. Check the path, collateral location and feasible transfer times.Explain it yourself: Can an offsetting terminal payoff remove a margin problem today?
Python implementation
Self-contained teaching example. Python 3.10+; dependencies and input conventions are shown in the code and notation. Run in your own Python environment.
from statistics import NormalDist
from math import floor
def empirical_es(losses, confidence=.95):
"""Exact integral of empirical quantiles, including fractional boundary mass."""
if not losses or not 0 < confidence < 1:
raise ValueError("Nonempty sample, confidence in (0,1)")
ordered = sorted(losses)
boundary = len(ordered)*confidence
index = floor(boundary)
tail_sum = (index+1-boundary)*ordered[index]+sum(ordered[index+1:])
return tail_sum/(len(ordered)*(1-confidence))
def normal_es(mean_loss, sd_loss, confidence=.95):
normal = NormalDist()
z = normal.inv_cdf(confidence)
return mean_loss+sd_loss*normal.pdf(z)/(1-confidence)
def recovery_return(drawdown):
if not 0 <= drawdown < 1:
raise ValueError("Recovery finite only for drawdown in [0,1)")
return drawdown/(1-drawdown)
print(normal_es(0, 1), recovery_return(.2))Continue learning
Risk Management — all lessons- Start with gains, losses and an ordered sample
- Value at Risk and maximum drawdown: two views of the bad days
- Sharpe ratio: return per unit of risk
- Kelly criterion: the fraction that maximises growth
- Monte Carlo: your backtest is one draw from a distribution
- Expected shortfall and scenario risk
Quantitative finance and development glossary · Python resources and libraries · Research sources and limitations