σμ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 3 · Wahrscheinlichkeit & Monte-Carlo-Simulation›Thema 3.10·~45 Min.Mittelstufe

Ziehen aus Verteilungen

Position in der SkillModul 3 von 11 · Thema 10 von 12
3.10 Ziehen aus Verteilungen
—Lab-Punkte— / 100XP gesamt—Serie—

Von gleichverteilt zu allem

Ein Generator liefert gleichmäßig zwischen 0 und 1 verteilte Zahlen. Ein Modell braucht andere Formen: eine Münze, die in 30 % der Fälle gewinnt, eine Wartezeit zwischen Trades, eine normale Tagesrendite. Der Trick ist immer derselbe: eine Transformation auf gleichverteilte Zahlen anwenden. Die allgemeinste ist die Inversionsmethode: Ist F die Verteilungsfunktion des Gewünschten, dann hat F⁻¹(u) für gleichverteiltes u genau diese Verteilung. Ganze Arrays durchlaufen die Transformation auf einmal.

import math
import numpy as np

# Exponential waiting times with rate 2 (a mean of 0.5): F(x) = 1 - exp(-rate * x), so x = -ln(1 - u) / rate
u = np.array([0.1, 0.5, 0.9])
print((-np.log(1 - u) / 2).round(4).tolist())       # [0.0527, 0.3466, 1.1513]   small u, short wait

rng = np.random.default_rng(42)
waits = -np.log(1 - rng.random(100000)) / 2
print(round(waits.mean(), 2))                        # 0.5   the mean is 1 / rate

Diskrete Ergebnisse und die Normalverteilung

Für eine diskrete Ergebnistabelle erledigt rng.choice(values, size=n, p=probs) die Inversion für Sie: Es zieht jeden Wert mit seiner Wahrscheinlichkeit, etwa einen Tag mit -2 %, 0 % oder +3 % bei Wahrscheinlichkeiten von 20 %, 50 % und 30 %. Bei der Normalverteilung hat die Umkehrung der Verteilungsfunktion keine einfache Formel; ein klassischer Trick ist die Box-Muller-Transformation: Aus zwei unabhängigen Gleichverteilten u1 und u2 ist z = sqrt(-2 ln u1) * cos(2 pi u2) eine standardnormale Ziehung. In der Praxis erledigt rng.standard_normal(n) das schneller, aber es einmal zu schreiben zeigt, dass es keine Magie gibt.

rng = np.random.default_rng(3)
days = rng.choice(np.array([-0.02, 0.0, 0.03]), size=100000, p=[0.2, 0.5, 0.3])
print(round(days.mean(), 3), round(0.2 * -0.02 + 0.3 * 0.03, 3))     # 0.005 0.005   the sample mean matches the table

rng = np.random.default_rng(42)
u1, u2 = 1 - rng.random(100000), rng.random(100000)                   # 1 - random() is in (0, 1]: never log(0)
z = np.sqrt(-2 * np.log(u1)) * np.cos(2 * math.pi * u2)
print(abs(z.mean()) < 0.02, round(z.std(), 2))                        # True 1.0   mean 0 and standard deviation 1

Von Normalziehungen zu Preisen

Eine standardnormale Ziehung z ist ein Schock; das Modell entscheidet, wie er einen Preis bewegt. Das übliche Aktienmodell, die geometrische Brownsche Bewegung, besagt, dass der Preis nach t Jahren S = S0 * exp((mu - 0,5 sigma²) t + sigma sqrt(t) z) ist. Er ist lognormalverteilt: immer positiv, mit dem langen rechten Rand echter Preise. Der Term -0,5 sigma² korrigiert den Mittelwert, sodass der erwartete Preis genau mit mu wächst: E[S] = S0 * exp(mu t). Der Median liegt unter dem Mittelwert, weshalb ein typisches Ergebnis schlechter ist als das durchschnittliche.

s0, mu, sigma, t = 100, 0.08, 0.2, 1
z = np.array([-1.0, 0.0, 1.0])                         # a one-sigma loss, no shock, a one-sigma gain
prices = s0 * np.exp((mu - 0.5 * sigma ** 2) * t + sigma * math.sqrt(t) * z)
print(prices.round(2).tolist())                         # [86.94, 106.18, 129.69]   all positive, the upside is larger

draws = np.random.default_rng(0).standard_normal(100000)
simulated = s0 * np.exp((mu - 0.5 * sigma ** 2) * t + sigma * math.sqrt(t) * draws)
print(round(simulated.mean(), 1), round(s0 * math.exp(mu * t), 1))     # 108.3 108.3   the mean grows at mu
print(round(float(np.median(simulated)), 1))                           # 106.1         the median is lower
# NumPy ships ready-made samplers too; the transformations above show what they do inside
z = np.random.default_rng(0).standard_normal(100000)
print(abs(z.mean()) < 0.02, round(z.std(), 2))      # True 1.0   standard_normal: mean 0, standard deviation 1
Prüfen Sie einen Sampler an dem, was Sie wissenZiehen Sie nach jedem Sampler eine große Stichprobe und vergleichen Sie Mittelwert, Standardabweichung oder eine Wahrscheinlichkeit mit dem exakten Wert: 0,5 für die Exponentialverteilung mit Rate 2, 0 und 1 für die Normalverteilung, S0 * exp(mu t) für den Preis. Ein Vorzeichenfehler oder eine vergessene Wurzel erzeugt plausibel aussehende, aber falsche Zahlen, und nur eine solche Kontrolle deckt es auf.
  • Inversionsmethode: die Umkehrfunktion der Verteilungsfunktion auf Gleichverteilte anwenden; exponentiell: -ln(1 - u) / rate.
  • rng.choice(values, size=n, p=probs) zieht aus einer diskreten Tabelle; Box-Muller sqrt(-2 ln u1) * cos(2 pi u2) erzeugt Normalziehungen.
  • Preis nach t Jahren: S0 * exp((mu - 0,5 sigma²) t + sigma sqrt(t) z), lognormal; prüfen Sie stets eine große Stichprobe gegen den exakten Mittelwert.

Als Nächstes: Monte-Carlo-Schätzung, die Zufallsziehungen nutzt, um Mittelwerte und Wahrscheinlichkeiten ohne Formel zu berechnen.

Lab: Was bewertet wird

  • Mit sample_discrete aus einer Ergebnistabelle ziehen25 Pkt.
  • Mit exponential_from_uniform die Verteilungsfunktion umkehren25 Pkt.
  • Mit box_muller glockenförmige Zahlen erzeugen25 Pkt.
  • Mit terminal_prices Schocks in künftige Preise umwandeln25 Pkt.
Explorer · lab-63-1
▾ lab-63-1
…
bash · im Browser
learner@quantcraft:~/lab-63-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

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