AlphaFeed Blog

Tushare 前复权回测对不上/不可复现?前复权未来函数陷阱与正确做法

对比与选型 · 代码验证于 2026-10-24

Tushare 前复权回测对不上/不可复现?前复权陷阱与正确做法

一句话回答: 前复权(qfq)是以”最近价格”为基准向前缩放历史,每当发生新的除权除息,整条历史前复权序列都会被重新计算——于是你上周跑的回测,这周数据更新后历史数值变了、结果对不上、难以复现。正确做法有两条:回测用后复权(基准在过去、历史值不随新除权改变),或存原始价 + 除权因子(ex_factors)自己复权并留痕审计。AlphaFeed 的 adjust 支持 5 种口径(none/forward/backward/forward_additive/backward_additive)一键切换,并提供 ex_factors 做可复现审计。

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

很多人默认用前复权跑回测,却忽略一个事实:前复权的”今天价”等于原始价,历史被按最新基准缩放。只要之后再除权一次,整段历史前复权价会整体再缩放一遍。后果:

实测可印证基准差异:600519 最新收盘在 none/forward 下都是 1335.0(前复权今天=原始价),而 backward(后复权)最新为约 10238.85——后复权放大的是”今天”、历史保持原值,因此历史不随新除权变动、可复现。

对照表:复权口径怎么选

口径基准历史值是否随新除权变适合
不复权 none原始成交价否看真实成交价/对账
前复权 forward(qfq)最近价会变(每次新除权重算)看当前走势、画图
后复权 backward(hfq)上市初期否(历史稳定)回测,可复现
加法前/后复权加法口径前者会变/后者稳定特定价差口径

经验法则:画图看走势用前复权;回测与存档用后复权或”原始价+因子”,避免历史被最新除权重算。

代码:可复现的做法

方案 A:回测直接用后复权

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:存原始价 + 除权因子,自己复权并留痕

# 原始价(不复权)落库,另存除权因子,复权过程可复现、可审计
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 * 因子推导复权价;原始价不变 → 任何时点都能复现同一结果

关键坑与注意事项

常见问题(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 正好覆盖这套做法。

相关链接:


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