为什么同一只A股的历史价格,过几个月重新下载会不一样**

TickDB Research ·

以下是假设场景。以下仅演示采用最新交易日作为锚点的数据源。

你保存了一份A股的前复权日线数据,用来做策略回测。几个月后想复现结果,从同一个数据源重新下载同一段历史区间。数据到手,拉出来一比——同一只股票,同一个日期,同一个前复权字段,数值却对不上了。

第一反应是数据源偷偷修了历史。但对比原始成交价,两版一致。再查复权因子,变了。

原始成交没有改。改变的是复权计算的那个基准日。

前复权保留某个基准日价格。基准可能是最新交易日,也可能是用户设置的查询结束日,取决于数据源规则和请求参数。理解这个现象的钥匙只有一句话——你下载的不是历史档案,而是一个以特定基准日重新计算的视图。基准往后移,每发生一次新的除权除息,权益事件日前的历史区段可能重新调整。历史价格变化,不等于历史成交被篡改。


复权不是还原历史,是重新建立一套坐标尺

理解这件事,需要先区分几个相似但完全不同的概念。

类型定义特点
原始成交价当日实际撮合成交的价格不因后续权益事件而复权重算,但数据提供方仍可能进行差错修订;含分红、送股带来的价格跳空
前复权保留某个基准日价格,反向调整历史价格每次分红送股后,基准日前的历史区段重新计算;同一日期数值在不同时点可能不同
后复权保持历史基准价格不变,正向调整后续价格历史值稳定;当前价格随时间推移可能远离真实交易价
PIT某个历史时点实际可得的数据快照不是另一种价格公式,是版本规则:回到过去,只用当时已知的信息

原始成交是地形,前复权是以选定的基准海平面重新标定过去的海拔,后复权是以历史的海拔推算今天的高度。


一个虚拟例子

假设某股票在1月1日收盘价为20元。2月1日进行了1拆2,无现金红利,忽略税费。

  • 1月1日原始成交价:20元
  • 2月1日除权参考价:10元(不等于实际开盘成交价)

第一次下载,时点为1月15日,拆股尚未发生。此时没有复权事件,前复权序列中1月1日仍显示20元。

第二次下载,拆股已完成后。系统以最新交易日为基准日重建前复权序列。因1拆2,历史价格会乘以0.5以保持序列连续。1月1日的前复权价变为10元。

同一日期,同一原始成交,前复权值变为原来的一半。

同一个数字变为原来的一半——不是数据错了,是你两次查询时,这把尺的零刻度线不在同一个位置。

实际除权参考价计算中,现金红利、配股价格和股份变动比例都可能进入公式,本例仅演示最简单的拆股场景。除权参考价的计算方式,可参考深圳证券交易所公布的除权除息参考价公式。


哪些逻辑更容易受影响

复权值变化对不同策略的影响程度不同。有些策略对绝对值敏感,有些只依赖相对比例。

更容易受影响的逻辑原因
基于绝对价格阈值的条件复权后数值变化可能改变条件触发与否
固定限价委托模拟限价基于复权价时,复权值变化导致成交判断偏移
按股数计算仓位的头寸拆股事件改变每股价格,但股数会同步调整,复权值变化使持仓市值计算需要重新对齐
精确撮合成本估算成本锚定在特定数值上,复权变化影响冲击成本估计

同一区间被统一缩放时,部分比例关系可能变化较小,但仍需逐项检查策略逻辑。


一份回测数据版本记录清单

如果你希望回测结果未来可复现,保存数据时至少记录以下信息:

  • 数据源名称及版本或接口地址
  • 数据抓取的具体日期
  • 复权方式(不复权、前复权、后复权)
  • 复权因子来源及计算日期
  • 品种代码格式
  • 所用时间频率和时区
  • 停牌期间处理方式
  • 缺失数据填充规则
  • 股息、拆股等公司行为数据的获取方式和时间戳

这九项不是教条。它们想表达的核心只有一件事——这类复现问题的关键往往不是随机性,而是数据版本未同步。


前复权的合理用途与边界

前复权存在时变性,不代表它没有合理用途。它消除了分红送股带来的价格跳空,让历史走势在视觉和统计上连续可比。问题是它容易让人产生一种错觉——以为下载一次的历史序列是客观事实,以后不会变。

它的合理使用边界是:接受它的数值会随时间变化,把它看作一个按数据源的基准日和复权规则计算的派生序列;当基准日或权益事件信息变化时,其历史数值可能重算。 如果你需要固定的历史档案来复现回测,不能只保存前复权值,需要保留原始成交和复权因子。

