σμ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.7·~55 Min.Fortgeschritten

Stresstests

Position in der SkillModul 7 von 11 · Thema 7 von 9
7.7 Stresstests
—Lab-Punkte— / 100XP gesamt—Serie—

„Was wäre, wenn?“ statt „wie wahrscheinlich?“ fragen

VaR und Expected Shortfall werden aus vergangenen Renditen geschätzt und sehen daher nicht, was nie passiert ist. Ein Stresstest lässt die Wahrscheinlichkeiten weg und wendet ein selbst gewähltes Szenario an: einen Aktiencrash um 20 %, einen Zinssprung um 2 Punkte, die Krise von 2008 im Replay, eine Abwertung. Der Verlust des Portfolios in diesem Szenario ist eine Zahl, die ein Risikokomitee diskutieren kann, und er zeigt Konzentrationen, die ein statistischer Mittelwert verbirgt.

import numpy as np

values = np.array([500000.0, 300000.0, -200000.0])       # two longs and a short
shocks = np.array([-0.20, -0.10, 0.15])                  # one scenario: stocks -20%, bonds -10%, the shorted stock +15%

pnl = values * shocks                                    # per position
print(pnl)                                               # [-100000.  -30000.  -30000.]  the short loses when its stock rises
print(float(pnl.sum()))                                  # -160000.0

Eine Tabelle von Szenarien

Risikoteams führen eine feste Liste von Szenarien, historische (1987, 2008, März 2020) und hypothetische. Legt man sie in eine Matrix mit einer Zeile je Szenario und einer Spalte je Position, ist der Gesamtverlust unter jedem Szenario ein einziges Matrix-Vektor-Produkt, scenarios @ values. Das Minimum dieses Vektors benennt den schlimmsten Fall, und das Szenario, das am meisten schmerzt, ist selbst eine Information, denn es zeigt, wo das Portfolio exponiert ist.

import numpy as np

values = np.array([500000.0, 300000.0, -200000.0])
scenarios = np.array([[-0.20, -0.10,  0.15],             # equity crash
                      [-0.05,  0.02,  0.00],             # mild dip
                      [ 0.10,  0.05, -0.20]])            # the shorted stock falls 20%: the short gains
names = ["equity crash", "mild dip", "rally and short gain"]

pnl = scenarios @ values
for name, p in zip(names, pnl):
    print(name, round(float(p)))
worst = int(np.argmin(pnl))
print("worst:", names[worst], round(float(pnl[worst])))
# A shock does not have to be a price move: a rate jump hits a bond through its duration
duration = 7.5                                    # years, from the duration topic
bond_value = 1_000_000.0
rate_jump = 0.02                                  # +2 percentage points
print(round(bond_value * (-duration * rate_jump)))   # -150000   the shock expressed as a price return of -15%

Der umgekehrte Stresstest

Man dreht die Frage um: Wie schlimm müsste ein Schock sein, um einen gegebenen Betrag zu kosten, etwa den Kapitalpuffer? Man nimmt eine Schockrichtung (etwa alles fällt gemeinsam) und skaliert sie mit einem Faktor k. Der Verlust ist -k * (values @ direction), linear in k, der Faktor mit genau loss_limit Verlust ist also loss_limit / -(values @ direction). Verliert die Richtung kein Geld, erreicht kein Faktor je die Grenze.

import numpy as np

def reverse_stress(values, direction, loss_limit):
    change = float(values @ direction)
    if change >= 0:
        return float("inf")
    return loss_limit / -change

values = np.array([500000.0, 300000.0, -200000.0])
direction = np.array([-1.0, -1.0, 0.0])                    # the two longs fall by the same percentage
k = reverse_stress(values, direction, 100000.0)
print(round(k, 4))                                          # 0.125  a 12.5% fall in both longs loses 100,000
print(round(float(-(values @ (k * direction))), 2))         # 100000.0
Ein Szenario ist nur so gut wie Ihre FantasieSchwierig ist, Szenarien zu wählen, die streng und doch plausibel sind und korrelierte Assets wie in einer Krise gemeinsam bewegen. Das Ergebnis ist außerdem eine Punktschätzung ohne Wahrscheinlichkeit: Eine schlechte Zahl ist ein Grund, die Position anzusehen, eine gute beweist nichts über Szenarien, an die man nicht gedacht hat. Stresstests ergänzen den VaR, sie ersetzen ihn nicht.
  • Ein Stresstest wendet gewählte Schocks an: Der PnL einer Position ist values * shocks, negativ bei Verlusten und positiv für den Short, der gewinnt.
  • Viele Szenarien auf einmal sind ein Produkt, scenarios @ values; das Minimum benennt den schlimmsten Fall und zeigt, wo das Portfolio exponiert ist.
  • Umgekehrter Stress: Das Vielfache eines Schocks, das genau das Limit verliert, ist loss_limit / -(values @ direction), oder unendlich, wenn die Richtung nie verliert.

Als Nächstes: ARIMA-Modelle, eine Reihe aus ihrer eigenen Vergangenheit vorhersagen.

Lab: Was bewertet wird

  • Mit shocked_pnl jede Position treffen25 Pkt.
  • Mit scenario_pnl viele Szenarien auf einmal rechnen25 Pkt.
  • Mit worst_scenario den schlimmsten Fall benennen25 Pkt.
  • Mit reverse_stress von einem Verlust zurückrechnen25 Pkt.
Explorer · lab-99-1
▾ lab-99-1
…
bash · im Browser
learner@quantcraft:~/lab-99-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

Alles in lab-99-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