σμ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.4·~45 Min.Mittelstufe

Hypothesentests: der t-Test

Position in der SkillModul 3 von 11 · Thema 4 von 12
3.4 Hypothesentests: der t-Test
—Lab-Punkte— / 100XP gesamt—Serie—

Ist die Durchschnittsrendite echt?

Ein Backtest zeigt eine Durchschnittsrendite von +0,14 % pro Tag. Ist die Strategie gut, oder hatte sie Glück? Renditen sind verrauscht, jede Stichprobe hat also einen Mittelwert, und selbst eine Münzwurf-Strategie hat in der Hälfte der Fälle einen positiven. Ein Hypothesentest stellt eine präzise Frage: Wäre der wahre Mittelwert mu0 (meist 0), wie überraschend wäre dann ein Stichprobenmittel, das so weit von mu0 entfernt ist? Die Antwort ist ein p-Wert. Ein kleiner p-Wert besagt, dass die Daten unter der Hypothese „es passiert nichts“ sehr unwahrscheinlich wären.

t = (mean - mu0) / (s / sqrt(n)) p = P(|Z| > |t|)

Die t-Statistik misst den Mittelwert in Einheiten seiner eigenen Unsicherheit. Die Unsicherheit eines Mittelwerts ist der Standardfehler s / sqrt(n): Er schrumpft mit wachsender Stichprobe, weshalb mehr Daten denselben Mittelwert überzeugender machen. Skaliert man alle Renditen um, ändern sich Mittelwert und Standardfehler gleich, t bleibt also gleich. Als Faustregel ist |t| über 2 selten bloßes Glück.

import math
import numpy as np

returns = np.array([0.004, -0.002, 0.001, 0.003, -0.004, 0.002, 0.006, -0.001, 0.005, 0.002, 0.003, -0.002])

n = len(returns)
mean = returns.mean()
std_error = returns.std(ddof=1) / math.sqrt(n)         # the uncertainty of the mean
t = mean / std_error                                   # testing against mu0 = 0

print(round(mean, 5), round(std_error, 6))             # 0.00142 0.000892   the mean is only 1.6 standard errors from 0
print(round(t, 3))                                     # 1.589

Von t zum p-Wert

Unter der Nullhypothese verhält sich t bei großer Stichprobe wie eine Standardnormalvariable, der zweiseitige p-Wert ist also die Wahrscheinlichkeit, in beiden Richtungen weiter als |t| von 0 zu landen: erfc(|t| / sqrt(2)). Bei t = 1,59 sind das 11 %: Ein so gutes Ergebnis tritt einmal in neun Fällen zufällig auf, einen echten Vorteil können wir also nicht behaupten. Die übliche Schwelle ist 5 % (|t| = 1,96). Für kleine Stichproben ist die eigentliche Referenz die Student-t-Verteilung mit schwereren Rändern, der Normal-p-Wert ist daher etwas zu klein; bei weniger als 30 Punkten nehmen Sie eine echte t-Tabelle.

p_value = math.erfc(abs(t) / math.sqrt(2))
print(round(p_value, 4))                      # 0.1121   an outcome this good happens by chance about 1 time in 9

print(round(math.erfc(1.96 / math.sqrt(2)), 4))   # 0.05     |t| = 1.96 is the usual 5% limit

# Testing against another value: is the mean different from 0.2% a day?
t_other = (mean - 0.002) / std_error
print(round(t_other, 3), round(math.erfc(abs(t_other) / math.sqrt(2)), 3))   # -0.654 0.513

Konfidenzintervalle und gepaarte Stichproben

Ein Konfidenzintervall sagt mehr als ein Ja/Nein-Test: Mittel -/+ 1,96 * Standardfehler ist ein Bereich, der den wahren Mittelwert in etwa 95 % der Fälle enthält. Enthält das Intervall 0, ist der Mittelwert bei 5 % nicht signifikant. Unser Intervall von -0,03 % bis +0,32 % pro Tag überspannt null und ist im Vergleich zum Mittelwert breit. Um zwei Strategien zu vergleichen, die an denselben Tagen gemessen wurden, testen Sie ihre täglichen Differenzen gegen 0. Die Paarung entfernt das gemeinsame Rauschen (die guten und schlechten Marktage) und erkennt einen Vorteil viel schärfer als zwei getrennte Tests.

low, high = mean - 1.96 * std_error, mean + 1.96 * std_error
print(round(low, 5), round(high, 5))           # -0.00033 0.00316   the interval contains 0: not significant at 5%

# Paired: the same six days for two strategies
a = np.array([0.004, -0.002, 0.001, 0.003, -0.004, 0.002])
b = np.array([0.002, -0.003, 0.000, 0.001, -0.002, 0.0])
d = a - b
t_paired = d.mean() / (d.std(ddof=1) / math.sqrt(len(d)))
print(round(d.mean(), 5), round(t_paired, 3))   # 0.001 1.581   a daily edge of 0.1%, but only 6 days
# Same mean and spread, four times the data: t doubles and the p-value collapses
spread = returns.std(ddof=1)
for n in (12, 48):
    t_n = mean / (spread / math.sqrt(n))
    print(n, round(t_n, 3), round(math.erfc(abs(t_n) / math.sqrt(2)), 4))
# 12 1.589 0.1121
# 48 3.178 0.0015
Signifikant heißt nicht wichtig, und viele Tests täuschenEin winziger Vorteil kann bei genug Daten sehr signifikant sein, ein großer bei wenigen nicht. Lesen Sie die Effektgröße immer neben dem p-Wert. Und wenn Sie 100 Strategien testen, bestehen etwa 5 bei 5 % allein durch Glück: Je mehr Varianten Sie an denselben Daten probieren, desto weniger sagt ein einzelner p-Wert.
  • t = (mean - mu0) / (s / sqrt(n)): der Mittelwert in Einheiten seines Standardfehlers s / sqrt(n); mehr Daten, größeres |t|.
  • Der zweiseitige p-Wert ist erfc(|t| / sqrt(2)) bei großen Stichproben; |t| > 1,96 heißt p < 5 %; ein Intervall mean -/+ 1,96 * se, das 0 enthält, heißt nicht signifikant.
  • Vergleichen Sie Strategien an denselben Tagen mit der t-Statistik der täglichen Differenzen; hüten Sie sich vor dem Testen vieler Varianten.

Als Nächstes: lineare Regression (OLS), eine Gerade, die eine Rendite durch eine andere erklärt.

Lab: Was bewertet wird

  • Mit t_statistic den Mittelwert in Einheiten seines Rauschens messen25 Pkt.
  • Mit two_sided_p t in einen p-Wert umrechnen25 Pkt.
  • Mit confidence_interval den wahren Mittelwert eingrenzen25 Pkt.
  • Mit paired_t_statistic zwei Strategien Tag für Tag vergleichen25 Pkt.
Explorer · lab-57-1
▾ lab-57-1
…
bash · im Browser
learner@quantcraft:~/lab-57-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

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