The peak-to-trough decline in portfolio value over a specific period, measuring how much you lose from the highest point before recovering.
In Plain English
Volatility tells you how bumpy the ride is. Drawdown tells you how far you fell. These are different things. A strategy that loses 1% every single day for 30 days has a 26% maximum drawdown but very low daily volatility. A strategy that bounces between +5% and -5% every day has high volatility but a much smaller maximum drawdown. Both matter, and they tell you different things about the risk of a strategy.
Drawdown measures the loss from a portfolio's peak value to its subsequent trough. If your portfolio hits $1 million, then falls to $700,000 before recovering, you experienced a 30% drawdown. Maximum drawdown (MaxDD) is the largest such decline over an entire track record — the worst loss an investor would have experienced if they had the terrible luck to invest at the absolute peak before the worst period.
Why does drawdown matter beyond simple volatility? Because psychology matters. A 50% drawdown does not just require a 50% recovery — it requires a 100% gain just to get back to breakeven. Investors who experience deep drawdowns often panic-sell near the trough, turning paper losses into permanent ones. Strategies with similar Sharpe ratios but very different drawdown profiles are not equally attractive — the one with smaller drawdowns is far easier to stick with during tough periods.
Recovery time is the companion metric to maximum drawdown. A 20% drawdown that recovers in 6 months is very different from a 20% drawdown that takes 3 years to recover. Some institutional investors have explicit drawdown limits — a fund may be required to reduce exposure or liquidate positions if drawdown exceeds a threshold.
Technical Definition
Let V_t be portfolio value at time t. The drawdown at time t:
DD_t = (V_t − max_\{s≤t\} V_s) / max_\{s≤t\} V_s
Maximum drawdown over a period [0, T]:
MaxDD = min_\{t ∈ [0,T]\} DD_t
The Calmar ratio = Annualized Return / |MaxDD|. A Calmar above 1.0 means you earned more than your worst drawdown.
Underwater period: the contiguous time interval during which DD_t < 0, bounded by the peak date and the eventual recovery date. Time to recovery is the length of this interval.
Expected maximum drawdown for a random walk with drift μ and volatility σ over T periods scales as O(σ √T), which is why longer backtests naturally show larger maximum drawdowns even from identical strategies.
Pain index (Zephyr): average drawdown across all periods, capturing the experience of holding through all valleys rather than just the worst one.
How VectorFin Uses This
VectorFin's GARCH volatility forecasts (signals/volatility) help anticipate periods of elevated drawdown risk. When garch_vol_21d rises sharply — particularly in combination with the volatile or bear regime signal — historical analysis shows this precedes the most severe drawdown periods.
A practical risk management approach using VectorFin signals: 1. Monitor garch_vol_1d for single-day tail risk 2. Monitor regime signal for structural market state shifts 3. When both indicate elevated risk: reduce position sizes (vol-targeting) 4. When anomaly signal triggers: flag individual stocks for manual review
The anomaly signal in signals/anomaly can also flag stocks that are entering unusual price-action territory — a potential early warning before a significant idiosyncratic drawdown.
GET https://api.vectorfinancials.com/v1/signals/volatility/{ticker}?date=2024-10-01
GET https://api.vectorfinancials.com/v1/signals/anomaly/{ticker}?date=2024-10-01Code Example
import requests
import pandas as pd
import numpy as np
API_BASE = "https://api.vectorfinancials.com"
API_KEY = "vf_your_api_key_here"
def max_drawdown(returns: pd.Series) -> float:
"""Compute maximum drawdown from a return series."""
cum_returns = (1 + returns).cumprod()
rolling_max = cum_returns.cummax()
drawdowns = (cum_returns - rolling_max) / rolling_max
return float(drawdowns.min())
def drawdown_series(returns: pd.Series) -> pd.Series:
"""Return the full drawdown time series."""
cum_returns = (1 + returns).cumprod()
rolling_max = cum_returns.cummax()
return (cum_returns - rolling_max) / rolling_max
# Fetch GARCH vol signal and use it for vol-targeted position sizing
resp = requests.get(
f"{API_BASE}/v1/signals/volatility/QQQ",
params={"start": "2022-01-01", "end": "2024-12-31"},
headers={"X-API-Key": API_KEY},
)
vol_df = pd.DataFrame(resp.json()["data"])
vol_df["date"] = pd.to_datetime(vol_df["date"])
vol_df = vol_df.set_index("date")
# Simulate: unmanaged vs vol-targeted portfolio
np.random.seed(0)
raw_returns = pd.Series(np.random.normal(0.0004, 0.02, len(vol_df)), index=vol_df.index)
target_vol = 0.15
vol_df["position_weight"] = (target_vol / 252) / vol_df["garch_vol_1d"].clip(0.001)
vol_df["position_weight"] = vol_df["position_weight"].clip(0.5, 2.0)
vol_targeted_returns = raw_returns * vol_df["position_weight"]
print(f"Unmanaged MaxDD: {max_drawdown(raw_returns):.1%}")
print(f"Vol-targeted MaxDD: {max_drawdown(vol_targeted_returns):.1%}")Related Terms
Put Drawdown to work in your pipeline
Access AI-ready financial data — embeddings, signals, Iceberg tables.