σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademySkills
Ctrl K
AO
+1,2 Tsd. Lernende
AnmeldenBeitreten ↗
Skills
AO
+1,2 Tsd. Lernende
Anmelden
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Python-Skill›Modul 7 · Alpha-Forschung und Risiko›Thema 7.6·~50 Min.Fortgeschritten

Expected Shortfall

Position in der SkillModul 7 von 11 · Thema 6 von 9
7.6 Expected Shortfall
—Lab-Punkte— / 100XP gesamt—Serie—

Was der VaR nicht sagt

Ein 99-%-VaR von 3 % sagt, dass Sie an 99 von 100 Tagen weniger als 3 % verlieren. Über den 100. Tag sagt er nichts: Es können 3,1 % oder 30 % sein. Der Expected Shortfall (ES, CVaR) schließt die Lücke. Er ist der durchschnittliche Verlust an den Tagen, an denen der VaR überschritten wird, und beschreibt so die Form des Tails. Als Mittelwert ändert er sich glatt und belohnt im Gegensatz zum VaR immer Diversifikation; deshalb ging Basel beim Marktrisiko vom VaR zum ES über.

import numpy as np

rng = np.random.default_rng(5)
returns = rng.standard_t(4, size=1000) * 0.01

cutoff = np.quantile(returns, 0.05)                   # the 95% VaR is minus this
tail = np.sort(returns[returns <= cutoff])            # the worst 5% of the days, lowest first
print(len(tail), round(float(-cutoff), 5))            # 50 days; the VaR
print(np.round(tail[:4], 4))                          # the four worst days

Den Tail mitteln

Historisch ist der ES einfach: Man wählt die Renditen auf oder unter der VaR-Schwelle, mittelt sie und kehrt das Vorzeichen um. Das Ergebnis ist nie kleiner als der VaR, weil jede Tail-Rendite mindestens so schlecht ist wie die Schwelle. Das Verhältnis ES / VaR zeigt, wie schwer der Tail ist. Bei einer Normalverteilung beträgt es bei 95 % etwa 1,2, Daten mit Fat Tails zeigen meist ein größeres Verhältnis.

import numpy as np

def tail_returns(returns, confidence):
    cutoff = np.quantile(returns, 1 - confidence)
    return np.sort(returns[returns <= cutoff])

def historical_es(returns, confidence):
    return float(-tail_returns(returns, confidence).mean())

rng = np.random.default_rng(5)
returns = rng.standard_t(4, size=1000) * 0.01
for confidence in (0.95, 0.99):
    var = -np.quantile(returns, 1 - confidence)
    es = historical_es(returns, confidence)
    print(confidence, round(float(var), 5), round(es, 5), round(es / float(var), 3))

Eine Formel für den Normalfall

Für eine normalverteilte Rendite hat der Mittelwert des Tails eine geschlossene Form: ES = sigma * pdf(z) / (1 - confidence) - mu, mit dem für den VaR verwendeten Quantil z und der Standardnormaldichte pdf bei z. Die Rechnung wird zu einer Zweizeilenfunktion und ist nur bei normalen Daten exakt; der Vergleich mit dem historischen ES ist daher ein schneller Test, wie weit die Daten von der Normalität abweichen.

from statistics import NormalDist

def normal_es(mu, sigma, confidence):
    z = NormalDist().inv_cdf(confidence)
    return sigma * NormalDist().pdf(z) / (1 - confidence) - mu

for confidence in (0.95, 0.975, 0.99):
    var = NormalDist().inv_cdf(confidence)                        # in standard deviations, mu = 0
    es = normal_es(0.0, 1.0, confidence)
    print(confidence, round(var, 3), round(es, 3), round(es / var, 3))       # ES/VaR: 1.254, 1.193, 1.146
# The formula against a simulated tail
import numpy as np
from statistics import NormalDist

rng = np.random.default_rng(0)
sample = rng.normal(0.0, 0.01, size=1_000_000)
tail = sample[sample <= np.quantile(sample, 0.01)]
simulated = -tail.mean()
z = NormalDist().inv_cdf(0.99)
formula = 0.01 * NormalDist().pdf(z) / 0.01
print(round(float(simulated), 5), round(formula, 5))         # both close to 0.02665
ES lässt sich auch schwerer backtestenDen VaR prüft man durch Zählen von Überschreitungen. Der ES beruht auf den wenigen Beobachtungen im Tail: bei 99 % über 250 Tage sind das zwei oder drei Renditen. Seine Schätzung ist verrauschter und braucht mehr Daten oder ein Modell. In der Praxis werden beide zusammen berichtet: der VaR als Schwelle, der ES als Schwere dahinter.
  • ES ist der durchschnittliche Verlust im Tail jenseits des VaR: minus der Mittelwert der Renditen auf oder unter dem (1 - confidence)-Quantil.
  • Er liegt nie unter dem VaR; ES / VaR misst das Gewicht des Tails, und die Normalformel ist sigma * pdf(z) / (1 - confidence) - mu.
  • Berichten Sie den VaR als Schwelle und den ES als Schwere; der ES ist verrauschter, weil er auf wenigen Tail-Beobachtungen beruht.

Als Nächstes: Stresstests, fragen, was ein Portfolio in einem bestimmten extremen Szenario verlieren würde.

Lab: Was bewertet wird

  • Mit tail_returns die schlimmsten Tage isolieren25 Pkt.
  • Mit historical_es den Tail mitteln25 Pkt.
  • Mit normal_es per Formel bestimmen25 Pkt.
  • Mit es_var_ratio Tail und Schwelle vergleichen25 Pkt.
Explorer · lab-98-1
▾ lab-98-1
…
bash · im Browser
learner@quantcraft:~/lab-98-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

Alles in lab-98-1 wird auf die Startdateien zurückgesetzt und das Terminal geleert. Ihre aktuelle Lösung geht verloren – das lässt sich nicht rückgängig machen.

Wird zurückgesetzt
  • main.py → Startcode
  • Terminal-Verlauf und Testausgabe
  • Nicht eingereichte Änderungen
Bleibt erhalten
  • Beste Lab-Punktzahl
  • Ihre XP und Ihre Serie
  • Vorlesungsfortschritt und Notizen

Melde dich an, um deinen Code auszuführen.

Alle Lektionen kannst du kostenlos lesen. Erstelle ein Konto oder melde dich an, um Code auszuführen, Tests zu starten und dieses Lab abzugeben.

  • IDE im Browser mit Bash-Terminal — nichts zu installieren
  • Sofortige Bewertung, XP und dein Platz auf der Skill
Konto erstellenAnmelden
ODER
Weiter mit GitHub