Kurtosis
Kurtosis measures the tailedness of a distribution — how much probability mass is in the tails relative to a normal distribution.
Excess Kurtosis = (4th standardized moment) − 3
Normal distribution: excess kurtosis = 0 (baseline)
import numpy as np
from scipy import stats
np.random.seed(42)
n = 5000
normal = np.random.normal(0, 1, n)
t3 = np.random.standard_t(df=3, size=n) # fat tails
uniform = np.random.uniform(-3, 3, n) # thin tails
for name, data in [("Normal", normal), ("t(df=3) Fat-tail", t3), ("Uniform Thin-tail", uniform)]:
ek = stats.kurtosis(data, fisher=True) # Fisher's: normal=0
print(f"{name:<22}: Excess Kurtosis = {ek:+.4f}")
| Type | Excess Kurtosis | Shape | Example |
|---|---|---|---|
| Mesokurtic | = 0 | Normal-like | Normal distribution |
| Leptokurtic | > 0 | Fat tails, sharp peak | t-distribution, daily returns |
| Platykurtic | < 0 | Thin tails, flat peak | Uniform distribution |
Fat Tails in Finance
# Simulate daily stock returns — compare crash frequency
normal_rets = np.random.normal(0, 0.01, 2520)
fat_rets = np.random.standard_t(5, 2520) * 0.01
threshold = 0.03 # 3% daily move
print(f"Normal model >3% moves: {np.sum(np.abs(normal_rets)>threshold)}/2520")
print(f"Fat-tail model >3% moves: {np.sum(np.abs(fat_rets)>threshold)}/2520")
print("Fat tails vastly increase extreme event frequency!")
Jarque-Bera Test for Normality
# Combines skewness and kurtosis into a single normality test
for name, data in [("Normal", normal), ("t(df=3)", t3)]:
jb_stat, p = stats.jarque_bera(data)
reject = "YES — not normal" if p < 0.05 else "NO — cannot reject normality"
print(f"{name}: JB={jb_stat:.2f}, p={p:.6f} → Reject normality? {reject}")
Key Takeaways
- Excess kurtosis = 0 for normal; > 0 = fat tails; < 0 = thin tails
- Leptokurtic distributions produce more extreme outliers than normal theory predicts
- Financial returns are almost always leptokurtic — risk models must account for this
- SciPy's kurtosis() uses Fisher's definition (excess kurtosis, normal=0) by default
- Jarque-Bera test formally tests normality using both skewness and kurtosis
- Fat tails = underestimated risk — Value at Risk models using normality are dangerous