前阵子在知乎看到一个帖子,堪称量化新手最大的悬案现场:
发帖的人用Tushare的数据回测一个双均线策略,前复权数据跑出来年化25%,曲线相当漂亮。后来换了个数据源,用后复权数据把同一套策略在同一只股票上又跑了一遍——年化直接掉到5%。同一只股票、同一段历史、同一套代码,收益差了20个点,人当场就懵了。知乎
B站也有个视频叫《手写复权引擎:彻底解决回测数据漂移》,开头第一句话说得更直接:为什么同一个策略,隔几个月重新回测,收益率和买卖点会全部改变?很多人以为是策略失效了,但真正的问题出在数据层。哔哩哔哩
今天把这件事一次讲透。这个坑的特点是:原理一句话就能讲清,但不知道的人,可能会浪费三个月去调策略、怀疑人生。
一、回测结果为什么会"变"
先说机制,就一条:前复权价格的基准,是"最新价"。
只要一只股票发生分红、送股、配股等除权事件,为了保证今天的价格不动,它的全部历史价格都要跟着重算一遍。也就是说,你硬盘里存的那份前复权K线,不是"历史事实",而是"站在今天看过去的视角"。明天这家公司分红,你的历史数据就全变了。
后复权相反:基准固定在最早的日期,因子一路向后累乘,历史一旦算定就不再变(除非数据商修正口径)。
再叠加一个时间点就更好理解了:每年5月到7月,是A股年报分红的集中实施期。换句话说,过去这两个月,五千多只A股的前复权价格刚刚经历了一轮集体重写。如果你年初把前复权价格存到了本地,现在拿这份数据重跑回测,结果和上次不一样,不是bug,是这份数据天生就带着的设定。
这也是为什么老玩家自建数据库,几乎都是同一种姿势:存"未复权价格+复权因子",而不是存前复权价格。
昨天《量化概念07》刚讲完前复权和后复权的基本盘,今天往前再走一步:基准为什么会动,动了之后会把回测带进哪四个坑。知乎
二、那为什么有人的前后复权差了20%?
这里最容易被带偏。知乎有篇高赞老文,标题就叫《量化回测到底应该用哪种复权数据?网上文章大多是错误的!》,它的核心结论是:同一套比例法复权、同一份完整的复权因子,前复权和后复权的回测收益理论上应该一模一样。知乎
这里先澄清一个常见误会:前复权价格不是"未来函数"。同一份数据快照里,前复权和后复权只是基准不同,涨跌幅、均线交叉这些相对计算结果完全一样,不存在偷看未来。真正的问题是前复权快照会"过期"——每发生一次分红送转,整份快照就被重写一遍;把不同时间存下的新旧快照混在一起用,回测才会漂。
所以别被"差了20%"吓住——前后复权本身不是问题来源。差异几乎都来自下面这四个坑:
坑一:用的是加减法复权。 复权算法分两大流派:比例法(也叫涨跌幅复权法)和加减法。万得、米筐、Tushare走的是比例法,同花顺、东方财富、大智慧走的是加减法。加减法的前复权可能出现负价格,回测语义会失真。有个十秒钟的鉴别办法:拉一下贵州茅台2001年8月27日的前复权收盘价,如果是负数,这个数据源就是加减法,做回测请直接排除。知乎

坑二:新旧两版前复权混用了。 你3月缓存的前复权价格,和8月重新拉的,已经是两份不同的数据(中间发生过分红的话)。策略里一旦混用了版本,收益自然漂移。
坑三:复权因子和行情日期没对齐。 Tushare的adj_factor官方说明里专门提醒:复权因子在股票停牌的日子也会补齐,而daily日线行情停牌日没有数据。两张表直接按日期合并,停牌段消失,索引错位,算出来的复权价悄悄出错。知乎
坑四:回测区间太长,跨进了股权分置改革年代。 2005-2007年股改期间,因为送权证等特殊措施,各家数据商对那个时段的除权价处理方式不同,同一只股票跨股改时期的后复权价比率,Tushare、万得、baostock、通达信之间是对不上的。偷懒解法:回测数据从2008年1月开始切,一刀避开这段公案。知乎

三、正确的存法:这份清单可以直接抄
只存两类数据:daily未复权日线 + adj_factor累计后复权因子。前复权价格,一律不存。
用的时候现算:后复权价 = 未复权价 × 复权因子;前复权价 = 未复权价 ×(当日因子 ÷ 最新因子)。
回测计算用后复权,画图看盘用前复权。后复权的历史是稳定的,任何时候重跑结果可复现,这是回测可信的底线。
复权因子每天更新一次即可。Tushare的adj_factor在每天8:30-9:30之间更新;注意按股票代码直接拉,只能拿到最近6000条,要更早的历史,得按交易日(trade_date)循环逐日拉到本地。知乎
如果想用dividend接口自己搭复权因子,只取div_proc为"实施"的记录。“预案”"董事会通过"阶段的方案还可能变更甚至取消,不能进公式。

顺带说一句门槛:复权因子接口要2000积分。在校生走学生认证可以免费拿2000积分,别急着掏钱;上班族要不要充,也建议先跑一遍自己真正缺哪些接口再决定——之前聊积分那篇说过,别被对比文带着充值。
另外提醒一句:如果你的回测代码是让AI助手写的,请把"只读未复权价格和复权因子、复权价现算"这条明确写进需求里,不然它大概率会图省事,直接去读你很久以前存下的那份前复权CSV。
四、顺手澄清一个误会
除权日前后,daily_basic里的PE、PB经常会剧烈跳变,不少人以为是数据坏了。不是。除权日股价、总股本、净资产会同步调整,PE、PB自然跟着跳;还有像比亚迪这种A+H两地上市的,2025年里有两天是A股价格纹丝不动、PE和PB却跳了——那是H股除权带来的股本口径调整,属于会计准则要求的正常处理,不是数据错误。知乎

还有个现象值得知道:除权日股价"下跌",不是真跌,是机械减法——股价被扣掉了分红金额。2026年4月《Pacific-Basin Finance Journal》上有项基于A股分红的研究,专门描述了这种"自由分红谬误":不少投资者不知道除权除息,除权日前追进去抢分红,除权日看到股价"跌了"又恐慌卖出。知乎如果你的策略围绕分红、均线或动量展开,回测里建议加一个除权日过滤器,跳过除权日前后的信号,不然每年这个阶段都会多出几个假信号。
五、结论就三句
存未复权价格+复权因子,永远不存前复权价格;
回测计算用后复权,画图展示用前复权;
回测结果变了,先查数据,再怀疑策略。
之前写过中报季财务数据"偷看答案"的前视问题,那是财报侧的坑;今天这个复权漂移,是行情侧的坑。两个都堵上,个人量化的数据底座才算干净。下一个观察点:9-10月随着三季报预告和中期分红实施,复权因子还有一轮集中更新,自建库的朋友可以趁机做一次全量校验——拉一遍复权因子,重跑一次基准策略,确认曲线能原样复现,你的数据仓库才算真正"不骗你"。