AlphaFeed Blog

如何用 Python 算最大回撤和回撤恢复期?(水下曲线与创新高间隔)

分析与指标 · 代码验证于 2026-10-02

如何用 Python 算最大回撤和回撤恢复期?

一句话回答: 最大回撤(Max Drawdown)是「从历史高点跌下来的最大幅度」,但更揪心的是回撤恢复期——跌下去后要多久才重新创新高(即「套牢多久」)。用 AlphaFeed 取回前复权净值后,几行 pandas 就能算出回撤序列、最大回撤、水下曲线(underwater)、最长恢复期与当前已水下天数。

为什么会有这个问题 / 传统做法的痛点

很多人只报一个「最大回撤 -30%」,但 -30% 回撤如果 3 个月就修复,和套牢 2 年还没回本,持有体验天差地别。衡量风险要同时看深度(回撤幅度)和时间(恢复期/水下时长)。坑在于:要用前复权净值算真实回撤,并正确识别「前高—谷底—重新创新高」这三个点。

分步骤解决(每步配可运行代码)

第 1 步:取前复权数据构造净值曲线

from alphafeed import AlphaFeed
import pandas as pd

af = AlphaFeed()  # 读取 ALPHAFEED_API_KEY

df = af.klines.get("600519.SH", period="1d", count=750,
                   adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)
equity = df["close"] / df["close"].iloc[0]       # 归一化净值(买入持有)
equity.index = pd.to_datetime(df["trade_date"])

用前复权收盘价构造净值,避免除权跳空把回撤算错。

第 2 步:回撤序列与最大回撤

peak = equity.cummax()                 # 历史最高净值
drawdown = equity / peak - 1           # 回撤序列(≤0),这就是“水下曲线”
mdd = drawdown.min()                   # 最大回撤
mdd_date = drawdown.idxmin()           # 最大回撤发生日(谷底)
print(f"最大回撤 {mdd:.2%},谷底日 {mdd_date.date()}")
概念定义含义
peak净值历史最高(cummax)创新高的轨迹
drawdownequity/peak − 1水下曲线,≤0
最大回撤drawdown.min()最深的套牢幅度

第 3 步:回撤恢复期(最长水下时长)

# 水下 = 净值低于历史高点(drawdown<0);连续水下段的最长长度=最长未创新高天数
underwater = drawdown < 0
# 给每一段连续水下编号,统计各段长度
seg = (~underwater).cumsum()                 # 每次创新高,段号+1
spells = underwater.groupby(seg).sum()       # 每段水下天数
longest_underwater = int(spells.max())       # 最长水下天数(交易日)
# 当前是否水下、已水下多久
cur_underwater = int(underwater.iloc[::-1].cumprod().sum())  # 末尾连续水下天数
print(f"最长回撤未创新高 {longest_underwater} 个交易日")
print(f"当前已水下 {cur_underwater} 个交易日(0=正处新高附近)")

第 4 步:找出「前高→谷底→修复」三个关键点

trough = drawdown.idxmin()                                   # 谷底
peak_before = equity.loc[:trough].idxmax()                   # 谷底前的高点
after = equity.loc[trough:]
recovered = after[after >= equity.loc[peak_before]]
recover_date = recovered.index[0] if len(recovered) else None
print(f"前高 {peak_before.date()} → 谷底 {trough.date()} → "
      f"{'修复于 '+str(recover_date.date()) if recover_date is not None else '至今未修复'}")

关键坑与注意事项

常见问题(FAQ)

Q:最大回撤和波动率有什么区别? A:波动率衡量日常波动的大小,最大回撤衡量「最坏的一段连续下跌」。回撤更贴近真实的套牢体验,二者应结合看。

Q:回撤恢复期为什么重要? A:它回答「套牢多久才回本」。两个策略最大回撤都是 -20%,但一个 1 个月修复、一个 3 年没回本,可持有性天差地别。

Q:水下曲线(underwater)是什么? A:就是回撤序列 equity/peak-1 的图形,始终 ≤0,低谷越深越久代表风险越大。

Q:需要付费吗? A:单只历史数据有免费额度;组合/多标的批量分析(klines.batch)需 Starter 及以上。详见定价页。

小结

衡量风险别只看一个「最大回撤」数字,还要看回撤恢复期(水下时长)。用 AlphaFeed 取前复权净值,cummax 得历史高点、equity/peak-1 得水下曲线,再统计连续水下段就能算出最大回撤、最长恢复期与当前水下天数。深度 + 时间一起看,才真正理解一只票/组合的风险。

相关链接:


免责声明:本文仅为技术与数据接口使用示例,代码与策略仅供学习研究,不构成投资建议。市场有风险,历史数据不代表未来表现。