Marktmechanik
MethodikBacktest-NotizenBacktest-Diagnostik

Deflated Sharpe Ratio: Warum dein Backtest lügt, und wie man es in vierzig Zeilen nachweist

Wer 1.240 Parameterkombinationen testet, findet eine Sharpe Ratio um 2 - auch in reinem Rauschen. Die Deflated Sharpe Ratio korrigiert dafür, und das Ergebnis ist meist unbequem.

Raphael ZbindenStatistische Arbitrage & Backtest-Methodik
4 Min Lesezeit

Ich habe 2015 eine Strategie gebaut, die im Backtest eine Sharpe Ratio (Rendite je Einheit Schwankung) von 2,1 hatte, über zwölf Jahre, mit einem maximalen Drawdown, also größten Rückgang vom Höchststand, von neun Prozent. Ich habe sie live geschaltet und in vierzehn Monaten elf Prozent verloren. Rückblickend war der Fehler im Backtest sichtbar: Ich hatte 1.240 Parameterkombinationen getestet, und bei so vielen Versuchen liegt eine Sharpe Ratio in dieser Höhe nahe an dem, was auch reines Rauschen liefert. Ich habe nur nicht danach gesucht.

Das Problem in einem Satz

Wenn man viele Strategien testet und die beste auswählt, ist die Sharpe Ratio der besten kein unverzerrter Schätzer ihrer wahren Sharpe Ratio. Sie ist das Maximum einer Stichprobe - und das Maximum einer Stichprobe von Zufallsvariablen wächst mit der Stichprobengröße, ganz ohne dass irgendetwas an den Variablen besser wird.

Die Demonstration

Man kann das in zehn Zeilen zeigen. Man erzeugt reines Rauschen ohne jede Struktur, testet darauf viele Parameterkombinationen und schaut sich die beste an.

python · rauschen.py
import numpy as np
rng = np.random.default_rng(42)

T, N = 2520, 1240                       # 10 Jahre Tagesdaten, 1240 "Strategien"
rauschen = rng.normal(0, 0.01, (N, T))  # keinerlei Struktur, Erwartungswert 0

sharpes = rauschen.mean(axis=1) / rauschen.std(axis=1, ddof=1) * np.sqrt(252)
print(f"beste Sharpe:   {sharpes.max():.2f}")     # -> ca. 1,7 bis 2,0
print(f"Median Sharpe:  {np.median(sharpes):.2f}")# -> ca. 0,00
print(f"Anteil > 1,5:   {(sharpes > 1.5).mean():.3%}")

Die beste von 1.240 Strategien auf reinem Rauschen erreicht typischerweise eine Sharpe Ratio zwischen 1,7 und 2,0. Wenn Sie also in einer Parameteroptimierung mit ähnlich vielen Kombinationen eine Sharpe von 1,8 finden, haben Sie keinerlei Evidenz für Alpha, also für echte, nicht zufällige Überrendite. Sie haben genau das Ergebnis, das Sie auch bei völliger Abwesenheit von Alpha erwarten würden.

26.519.312.14.8-2.4-1,0-0,500,51,01,52,02,53,0Verteilung aller Trial-Sharpes (%)Ausgewählter Kandidat (%)
Verteilung der Sharpe Ratios über 1.240 Parameterkombinationen. Der ausgewählte Kandidat liegt im rechten Tail einer Verteilung, die überwiegend Rauschen ist. Beispielwerte.

Die Korrektur

Bailey und López de Prado haben dafür die Deflated Sharpe Ratio vorgeschlagen. Man berechnet, welche Sharpe Ratio man bei N unabhängigen Versuchen allein durch Selektion erwarten würde, und prüft, ob die beobachtete Sharpe Ratio darüber liegt.

SR0 = σ(SR) · [ (1-γ)·Φ-1(1 - 1/N) + γ·Φ-1(1 - 1/(N·e)) ] σ(SR) = Streuung der Sharpe Ratios über alle Versuche
N = Anzahl unabhängiger Versuche · γ ≈ 0,5772 (Euler-Mascheroni)
Φ-1 = inverse Standardnormalverteilung
DSR = Wahrscheinlichkeit, dass die wahre Sharpe Ratio größer als SR0 ist
python · dsr.py
import numpy as np
from scipy.stats import norm

GAMMA = 0.5772156649

def sr0(sharpe_streuung, n_versuche):
    '''Erwartetes Maximum der Sharpe Ratio bei reiner Selektion.'''
    n = max(2, n_versuche)
    return sharpe_streuung * (
        (1 - GAMMA) * norm.ppf(1 - 1 / n) +
        GAMMA * norm.ppf(1 - 1 / (n * np.e))
    )

