σμ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 2 · NumPy & pandas für Marktdaten›Thema 2.3·~45 Min.Einsteiger

Vektorisierung

Position in der SkillModul 2 von 11 · Thema 3 von 20
2.3 Vektorisierung
—Lab-Punkte— / 100XP gesamt—Serie—

In ganzen Arrays denken, nicht in Elementen

Vektorisierung heißt, eine Rechnung als Operationen auf ganzen Arrays zu schreiben und NumPy die Schleife in schnellem kompiliertem Code ausführen zu lassen. a + b addiert zwei Arrays elementweise, a * b multipliziert sie, a ** 2 quadriert jedes Element und np.sqrt(a) zieht jede Wurzel. Das sind universelle Funktionen (ufuncs). Das Ergebnis ist kürzer zu schreiben, besser lesbar und bei großen Daten oft fünfzigmal schneller als die entsprechende Python-for-Schleife, die bei jedem einzelnen Element den Interpreter-Aufwand zahlt.

import numpy as np

a = np.array([1.0, 2.0, 3.0])
b = np.array([10.0, 20.0, 30.0])

print(a + b)             # [11. 22. 33.]
print(a * b)             # [10. 40. 90.]
print(a ** 2)            # [1. 4. 9.]
print(np.sqrt(a))        # [1.         1.41421356 1.73205081]

# The loop version of a * b, which vectorisation replaces
result = np.empty(3)
for i in range(3):
    result[i] = a[i] * b[i]
print(result)            # [10. 40. 90.]

Renditen ohne Schleife: Verschieben mit Slices

Eine Rechnung, die jedes Element mit seinem Nachbarn vergleicht, braucht eine zweite Kopie des Arrays, um eins verschoben, und Slices liefern sie gratis. p[1:] ist der heutige Preis und p[:-1] der gestrige, beide mit Länge n - 1; die einfachen Renditen sind also p[1:] / p[:-1] - 1. Dasselbe Paar liefert Differenzen (p[1:] - p[:-1] oder np.diff(p)). Laufende Summen und Produkte sind np.cumsum und np.cumprod; ein Wachstumspfad ist np.cumprod(1 + returns). Vergleiche ganzer Arrays (r > 0) und np.where(bedingung, wenn_wahr, wenn_falsch) ersetzen das if in einer Schleife.

import numpy as np

p = np.array([100.0, 102.0, 101.0, 103.0])

returns = p[1:] / p[:-1] - 1                 # today / yesterday - 1, no loop
print(np.round(returns, 4))                  # [ 0.02   -0.0098  0.0198]
print(np.diff(p))                            # [ 2. -1.  2.]
print(np.cumprod(1 + np.array([0.01, 0.02])))   # [1.01   1.0302]

# np.where replaces if/else inside a loop
r = np.array([0.01, -0.02, 0.03, -0.01])
print(np.where(r > 0, "up", "down"))         # ['up' 'down' 'up' 'down']
print(np.where(r > 0, r, 0.0))               # [0.01 0.   0.03 0.  ]

Aggregationen entlang einer Achse und Matrixprodukte

Funktionen wie sum, mean, std, min und max fassen ein Array zusammen. Bei einem 2-D-Array von Renditen (eine Zeile pro Tag, eine Spalte pro Wert) fasst axis=0 die Zeilen zusammen und liefert einen Wert pro Spalte (den Durchschnitt jedes Werts über die Zeit), axis=1 liefert einen Wert pro Zeile (den Tagesdurchschnitt über die Werte). Das Matrixprodukt R @ w eines (Tage, Werte)-Arrays mit einem Gewichtsvektor der Länge Werte ergibt die Portfoliorendite jedes Tages in einem Aufruf: das Skalarprodukt aus dem Vektorthema, für alle Zeilen auf einmal.

import numpy as np

# 2 days x 3 assets
R = np.array([[0.02, -0.01, 0.03],
              [0.01,  0.00, 0.02]])
w = np.array([0.5, 0.3, 0.2])

print(R.shape)            # (2, 3)
print(R.mean(axis=0))     # [ 0.015 -0.005  0.025]   one value per asset
print(R.sum(axis=1))      # [0.04 0.03]              one value per day
print(R @ w)              # [0.013 0.009]            portfolio return each day

# Standardise: how many standard deviations from the mean?
z = np.array([1.0, 2.0, 3.0, 4.0])
print((z - z.mean()) / z.std())   # [-1.34164079 -0.4472136   0.4472136   1.34164079]

Gleitende Mittel mit cumsum und die Grenzen der Vektorisierung

Ein gleitender Durchschnitt über ein Fenster w scheint eine Schleife zu brauchen, mit einer laufenden Summe aber nicht: Setzen Sie eine 0 vor np.cumsum(x), und die Summe beliebiger w aufeinanderfolgender Werte ist eine Differenz zweier laufender Summen, cs[w:] - cs[:-w]; durch w teilen. Das Ergebnis hat len(x) - w + 1 Werte. Vektorisieren Sie die Arithmetik, nicht Logik, die vom vorherigen Ergebnis abhängt (etwa eine Position, die von der gestrigen Ausführung abhängt): Die bleibt in einer Schleife oder wandert später zu kompilierten Werkzeugen wie Numba. Achten Sie auch auf den Speicher, denn jedes Zwischenarray ist eine volle Kopie.

import numpy as np

x = np.array([1.0, 2.0, 4.0, 8.0, 16.0])
w = 3

cs = np.concatenate(([0.0], np.cumsum(x)))   # [0, 1, 3, 7, 15, 31]
print((cs[w:] - cs[:-w]) / w)                # [2.33333333 4.66666667 9.33333333]

# Check against the plain definition
print([x[i:i + w].mean() for i in range(len(x) - w + 1)])   # three values, the same
Vektorisieren Sie, dann vergleichen Sie mit der langsamen VersionEine schnelle, aber falsche Rechnung ist schlimmer als eine langsame, richtige. Behalten Sie die naheliegende Schleifenversion, schreiben Sie die vektorisierte und vergleichen Sie beide mit np.allclose(schnell, langsam) auf Zufallsdaten, bevor Sie sich darauf verlassen. Beachten Sie auch die Ränder: ein leeres Array, ein einzelnes Element, eine konstante Reihe (Standardabweichung null, ein z-Wert teilt also durch null) und nan-Werte verlangen eine Entscheidung, keinen Absturz und keine stillschweigend falsche Zahl.
  • Operationen auf ganzen Arrays (a + b, a ** 2, np.sqrt(a)) ersetzen Schleifen; vergleichen Sie mit np.where.
  • Verschobene Slices: p[1:] / p[:-1] - 1; cumsum und cumprod für laufende Summen und Wachstum.
  • axis=0 fasst Zeilen zusammen (pro Spalte), axis=1 Spalten (pro Zeile); R @ w ist ein Skalarprodukt pro Zeile.

Als Nächstes: Broadcasting, die Regel, mit der Arrays unterschiedlicher Form zusammenarbeiten.

Lab: Was bewertet wird

  • Mit simple_returns alle Renditen auf einmal berechnen25 Pkt.
  • Mit portfolio_returns die Portfoliorendite jedes Tages berechnen25 Pkt.
  • Mit moving_average eine Reihe ohne Schleife glätten25 Pkt.
  • Mit zscore Werte standardisieren25 Pkt.
Explorer · lab-36-1
▾ lab-36-1
…
bash · im Browser
learner@quantcraft:~/lab-36-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

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