σμ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.9·~40 Min.Mittelstufe

Zufallszahlengeneratoren und Seeds

Position in der SkillModul 3 von 11 · Thema 9 von 12
3.9 Zufallszahlengeneratoren und Seeds
—Lab-Punkte— / 100XP gesamt—Serie—

Zufällig, aber wiederholbar

Monte-Carlo-Simulation, Bootstrap und viele Tests brauchen Zufallszahlen, doch ein Ergebnis, das niemand reproduzieren kann, ist wertlos: Man kann es nicht debuggen, nicht zwei Modellversionen vergleichen und es keinem Kollegen zeigen. Die Zahlen eines Computers sind nicht wirklich zufällig. Ein Pseudozufallszahlengenerator ist ein deterministischer Algorithmus, der aus einem Anfangswert, dem Seed, eine lange Folge erzeugt, die sich wie Zufallsziehungen verhält. Gleicher Seed, gleiche Folge, jedes Mal und auf jeder Maschine.

import numpy as np

rng = np.random.default_rng(42)            # a Generator created from the seed 42
print(rng.random(3).round(4).tolist())     # [0.774, 0.4389, 0.8586]

rng = np.random.default_rng(42)            # the same seed again: the same numbers
print(rng.random(3).round(4).tolist())     # [0.774, 0.4389, 0.8586]

rng = np.random.default_rng(43)            # another seed: other numbers
print(rng.random(3).round(4).tolist())     # [0.6523, 0.0438, 0.02]

Nehmen Sie einen Generator, keinen globalen Zustand

Älterer Code ruft einmal np.random.seed(42) auf und dann irgendwo np.random.normal(...): Der gesamte Code teilt sich einen versteckten globalen Generator. Jede Bibliothek oder jede neue Zeile, die eine Zahl zieht, verschiebt die Folge aller anderen, sodass sich Ergebnisse aus Gründen ändern, die mit Ihrem Modell nichts zu tun haben. Der moderne Weg ist, mit np.random.default_rng(seed) ein Generator-Objekt zu erzeugen und es ausdrücklich weiterzureichen. Seine Methoden random, normal, choice, integers erledigen alle Ziehungen, und zwei Generatoren stören sich nie.

def simulate_returns(seed, n, mu, sigma):
    rng = np.random.default_rng(seed)              # a private generator, not the global one
    return rng.normal(mu, sigma, size=n)

first = simulate_returns(7, 5, 0.0005, 0.01)
second = simulate_returns(7, 5, 0.0005, 0.01)
print(first.round(5).tolist())                     # [0.00051, 0.00349, -0.00224, -0.00841, -0.00405]
print(np.array_equal(first, second))               # True   repeatable

Resampling und unabhängige Ströme

Ein Bootstrap zieht die Historie neu, um zu sehen, wie stark eine Kennzahl hätte schwanken können: Man zieht so viele Renditen, wie man hat, mit Zurücklegen, mit rng.choice(returns, size=len(returns), replace=True). Manche Tage erscheinen zweimal, andere gar nicht. Laufen viele Simulationen parallel, ist es riskant, jedem Prozess die Seeds 1, 2, 3 zu geben, weil benachbarte Seeds nicht garantiert unabhängig sind. np.random.SeedSequence(seed).spawn(k) leitet k Kindfolgen ab, die sich nicht überlappen sollen; bauen Sie aus jeder ein default_rng(child).

data = np.array([1, 2, 3, 4, 5])
rng = np.random.default_rng(1)
print(rng.choice(data, size=len(data), replace=True).tolist())    # [3, 3, 4, 5, 1]   3 appears twice, 2 not at all

# Three independent streams from one seed, for three parallel simulations
children = np.random.SeedSequence(2026).spawn(3)
streams = [np.random.default_rng(child) for child in children]
print([stream.random(2).round(4).tolist() for stream in streams])
# [[0.3827, 0.0204], [0.6711, 0.158], [0.5508, 0.2339]]
rng = np.random.default_rng(42)
print(rng.integers(1, 7, size=8).tolist())             # [1, 5, 4, 3, 3, 6, 1, 5]   eight dice rolls, repeatable
rng = np.random.default_rng(42)
print(rng.uniform(-0.01, 0.01, 3).round(5).tolist())   # [0.00548, -0.00122, 0.00717]
Setzen Sie den Seed bewusst und halten Sie ihn festEin fester Seed macht einen Lauf wiederholbar, ist aber keine Qualitätskontrolle: Ein Glücks-Seed kann eine schlechte Idee gut aussehen lassen. Führen Sie die Analyse mit mehreren Seeds aus und prüfen Sie, ob die Schlussfolgerung hält. Geben Sie den verwendeten Seed aus oder protokollieren Sie ihn, damit ein Berichtsergebnis stets neu erzeugt werden kann, und wählen Sie nie einen Seed, weil er eine schönere Antwort liefert.
  • rng = np.random.default_rng(seed): Derselbe Seed liefert immer dieselben Zahlen; nutzen Sie die Methoden random, normal, choice, integers.
  • Reichen Sie den Generator weiter, statt den versteckten globalen Zustand np.random.seed zu nutzen.
  • choice(..., replace=True) ist ein Bootstrap; SeedSequence(seed).spawn(k) liefert k unabhängige Ströme; protokollieren Sie den Seed.

Als Nächstes: Ziehen aus Verteilungen, gleichverteilte Zufallszahlen in normale, exponentielle und diskrete Ziehungen umwandeln.

Lab: Was bewertet wird

  • Mit make_rng einen wiederholbaren Generator erzeugen25 Pkt.
  • Mit simulate_returns reproduzierbare Renditen ziehen25 Pkt.
  • Mit bootstrap_returns die Historie neu ziehen25 Pkt.
  • Mit independent_streams einen Seed in unabhängige Ströme aufteilen25 Pkt.
Explorer · lab-62-1
▾ lab-62-1
…
bash · im Browser
learner@quantcraft:~/lab-62-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

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