def deflated_sharpe(sr_beob, T, schiefe, kurtosis, sr_streuung, n_versuche):
    '''
    sr_beob:  beobachtete (annualisierte) Sharpe Ratio der besten Strategie
    T:        Anzahl Beobachtungen
    schiefe / kurtosis: der Renditereihe der besten Strategie
    '''
    schwelle = sr0(sr_streuung, n_versuche)
    sr_d = sr_beob / np.sqrt(252)          # zurueck auf Periodenbasis
    sw_d = schwelle / np.sqrt(252)
    # Standardfehler nach Mertens, korrigiert um hoehere Momente
    se = np.sqrt((1 - schiefe * sr_d + (kurtosis - 1) / 4 * sr_d ** 2) / (T - 1))
    return float(norm.cdf((sr_d - sw_d) / se))

Angewendet auf meine damalige Strategie

Nachträgliche Diagnostik der 2015er Strategie. Beispielwerte.
KennzahlWertBewertung
Beobachtete Sharpe (In-Sample)2,10sieht ausgezeichnet aus
Getestete Kombinationen1.240und darauf kommt es an
Streuung der Trial-Sharpes0,61hoch → instabile Parameterlandschaft
Schwelle SR01,94Selektionserwartung bei N = 1.240
Schiefe der Renditereihe-1,42negativ → Standardfehler steigt
Deflated Sharpe Ratio0,58< 0,95 → keine Evidenz

Eine DSR von 0,58 heißt: Die Wahrscheinlichkeit, dass die wahre Sharpe Ratio über der Selektionsschwelle liegt, beträgt 58 Prozent. Bei einem üblichen Konfidenzniveau von 95 Prozent ist das keine Evidenz für Alpha, sondern ein Münzwurf. Hätte ich das 2015 gerechnet, wäre die Strategie nie live gegangen.

Der schwierige Parameter: N

Wie viele Versuche waren es wirklich?

N ist die Anzahl unabhängiger Versuche, nicht die Anzahl ausgeführter Backtests. Wenn Sie einen Parameter von 10 bis 200 in Einerschritten testen, sind das 191 Läufe, aber keineswegs 191 unabhängige Hypothesen - benachbarte Werte sind hoch korreliert.

Meine Näherung: Ich berechne die Korrelationsmatrix der Renditereihen aller Versuche, führe eine Hauptkomponentenanalyse durch und setze N auf die Anzahl Komponenten, die 95 Prozent der Varianz erklären. Bei den 1.240 Läufen von damals ergibt das N ≈ 34 statt 1.240 - und damit eine deutlich niedrigere Schwelle. Die DSR steigt in diesem Fall auf 0,89, was noch immer unter 0,95 liegt.

Und dann kommt der Teil, den keine Formel abdeckt: Alle Versuche, die ich verworfen habe, bevor ich sie protokolliert habe, gehören ebenfalls zu N. Wer sechs Monate lang Ideen ausprobiert und nur die letzte dokumentiert, hat ein N, das er nicht kennt und das systematisch zu niedrig geschätzt wird.

Was ich seitdem anders mache

  • Versuchsprotokoll ab dem ersten Lauf. Jede Kombination wird geloggt, auch die verworfenen. N ist damit dokumentiert und nicht rekonstruiert.
  • Parameterlandschaft vor Punktschätzer. Wenn die Sharpe Ratio bei Parameter 47 hoch und bei 46 und 48 niedrig ist, ist das ein Artefakt. Ich verlange ein zusammenhängendes Plateau.
  • Out-of-Sample-Fenster bleibt unberührt. Der zurückgehaltene Testzeitraum dient nur der Schlussprüfung. Ein einziger Blick darauf während der Entwicklung macht es zu In-Sample. Bei mir liegt es in einer separaten Datei, die die Entwicklungsumgebung nicht liest.
  • DSR als Freigabekriterium. Unter 0,95 geht nichts live, unabhängig davon, wie gut die Equity-Kurve aussieht.

Der praktische Effekt: Ich habe seit 2015 vier Strategien live geschaltet statt vorher etwa einer pro Quartal. Drei davon laufen.

Risikohinweis

Dieser Beitrag ist eine methodische Darstellung zur statistischen Bewertung von Handelsstrategien und stellt keine Anlageberatung dar. Auch eine statistisch validierte Strategie kann zu Verlusten führen. Alle Zahlenwerte sind Beispielwerte.

  • Deflated Sharpe
  • Overfitting
  • Multiple Testing
  • Walk-Forward
  • Backtest
Statistische Arbitrage & Backtest-MethodikRaphael Zbinden

Raphael Zbinden hat Statik gezeichnet, bevor er Zeitreihen modelliert hat. Aus dem Hochbau bringt er eine Haltung mit, die im Trading selten ist: Man rechnet Lastfälle, die man nicht erwartet, weil genau die einstürzen lassen.

Profil ansehen →
Newsletter

Das Briefing am Freitag

Die Beiträge der Woche, eine offene Methodenfrage und ein Verfahren, das wir getestet und verworfen haben. Keine Signale, keine Kursziele.

Demo-Formular ohne Datenverarbeitung