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

用户头像Jacktick
2026-10-29 发布

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

研究会上,如果两个人拿出不同的回测结果,讨论很容易落到参数、模型和交易规则上。可要是两个人用的历史价格原本就不同,后面的争论会绕很远:你以为在比较策略,实际连输入都没对齐。

先确认用的是哪份行情,再判断研究方法要不要改。TickDB提供统一的市场数据访问服务,历史行情、股票信息、交易日和复权相关查询可以围绕同一标的组织起来,并通过程序和AI工具使用。对研究团队而言,这意味着取数之后,还能沿着原来的对象和条件回查差异,把依据交给同事继续验证。

一、研究结果对不上,先分清什么变了

看到结果变化,先把问题拆到能检查的位置:

先问什么 怎样检查 对下一步有什么帮助
查的是同一只股票吗 对照完整代码、市场、币种 排除简称相似或对象选错
用的是同一段历史吗 对照起止日期、周期及实际返回日期 避免拿不同样本讨论同一个结果
价格口径相同吗 对照不复权、前复权或后复权设置 判断差异是否来自价格处理
输入版本变过吗 对照取数时间、原始记录和更新差异 找出新增、修订或重复记录

这些问题确认之后,团队才能更清楚地讨论模型、交易成本和执行假设。对于不写代码的产品经理,这也是一份可以直接向技术同事提出的问题清单。

尤其要留意第三项:两列都叫“收盘价”,背后可能采用不同的处理方式。

image.png

图1:两条刻度带表示不同价格口径,不表示供应商优劣或投资结果。

二、寒武纪对照:两列收盘价,差异从哪里来

2026年10月28日,我们通过TickDB MCP查询寒武纪688256.SH,日期固定为4月20日至5月15日,周期固定为日线,只切换价格口径:一份不复权,一份前复权。

两次各返回17条记录,日期逐一对应。取其中相邻的两个交易日:

日期 不复权收盘价(元) 前复权收盘价(元)
2026-05-07 1868.00 1252.680723
2026-05-08 1182.53 1182.530000

如果一张图使用左列,另一张图使用右列,5月7日到8日呈现的价格变化就会很不一样。

前复权价格经过调整,用于相应口径下的历史比较;它也不应被拿来当作当日实际可成交的报价。研究时,需要先确定自己要回答的是“当时交易在什么价格”,还是“经过调整的价格序列怎样变化”。

同次查询中,TickDB返回的复权因子记录时间对应5月8日。我们按照因子,把适用日期的不复权开高低收重新计算,与前复权返回对照:17个交易日的68个价格值,误差均小于0.000001元,最大差异约为0.0000004924元。

这让价格差异有了可检查的解释。团队可以先统一序列,再重新运行自己的研究,不必一开始就凭图形猜测是哪里出了问题。

image.png

图2:依据2026年10月28日真实返回绘制,横轴按返回交易日排列。两条线分别为不复权与前复权收盘价,非策略收益曲线。

用知名数据库,也要先选清楚价格口径

哈佛商学院Baker Library在介绍如何查询CRSP股票价格时,专门提醒读者取到的是未复权价格。这条提醒适用于它介绍的查询场景,也说明研究人员需要主动确认价格处理方式。资料名称为《Finding a time series of stock prices in CRSP》。

对A股历史数据,同样要把口径写进取数要求。TickDB官方文档列明不复权、前复权和后复权选项,并提醒复权历史可能随公司行动或数据更新调整。TickDB K线文档

把口径留在数据旁边。几个月后同事重新打开文件,就能知道当时用的是什么,少一次凭记忆重建过程的麻烦。

三、为什么研究团队值得考虑TickDB这类接入方式

只看“能下载日线”,很多方案都能进入候选。真正影响采用决定的,是下载之后,团队还要让这些数据去哪里、由谁继续使用。

从拿到文件,走到能按条件回查

一份CSV可以交付结果,但遇到差异时,还需要知道它怎样生成。

