σμ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.8·~1 Std.Fortgeschritten

scikit-learn-Pipelines für Renditen

Position in der SkillModul 8 von 11 · Thema 8 von 10
8.8 scikit-learn-Pipelines für Renditen
—Lab-Punkte— / 100XP gesamt—Serie—

Maschinelles Lernen auf Renditen

Überwachtes Lernen passt eine Funktion von Merkmalen X an ein Ziel y an. In der Finanzwelt ist das Ziel meist eine künftige Rendite, und die Merkmale sind vorher Bekanntes: vergangene Renditen, Volatilität, Volumen. scikit-learn bietet eine einheitliche Schnittstelle: Jedes Modell hat fit(X, y) und predict(X). Ein wesentlicher Unterschied zu Lehrbuchproblemen ist das Signal-Rausch-Verhältnis: Renditen sind fast reines Rauschen, selbst ein gutes Modell erklärt nur einen Bruchteil, und ein nachlässiger Aufbau findet Muster, die es nicht gibt.

import numpy as np

returns = np.array([0.01, -0.02, 0.015, 0.005, -0.01, 0.02])
n_lags = 2

# Row i holds the two returns before the target; y[i] is the return that follows them
windows = np.lib.stride_tricks.sliding_window_view(returns, n_lags)
X, y = windows[:-1], returns[n_lags:]
print(X)
print(y)                                             # the targets are one step ahead of the features

Merkmale aus Lags

Die einfachsten Merkmale einer Rendite sind die Renditen davor. Bauen Sie eine Lag-Matrix: Zeile i enthält returns[i : i + n_lags], das Ziel ist returns[i + n_lags], der nächste Wert. Eine Sliding-Window-Ansicht liefert sie ohne Schleife. Alles in einer Zeile muss zum Prognosezeitpunkt bekannt sein, die Look-ahead-Regel auf ein Modell angewandt: Ein um eine Position falsch verschobenes Merkmal ließe das Modell die Antwort sehen.

import numpy as np
from sklearn.linear_model import Ridge
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

# Pipeline: scale each feature, then a ridge regression (a linear model with a penalty on large coefficients)
pipe = Pipeline([("scale", StandardScaler()), ("model", Ridge(alpha=10.0))])
print([name for name, _ in pipe.steps])

rng = np.random.default_rng(1)
returns = np.zeros(400)
noise = rng.normal(0, 0.01, size=400)
for t in range(1, 400):
    returns[t] = 0.3 * returns[t - 1] + noise[t]                    # a series with a little memory

windows = np.lib.stride_tricks.sliding_window_view(returns, 3)
X, y = windows[:-1], returns[3:]
pipe.fit(X[:300], y[:300])                                          # fit on the first 300 rows
print(np.round(pipe.named_steps["model"].coef_, 4))                 # the last lag weighs most

Pipelines und Datenleck

Eine Pipeline bündelt Skalierer und Modell, sodass fit die Skalierungsstatistiken (Mittel und Standardabweichung jedes Merkmals) nur aus den Trainingszeilen lernt und predict sie unverändert auf neue Zeilen anwendet. Würde man erst den ganzen Datensatz skalieren und dann teilen, flössen Mittel und Streuung der Testperiode ins Training: derselbe Look-ahead-Bias an neuer Stelle. Bei Zeitreihen ist die Teilung außerdem chronologisch: auf frühen Zeilen trainieren, auf späteren testen, nie zufällig mischen.

import numpy as np
from sklearn.linear_model import Ridge
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

def build_pipeline(alpha):
    return Pipeline([("scale", StandardScaler()), ("model", Ridge(alpha=alpha))])

rng = np.random.default_rng(1)
returns = np.zeros(600)
noise = rng.normal(0, 0.01, size=600)
for t in range(1, 600):
    returns[t] = 0.3 * returns[t - 1] + noise[t]

windows = np.lib.stride_tricks.sliding_window_view(returns, 3)
X, y = windows[:-1], returns[3:]
model = build_pipeline(10.0).fit(X[:400], y[:400])                  # chronological split: early rows to train
pred = model.predict(X[400:])                                       # later rows to test
print(round(float(np.mean(np.sign(y[400:]) == np.sign(pred))), 3))  # direction accuracy on unseen data

Das Ergebnis ehrlich beurteilen

Bei einem Handelssignal zählt oft die Richtung, ein einfaches Maß ist daher die Richtungstrefferquote: der Anteil der Tage, an denen vorhergesagte und tatsächliche Rendite dasselbe Vorzeichen haben. 50 % ist Münzwurf. Echte Renditeprädiktoren erreichen 51 bis 53 %, und 60 % auf Testdaten sind eher ein Leck als eine Entdeckung. Vergleichen Sie mit den trivialen Basislinien (immer steigend vorhersagen, null vorhersagen), bevor Sie etwas glauben.

import numpy as np

y_true = np.array([0.01, -0.02, 0.015, -0.005, 0.02, -0.01])
y_pred = np.array([0.004, 0.001, 0.002, -0.001, 0.003, 0.002])        # the model is right on 4 of 6 signs

accuracy = float(np.mean(np.sign(y_true) == np.sign(y_pred)))
always_up = float(np.mean(np.sign(y_true) == 1))                      # the trivial baseline: always predict a rise
print(round(accuracy, 3), round(always_up, 3))                        # compare the model with the baseline
Einfache Modelle, ehrliche ValidierungBei so viel Rauschen schlagen regularisierte lineare Modelle (Ridge, Lasso) meist flexible wie tiefe Bäume oder neuronale Netze, die den Trainingszeitraum auswendig lernen. Die Strafe alpha ist ein Regler zum Einstellen, aber auf einem Validierungszeitraum, nie auf dem Testzeitraum. Die nächsten Themen bauen die Merkmale und das Walk-forward-Testen, die das ehrlich machen.
  • Eine Lag-Matrix (sliding_window_view) liefert Merkmale aus den Renditen vor jedem Ziel; alles in einer Zeile muss zum Prognosezeitpunkt bekannt sein.
  • Eine Pipeline([("scale", StandardScaler()), ("model", Ridge(alpha=alpha))]) lernt die Skalierung nur auf den Trainingszeilen; chronologisch teilen, nie zufällig.
  • Bewerten Sie die Richtung (Anteil gleicher Vorzeichen) gegen triviale Basislinien; 51 bis 53 % sind realistisch, 60 % deuten auf ein Leck; regularisierte lineare Modelle passen zu verrauschten Daten.

Als Nächstes: Feature Engineering für Finanzdaten, bessere Eingaben als rohe verzögerte Renditen bauen.

Lab: Was bewertet wird

  • Mit lag_matrix eine Reihe in Merkmale umwandeln25 Pkt.
  • Mit build_pipeline die Schritte verketten25 Pkt.
  • Mit fit_predict an der Vergangenheit trainieren, den Rest vorhersagen25 Pkt.
  • Mit direction_accuracy die Richtungen bewerten25 Pkt.
Explorer · lab-109-1
▾ lab-109-1
…
bash · im Browser
learner@quantcraft:~/lab-109-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

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