一句话回答: 前复权(qfq)是以"最近价格"为基准向前缩放历史 ,每当发生新的除权除息,整条历史前复权序列都会被重新计算 ------于是你上周跑的回测,这周数据更新后历史数值变了、结果对不上、难以复现。正确做法有两条:回测用后复权(基准在过去、历史值不随新除权改变) ,或存原始价 + 除权因子(ex_factors)自己复权并留痕审计 。AlphaFeed 的 adjust 支持 5 种口径(none/forward/backward/forward_additive/backward_additive)一键切换,并提供 ex_factors 做可复现审计。
为什么会有这个问题 / 传统做法的痛点
很多人默认用前复权跑回测,却忽略一个事实:前复权的"今天价"等于原始价,历史被按最新基准缩放。只要之后再除权一次,整段历史前复权价会整体再缩放一遍。后果:
- 不可复现:同一段回测,换个日期重拉数据,历史 K 线数值变了,信号与收益跟着变;
- 对不上:你存档的前复权价和今天重新下载的对不上,排查半天其实是复权基准变了;
- 隐患:用"含未来除权信息的最新基准"解释很久以前的价格,逻辑上也不干净。
实测可印证基准差异:600519 最新收盘在 none/forward 下都是 1335.0(前复权今天=原始价),而 backward(后复权)最新为约 10238.85------后复权放大的是"今天"、历史保持原值,因此历史不随新除权变动、可复现。
对照表:复权口径怎么选
| 口径 | 基准 | 历史值是否随新除权变 | 适合 |
|---|---|---|---|
| 不复权 none | 原始成交价 | 否 | 看真实成交价/对账 |
| 前复权 forward(qfq) | 最近价 | 会变(每次新除权重算) | 看当前走势、画图 |
| 后复权 backward(hfq) | 上市初期 | 否(历史稳定) | 回测,可复现 |
| 加法前/后复权 | 加法口径 | 前者会变/后者稳定 | 特定价差口径 |
经验法则:画图看走势用前复权;回测与存档用后复权或"原始价+因子",避免历史被最新除权重算。
代码:可复现的做法
方案 A:回测直接用后复权
python
from alphafeed import AlphaFeed
af = AlphaFeed(api_key="your-api-key")
# 后复权:基准在过去,历史值不随新除权改变 → 回测可复现
df = af.klines.get("600519.SH", period="1d", count=1000,
adjust="backward", to_dataframe=True)
方案 B:存原始价 + 除权因子,自己复权并留痕
python
# 原始价(不复权)落库,另存除权因子,复权过程可复现、可审计
raw = af.klines.get("600519.SH", period="1d", count=1000,
adjust="none", to_dataframe=True)
factors = af.klines.ex_factors(["600519.SH"], to_dataframe=True)
# factors 列:symbol, timestamp, trade_date, ex_factor
# 需要时用 raw * 因子推导复权价;原始价不变 → 任何时点都能复现同一结果
关键坑与注意事项
- 前复权不是"错",是"会变":它适合看当前走势与画图;问题在于历史随最新除权重算,不利于回测复现。
- 后复权也有口径差异 :不同数据源的因子口径不同,后复权绝对值不一定和别家相同;但同一源内历史稳定、可复现才是回测要的。
- 别拿前复权价存档当"永久真值":要存档就存原始价+因子,或后复权。
- 复权数值不保证跨源一致:迁移后以"单源自洽、可复现"为准,不要期望和 Tushare 逐值对齐。
- AlphaFeed 只做交易型行情,财务/参考数据不覆盖。
常见问题(FAQ)
Q:回测到底该用前复权还是后复权?
A:优先后复权(历史不随新除权变、可复现)。前复权更适合看当前走势、画图。或存原始价+因子自己复权。
Q:为什么我存的前复权价和重新下载的对不上?
A:中间发生过除权,前复权基准变了,整段历史被重算。这正是前复权的特性,不是数据错。
Q:AlphaFeed 的复权会和 Tushare 完全一样吗?
A:不保证逐值相同(因子口径不同)。关键是在单一数据源内保持一致、可复现。
Q:ex_factors 返回什么?
A:长表 symbol, timestamp, trade_date, ex_factor,可配合不复权原始价自行复现复权价,便于审计。
小结
前复权回测"对不上/不可复现"的根因是:前复权以最新价为基准、历史随新除权重算。要可复现,就用后复权,或存"原始价+ex_factors"自己复权留痕。AlphaFeed 的 adjust 5 种口径 + ex_factors 正好覆盖这套做法。
参考
- AlphaFeed Python SDK 文档:https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart
- AlphaFeed 官网:https://alphafeed.org/
- 本文完整版(AlphaFeed 博客):https://blog.alphafeed.org/blog/tushare-qfq-lookahead-trap