在本例中,股票身份、历史日线、复权因子都能围绕寒武纪查询;上一轮还取得了交易日历,用来核对研究区间。产品团队可以把这些输入安排成连续步骤:先选对对象,再确定区间和口径,取得数据后检查日期,价格有差异时回查调整依据。

TickDB在这里提供的是一组能协作的数据查询能力。保存原始返回、生成研究表和记录修改,则由团队的程序完成。

让程序和AI围绕同一次输入工作

研究员在表格里看走势,开发者在脚本里计算,AI助手负责整理说明。如果各自临时取一份数据,日期和口径很容易悄悄分开。

TickDB提供API及MCP、CLI等工具访问路径,团队可以按自己的使用方式组织查询。我们这次使用MCP取得结构化结果,再保留当次返回,供表格和复核使用。TickDB AI工具说明

要让后来的人使用相同输入,关键还在于保存这次查询的快照,并让程序或AI明确引用它。仅仅使用同一家服务,仍需要团队约定具体对象、日期和口径。

研究范围扩大时,继续比较接入工作

TickDB的产品范围还包括港股、美股等市场;按需历史查询与持续行情订阅也有各自入口。团队准备增加市场、把研究功能接入看板或AI工具时,可以在同一产品体系下继续核对所需数据和访问方式。

这正是统一服务值得评估的地方:后续任务增加时,哪些接入方式和取数组织可以沿用,哪些市场规则仍需分别处理。具体字段、历史范围、权限和交易时间,要按新增任务确认。历史查询文档、持续订阅文档

什么情况下,其他方式也很合适

一次性看一段历史,手工下载的小表就很直接。已经在Python里研究的团队,也可以继续使用熟悉的数据接口库;例如AKShare官方将其定位为Python财经数据接口库。

当需求扩展到反复查询、多人协作、程序与AI使用,以及后续市场扩展时,就值得把TickDB的托管数据访问方式放进试用范围,比较整项任务需要投入的接入和维护工作。

四、数据更新以后,怎样知道旧研究还用得上

研究资料会继续更新,旧记录也要留住。

2026年10月27日,我们做过一轮寒武纪历史日线的分段更新验证:初始区间为9月1日至10月16日,更新区间为10月15日至26日,均为日线、不复权。

结果如下:

检查项 实际结果
初始记录 28条
更新记录 8条
重叠且一致 2条
新增日期 6个
重叠记录变化 0条
合并后 34条

合并后的34条与同区间整段查询逐条一致。把同一批更新再次交给程序处理,记录数仍为34,没有重复追加。

这组检查为后续更新提供了一个具体做法:把新增、重复和变化分开记录。数据有修订时,先留出旧值与新值,再决定怎样更新研究输入;如果更早的复权历史受到影响,应扩大重取区间,重新生成相应研究结果。

保留旧输入,才能解释新结果。团队讨论结果差异时,可以把数据变化与研究方法变化分别拿出来核对。

五、直接带走:一条取数指令,一段价格核验代码

不写代码,可以把这段要求交给MCP助手

在已接入TickDB MCP、具备相应查询权限的工具中,可以复制下面的任务要求。助手需要实际调用工具;遇到错误或权限不足,就返回错误,不用估算值填表。

使用TickDB MCP查询寒武纪688256.SH,type=stock,interval=1d。
查询区间:2026-04-20 00:00:00至2026-05-15 23:59:59.999,Asia/Shanghai。
分别调用get_kline,adjust=none与forward,limit=100。
再调用get_ex_factors,查询同一股票、同一区间的复权因子。
将起止时间转换为Unix毫秒。保存查询参数、实际取数时间和原始返回。
将两份日线按北京时间日期对齐,输出:日期、不复权收盘价、前复权收盘价。
另外报告两份记录数、重复日期、仅在其中一份出现的日期。
查询失败就报告失败;不得补造缺失记录,不得把复权价格当作实际成交价。

