Der Verlust, den man wirklich spürt
Volatilität behandelt Auf und Ab gleich, doch ein Anleger lebt mit einer anderen Zahl: wie weit das Depot unter dem besten Wert liegt, den es je hatte. Das ist der Drawdown. Stieg ein Portfolio auf 110 und steht jetzt bei 98, liegt es 10,9 % unter seinem Höchststand, was auch die Tagesvolatilität sagt. Der maximale Drawdown ist das tiefste solche Loch der Historie, die Zeit unter Wasser die Dauer, bis man wieder heraus war. Kunden steigen bei Drawdowns aus und Risikomanager kürzen Limits bei Drawdowns, nicht bei Standardabweichungen.
import pandas as pd
prices = pd.Series(
[100, 105, 103, 98, 104, 110, 108, 107, 111, 95], dtype=float,
index=pd.bdate_range("2026-03-02", periods=10),
)
peak = prices.cummax() # the highest price so far, day by day
drawdown = prices / peak - 1 # 0 on a new high, negative below it
print(peak.tolist()) # [100.0, 105.0, 105.0, 105.0, 105.0, 110.0, 110.0, 110.0, 111.0, 111.0]
print(drawdown.round(4).tolist()) # [0.0, 0.0, -0.019, -0.0667, -0.0095, 0.0, -0.0182, -0.0273, 0.0, -0.1441]Das tiefste Loch
cummax() liefert den laufenden Höchststand in einem Aufruf. Den Preis dadurch zu teilen und 1 abzuziehen ergibt an jedem Tag den Drawdown, stets null oder negativ. Der maximale Drawdown ist einfach das Minimum dieser Reihe, und idxmin() sagt, wann er auftrat. Drawdowns sind auf wichtige Weise asymmetrisch: Ein Verlust von 20 % braucht 25 % Gewinn, um zurückzukommen, 1 / (1 - 0,20) - 1, einer von 50 % braucht 100 %. Deshalb kämpfen Risikomanager für flache Drawdowns.
print(round(drawdown.min(), 4), drawdown.idxmin().date()) # -0.1441 2026-03-13 111 down to 95
# The climb back is steeper than the fall
for loss in (0.10, 0.20, 0.50):
print(loss, round(1 / (1 - loss) - 1, 3))
# 0.1 0.111
# 0.2 0.25
# 0.5 1.0Die Zeit unter Wasser
Die Tiefe ist nur die halbe Geschichte, die Dauer die andere Hälfte. Eine Strategie kann nur 8 % verlieren und trotzdem drei Jahre unter ihrem alten Hoch verbringen, was die Geduld jedes Anlegers prüft. Ein Tag ist unter Wasser, solange sein Drawdown negativ ist, und ein neues Hoch beendet die Phase. Um mit pandas die längste Phase zu finden, markieren Sie die Tage unter Wasser durch einen Vergleich, nummerieren jede Folge gleicher Werte mit (flag != flag.shift()).cumsum() und zählen innerhalb jeder Folge. Eine einfache Schleife, die zählt und zurücksetzt, geht genauso gut und liest sich leicht.
underwater = drawdown < 0 # True while below the running peak
run_id = (underwater != underwater.shift()).cumsum() # a new id each time the flag changes
streak = underwater.astype(int).groupby(run_id).cumsum() # 1, 2, 3, ... inside each underwater run
print(streak.tolist()) # [0, 0, 1, 2, 3, 0, 1, 2, 0, 1]
print(int(streak.max())) # 3 the longest wait for a new high, in days# Return divided by the depth of the worst hole: the Calmar ratio
annual_return = 0.12
print(round(annual_return / abs(drawdown.min()), 2)) # 0.83peak = prices.cummax()unddrawdown = prices / peak - 1: null bei neuem Hoch, darunter negativ.- Der maximale Drawdown ist
drawdown.min(); ein Verlust vonxbraucht einen Gewinn von1 / (1 - x) - 1zur Erholung. - Die Zeit unter Wasser ist die längste Folge von Tagen mit negativem Drawdown; der schlimmste Drawdown eines Backtests ist eine Untergrenze, keine Garantie.
Als Nächstes: Zufallszahlengeneratoren und Seeds, die Grundlage jeder Simulation.
Lab: Was bewertet wird
- Mit
running_peakden bisherigen Höchststand verfolgen25 Pkt. - Mit
drawdown_seriesden Abstand zum Höchststand messen25 Pkt. - Mit
max_drawdownden schlimmsten Einbruch finden25 Pkt. - Mit
longest_underwaterdas längste Warten auf ein neues Hoch zählen25 Pkt.