PIT是另一种解决思路——不是另一种价格公式,而是规定信息可得性和版本纪律。PIT的含义是:回测到某个历史决策时点时,只能使用该时点已经可得的数据和公司行为信息,不能把后来才出现或后来修订的信息倒灌回去。


本文仅讨论数据处理与回测复现,不构成投资建议。


你可能已经在想

“那直接用后复权不就好了?”

后复权的历史值确实稳定。但后复权的当前价格会随时间推移不断远离真实交易价,不能直接用来模拟实时委托价格。两种复权各有利弊,选择取决于你的具体用途,没有哪个在所有场景下都更好。

“是不是数据源不靠谱导致的?”

仅凭前复权值变化,不能判断数据源不可靠。前复权值变化的机制根植于其计算规则本身。差异可能来自不同的基准日规则、复权公式或参数版本。

“复权因子能自己算吗?”

理论上可以,如果你有每笔分红、送股和配股的精确记录,并严格按照交易所公布的除权除息参考价公式计算。实际操作中这件事的维护成本不低,不能给出一个放之四海皆准的万能公式。


一个行情接入层的小例子

以TickDB作为行情API接入层的例子,调用行情API后,研究者仍需自行保存原始响应、抓取时间和处理参数。行情API解决的是取数入口,复权口径和point-in-time数据版本仍属于研究数据治理问题。


你现在保存的,只是一份CSV,还是也保存了这份CSV当时怎么来的?

如果你有过回测结果对不上的经历,欢迎在评论区说说你当时查到的原因。是复权方式不同,还是数据源版本不一致,或者是其他你没想到的因素。


参考来源

  • 深圳证券交易所投资者教育中心,除权除息参考价计算公式说明
  • AKShare官方文档,股票数据接口说明
  • Tushare官方文档,复权因子接口说明及pro_bar参数说明
  • Glassnode文档,Point-in-Time指标定义
  • QuantConnect研究文档,关键概念——研究指南
  • QuantConnect云平台文档,数据集常见误解
  • TickDB API文档

相关文章

Python 接国内期货行情:脚本没报错,但判断全是错的——先查字段映射

用 Python 接国内期货行情,脚本跑通只是第一步。真正让监控误判、回测跑偏的,是三个更隐蔽的问题:volume_24h 和 volume 被当成同一个东西、last_price 和 close 被混用、异步处理只写了 async 没做去重和背压。本文基于 MCP 实测字段结构与审核事实库核验,用一张接口对照表、一段字段归一化示例和异步处理边界说明,帮你把这几个坑一次踩实。

TickDB Research ·

外汇行情还在更新吗?用 Python 订阅 EURUSD 并记录双时间

适合正在开发外汇报价监控、需要确认脚本持续收到行情的 Python 开发者。使用 TickDB 的 WebSocket 行情订阅,记录 EURUSD 报价、数据时间和本机接收时间,生成原始消息与 CSV。通过目标报价数量、接收间隔和数据时间推进情况,区分连接仍在、消息到达与数据更新。本次30秒订阅观察收到38条目标报价;代码支持有限运行和自动保存结果,方便在自己的环境复查。

TickDB Research ·

Codex股票分析实测:用TickDB MCP查A股行情、财报数据和估值

用Codex分析A股,怎样把行情、财报数据和估值放在一起看?本文以寒武纪为例,实测通过TickDB MCP获取历史行情、单季财务与PE估值,结合公司公告核对期间和口径,再用Python生成事实卡、整理个股研究笔记。附可复制的任务指令、真实输入和可运行代码,适合个人研究者与AI投研产品团队,减少重复查数和整理。

TickDB Research ·

A股历史数据下载:回测结果变了,先别急着改策略

同一只股票,换一份历史数据,研究结果为什么对不上?这篇写给定期做A股研究、准备回测输入的小团队,以及负责研究功能的产品经理。我们用寒武纪的真实日线对照,拆开价格口径、样本范围和数据更新带来的差异,再说明怎样借助TickDB的历史行情、股票信息与复权查询,让研究表、脚本和AI工具有共同的数据依据。

TickDB Research ·

A股行情接口怎么选?AKShare、Tushare、TickDB按用途比较

给A股看板、研究页或AI助手选行情接口,产品经理首先要明确数据用于什么功能、需要怎样更新。本文按用途比较AKShare、Tushare与TickDB的具体入口,结合寒武纪的真实查询结果,给出候选选择表和一张填好的试用需求卡,方便与技术同事讨论接入。

TickDB Research ·