这是一份可复用的取数任务描述。本文10月28日的查询各返回17条;以后重查时,应保存新结果与旧记录对照。

技术同事,可以先运行这个价格核验例子

下面用上表两条真实记录和同次返回的前复权因子,演示怎样检查“调整后的价格是否算得回来”。复制为check_basis.py,用Python 3运行python3 check_basis.py即可,不需要安装第三方库或填写密钥。

from decimal import Decimal

# 本文2026-10-28采集快照中的两条收盘价
rows = [
    ("2026-05-07", "1868.00", "1252.680723"),
    ("2026-05-08", "1182.53", "1182.530000"),
]
event_date = "2026-05-08"
factor_a = Decimal("0.6705999589592825")
factor_b = Decimal("0")
tolerance = Decimal("0.000001")

for date, raw, adjusted in rows:
    price = Decimal(raw)
    # 此样本只含一个forward因子事件;仅调整事件之前的价格
    expected = price * factor_a + factor_b if date < event_date else price
    error = abs(expected - Decimal(adjusted))
    result = "通过" if error < tolerance else "需检查"
    print(f"{date} 复算={expected:.6f} {result}")
    if error >= tolerance:
        raise ValueError(f"{date} 价格差异={error}")

本地实际输出:

2026-05-07 复算=1252.680723 通过
2026-05-08 复算=1182.530000 通过

这一小段可以看清为什么两个口径得到不同价格,也能改成逐行核对自己的数据。这里固定使用采集快照中的一个因子事件;用于其他区间时,要查询对应因子,按适用日期和顺序处理多个事件。接口查询与本地复算是两步,这段代码只做后一步。

产品经理,可以直接转发这份交接卡

查询寒武纪688256.SH的指定区间日线,明确周期、复权方式、币种和北京时间日期。保存原始返回、查询条件与取数时间,整理后按日期排序。后续更新核对重叠日期,分别记录新增、相同和变化项;价格口径不同的序列分开保存。需要复查时,按原条件查询,或结合复权因子解释差异。表格、脚本和AI使用已保存的同次输入时,注明所用版本。

对于负责选型或研究功能的产品经理,试用结束时可以检查三个结果:同事能否找回当时输入,差异能否定位到具体记录,下一次增加任务时需要重新接哪些环节。

这些结果,比“接口返回成功”更接近团队真正要交付的研究能力。

固定区间查询还涉及账户条件。TickDB当前文档说明,免费版可查询K线,但不支持使用起止时间指定范围;按自己的研究区间试接前,先确认对应权限。查询条件与权限

第一次试用,先做哪一步?

选一只股票、一个明确日期区间和一种价格口径。保存返回与取数条件,做出能核对的小表,再让同事按这份说明复查。

数据或研究结果对不上,先查什么?

先查股票、日期范围、周期、复权方式和输入版本。确认发生了什么变化,再回到研究方法与计算假设;缺记录时结合交易日历、个股状态及接口规则补查。

下一步怎样用上TickDB的其他能力?

按实际任务选择:价格差异可补查复权依据,跨市场研究可验证新增市场的日线和时间规则,盘中观察再验证持续订阅。程序或AI继续使用数据时,把查询条件、保存版本和复核办法一起交接。

研究结果变动时,先能回答“我们当时用了什么”,后面的判断才有共同起点。

参考资料

  • TickDB K线查询:区间、周期、价格口径、权限及历史调整说明。
  • 哈佛商学院Baker Library,《Finding a time series of stock prices in CRSP》:所述查询场景中的未复权价格提醒。查阅于2026年10月28日。
  • TickDB AI工具:MCP、CLI等访问方式与适用任务。
  • AKShare官方仓库README:Python财经数据接口库的产品形态。查阅于2026年10月28日。

价格口径对照采集于2026年10月28日;更新验证采集于10月27日,均使用TickDB MCP。图表展示历史数据及本地核验结果,不是策略回测成绩或投资建议。

评论