一句话回答: 最大回撤(Max Drawdown)是「从历史高点跌下来的最大幅度」,但更揪心的是回撤恢复期 ------跌下去后要多久才重新创新高(即「套牢多久」)。用 AlphaFeed 取回前复权净值 后,几行 pandas 就能算出回撤序列、最大回撤、水下曲线(underwater)、最长恢复期与当前已水下天数。
为什么会有这个问题 / 传统做法的痛点
很多人只报一个「最大回撤 -30%」,但 -30% 回撤如果 3 个月就修复,和套牢 2 年还没回本,持有体验天差地别。衡量风险要同时看深度(回撤幅度)和时间(恢复期/水下时长) 。坑在于:要用前复权净值算真实回撤,并正确识别「前高---谷底---重新创新高」这三个点。
分步骤解决(每步配可运行代码)
第 1 步:取前复权数据构造净值曲线
python
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 步:回撤序列与最大回撤
python
peak = equity.cummax() # 历史最高净值
drawdown = equity / peak - 1 # 回撤序列(≤0),这就是"水下曲线"
mdd = drawdown.min() # 最大回撤
mdd_date = drawdown.idxmin() # 最大回撤发生日(谷底)
print(f"最大回撤 {mdd:.2%},谷底日 {mdd_date.date()}")
| 概念 | 定义 | 含义 |
|---|---|---|
peak |
净值历史最高(cummax) | 创新高的轨迹 |
drawdown |
equity/peak − 1 |
水下曲线,≤0 |
| 最大回撤 | drawdown.min() |
最深的套牢幅度 |
第 3 步:回撤恢复期(最长水下时长)
python
# 水下 = 净值低于历史高点(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 步:找出「前高→谷底→修复」三个关键点
python
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 '至今未修复'}")
关键坑与注意事项
- 用前复权净值:未复权价在除权日的跳变会把回撤算得失真。
- 回撤深度和时间都要看:-30% 回撤修复 3 个月 vs 2 年,风险体感完全不同,别只报一个数。
- 恢复期以交易日计:换算成自然日要乘约 1.4(约 250 交易日/年),别混。
- 当前水下时长 :末尾连续
drawdown<0的长度,提醒你现在距上一次新高多久。 - 样本区间影响结论:最大回撤与恢复期强依赖所取区间,跨周期对比要用同一区间。
- 组合同理 :把
equity换成组合净值即可,方法通用。
常见问题(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 得水下曲线,再统计连续水下段就能算出最大回撤、最长恢复期与当前水下天数。深度 + 时间一起看,才真正理解一只票/组合的风险。
参考
- AlphaFeed Python SDK 文档:https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart
- AlphaFeed 官网:https://alphafeed.org/