σμ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 8 · Stochastische Modelle und Machine Learning›Thema 8.7·~50 Min.Fortgeschritten

Kontrollvariablen

Position in der SkillModul 8 von 11 · Thema 7 von 10
8.7 Kontrollvariablen
—Lab-Punkte— / 100XP gesamt—Serie—

Nutzen, was man schon weiß

Beim Simulieren eines Calls simuliert man auch den Aktienkurs bei Verfall S_T, dessen wahren Mittelwert S0 * exp(r * T) man genau kennt. In der Stichprobe kam der Mittelwert von S_T etwas daneben heraus, sagen wir zu hoch. Da Call-Auszahlung und S_T zusammen laufen, ist auch der Stichprobenmittelwert des Calls wahrscheinlich zu hoch. Eine Kontrollvariable nutzt das: Sie zieht von der Schätzung der gesuchten Größe ein Vielfaches des beobachteten Fehlers der bekannten Größe ab.

import numpy as np

rng = np.random.default_rng(1)
z = rng.standard_normal(2000)
s_t = 100.0 * np.exp((0.05 - 0.5 * 0.2 ** 2) + 0.2 * z)             # terminal prices
call = np.maximum(s_t - 100.0, 0.0)                                  # the payoff we want

known = 100.0 * np.exp(0.05)                                         # E[S_T], exactly
print(round(float(s_t.mean()), 3), round(known, 3))                  # the sample mean of S_T vs its true mean
print(round(float(s_t.mean() - known), 3))                           # the observed error of the control

Das beste Vielfache

Wie viel vom Fehler der Kontrolle sollte man abziehen? Das Vielfache b, das die Varianz von payoff - b * control minimiert, ist b = cov(payoff, control) / var(control), genau die Steigung der Regression der Auszahlung auf die Kontrolle (dieselben Summen wie das Beta im CAPM-Thema). Die kontrollierte Schätzung ist mean(payoff) - b * (mean(control) - known_mean). Sie ist unverzerrt, weil der abgezogene Term den Erwartungswert null hat.

import numpy as np

def control_coefficient(payoff, control):
    dev = control - control.mean()
    return float(np.sum(dev * (payoff - payoff.mean())) / np.sum(dev ** 2))

rng = np.random.default_rng(1)
z = rng.standard_normal(2000)
s_t = 100.0 * np.exp((0.05 - 0.5 * 0.2 ** 2) + 0.2 * z)
call = np.maximum(s_t - 100.0, 0.0)
known = 100.0 * np.exp(0.05)

b = control_coefficient(call, s_t)
controlled = call.mean() - b * (s_t.mean() - known)
print(round(b, 4), round(float(call.mean()), 4), round(float(controlled), 4))       # the plain mean and the corrected one
# A payoff that is exactly proportional to the control is estimated without any error
import numpy as np

x = np.random.default_rng(2).standard_normal(50) + 5.0          # the control, known mean 5.0
y = 2.0 * x                                                      # the payoff
dev = x - x.mean()
b = np.sum(dev * (y - y.mean())) / np.sum(dev ** 2)
print(round(float(b), 6), round(float(y.mean() - b * (x.mean() - 5.0)), 6))      # 2.0 and exactly 10.0

Wie viel Fehler gespart wird

Die angepassten Stichproben payoff - b * control tragen das Rauschen, der Standardfehler der kontrollierten Schätzung ist also ihre Standardabweichung (ddof=1) durch sqrt(n). Bei Korrelation rho zwischen Auszahlung und Kontrolle sinkt die Varianz um den Faktor 1 - rho^2: Eine Korrelation von 0,9 beseitigt 81 %, 0,99 beseitigt 98 %. Die Kontrolle kostet keine zusätzliche Simulation, nur ein paar Zeilen mehr.

import numpy as np

def control_variate_error(payoff, control):
    dev = control - control.mean()
    b = np.sum(dev * (payoff - payoff.mean())) / np.sum(dev ** 2)
    return float((payoff - b * control).std(ddof=1) / np.sqrt(len(payoff)))

rng = np.random.default_rng(1)
z = rng.standard_normal(20000)
s_t = 100.0 * np.exp((0.05 - 0.5 * 0.2 ** 2) + 0.2 * z)
for strike in (80.0, 100.0, 120.0):
    call = np.maximum(s_t - strike, 0.0)
    plain = float(call.std(ddof=1) / np.sqrt(len(call)))
    print(strike, round(plain, 4), round(control_variate_error(call, s_t), 4), round(plain / control_variate_error(call, s_t), 2))
Eine gute Kontrolle ist korreliert und bekanntBeide Bedingungen zählen. Die Kontrolle muss sich mit der Auszahlung bewegen (sonst ist b nahe 0 und nichts gewonnen), und ihr exakter Mittelwert muss bekannt sein (sonst ist die Korrektur geraten). Gute Kontrollen für den arithmetischen Durchschnitt einer asiatischen Option sind der geometrische Durchschnitt, dessen Preis eine Formel hat, oder der Endkurs selbst. Man kann mehrere Kontrollen gleichzeitig nutzen, die Koeffizienten stammen dann aus einer multiplen Regression.
  • Eine Kontrollvariable ist eine simulierte Größe mit bekanntem Mittelwert; von der Schätzung zieht man ein Vielfaches ihres beobachteten Fehlers ab: mean(Y) - b * (mean(X) - E[X]).
  • Das beste Vielfache ist die Regressionssteigung b = cov(Y, X) / var(X); der Fehler ist die Standardabweichung von Y - b * X durch sqrt(n).
  • Die Varianz sinkt um den Faktor 1 - rho^2; eine gute Kontrolle ist stark mit der Auszahlung korreliert, hat einen exakt bekannten Mittelwert und kostet keine zusätzliche Simulation.

Als Nächstes: scikit-learn-Pipelines für Renditen, Vorhersagemodelle auf Renditedaten anpassen und bewerten.

Lab: Was bewertet wird

  • Mit control_coefficient das richtige Vielfache wählen25 Pkt.
  • Mit control_variate_estimate die Schätzung korrigieren25 Pkt.
  • Mit control_variate_error den Fehlerbalken verkleinern25 Pkt.
  • Mit error_reduction den Gewinn beziffern25 Pkt.
Explorer · lab-108-1
▾ lab-108-1
…
bash · im Browser
learner@quantcraft:~/lab-108-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

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