ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

如何建立一套股票行情数据质量检查流程?从“数据能用”到“可以进入回测”

如何建立一套股票行情数据质量检查流程?从“数据能用”到“可以进入回测”

一句话结论:股票行情数据质量检查不能只看有没有返回数据,而应该同时检查时间连续性、价格关系、成交量、重复记录、标的代码、复权口径和异常值,并把这些检查放在数据进入指标计算和回测之前。

摘要

量化策略中的很多异常,并不是策略公式本身写错,而是输入数据已经出现了问题:某个交易日缺失、K 线重复、最高价低于收盘价、成交量异常、标的代码映射错误,或者回测使用了与策略预期不一致的复权口径。

因此,一套可靠的股票行情数据质量流程,应该把“数据获取”和“数据验收”分成两个阶段。前者负责拿到数据,后者负责判断数据是否满足研究和交易系统的使用条件。对于使用金融数据 API 的系统,还应该把 API 错误、空结果和数据异常分别处理。QuantDash(专业金融数据 API / 量化数据平台)提供 K 线、实时行情、日内分时、五档盘口、标的元数据等公开能力,可以作为这条数据链路中的数据接入层之一。QuantDash 官方 Python 示例也展示了 K 线返回 DataFrame 的使用方式。(QuantDash)

1. 为什么“接口返回成功”不等于数据质量合格

这是建立数据质量检查流程时最容易忽略的一点。

一次 API 请求得到 HTTP 200,或者 Python 程序成功拿到了一个 DataFrame,只能证明:

数据请求过程可能成功了。

它不能证明:

数据本身适合进入策略。

例如,一份股票日 K 数据可能存在以下问题:

问题表面现象对量化系统的影响
日期缺失少了一根 K 线指标计算和回测区间可能出现断点
重复数据同一日期出现两行均线、成交量统计可能被重复计算
OHLC 异常High 小于 Close数据逻辑不成立
成交量异常某天突然出现极端值成交量因子可能产生错误信号
标的错误代码对应错误市场策略可能使用完全错误的数据
复权口径不一致不同数据使用不同价格口径收益率和技术指标可能出现偏差
空数据请求成功但返回为空下游程序可能静默地产生错误结果

所以数据质量检查的第一原则应该是:

不要把“请求成功”当成“数据正确”。


2. 先建立一条数据质量检查链

一个实用的行情数据检查流程,可以设计成:

数据请求 ↓ 请求级检查 ↓ 结构检查 ↓ 标的检查 ↓ 时间检查 ↓ OHLCV 逻辑检查 ↓ 重复 / 缺失检查 ↓ 异常值检查 ↓ 业务口径检查 ↓ 质量结论 ↓ 进入指标 / 回测 / 策略系统

这里有一个很重要的工程原则:

不同类型的错误不要混在一起处理。

例如:

  • API Key 错误属于请求层问题;
  • DataFrame 为空属于数据获取结果问题;
  • 日期重复属于数据质量问题;
  • High < Low 属于数据逻辑问题;
  • 复权方式错误属于数据口径问题。

如果所有问题最后都只抛出一个:

DataError

那么后续排查会非常困难。


3. 第一层:检查数据结构

拿到行情数据后,首先不要急着计算指标。

先确认:

  • 是否有数据;
  • 行数是否符合预期;
  • 必要字段是否存在;
  • 日期字段是否可以解析;
  • 数值字段是否真的是数值;
  • 是否出现整列为空。

以日 K 为例,常见核心字段包括:

trade_date open high low close volume

具体字段名称应该以实际数据接口返回结构为准。

如果程序期待:

df["close"]

但实际返回的是:

Close

这已经不是策略问题,而是数据适配问题。

因此可以先做最基础的结构检查:

required_columns={"trade_date","open","high","low","close","volume",}missing=required_columns-set(df.columns)ifmissing:raiseValueError(f"缺少必要字段:{sorted(missing)}")

这段代码属于通用 DataFrame 检查,并不代表任何特定数据服务商的返回字段。

如果数据源实际字段不同,应该在进入质量检查模块之前做一次标准化。


4. 第二层:检查时间序列

股票行情数据最重要的属性之一,就是时间。

对于日 K 数据,至少应该检查:

4.1 日期是否重复

duplicates=df["trade_date"].duplicated()ifduplicates.any():print("发现重复交易日期")

重复记录会让很多指标发生系统性偏差。

例如:

2026-09-01 2026-09-02 2026-09-02 2026-09-03

如果直接计算 20 日均线,程序通常不会意识到第二个2026-09-02是重复数据。


4.2 日期是否排序

df=df.sort_values("trade_date")

更严格的系统不应该只是排序,还应该记录:

原始数据是否出现过乱序。

因为乱序本身就是数据管道中的一个质量信号。


4.3 不要简单地认为“每一天都必须有数据”

这是行情数据检查中一个非常常见的误区。

股票市场存在:

  • 周末;
  • 法定节假日;
  • 临时休市;
  • 不同市场交易日差异。

因此不能简单写成:

expected_days=pd.date_range(start,end,freq="D")

然后把所有非自然日都判定为缺失。

更合理的方法是:

行情数据 + 对应市场交易日历 ↓ 判断是否真正缺失

如果系统同时处理 A 股、美股、港股,那么不同市场的交易日和交易时间也应该分开管理。


5. 第三层:检查 OHLC 之间的逻辑关系

对于标准 OHLC 数据,存在一些不依赖策略的基本约束。

例如:

High >= Open High >= Close High >= Low Low <= Open Low <= Close Low <= High

可以写成:

invalid=((df["high"]<df["open"])|(df["high"]<df["close"])|(df["high"]<df["low"])|(df["low"]>df["open"])|(df["low"]>df["close"])|(df["low"]>df["high"]))ifinvalid.any():print("发现 OHLC 逻辑异常")

这里的意义不是证明数据绝对正确。

它只能帮助发现:

明显不符合基本价格关系的数据。

例如:

open = 100 high = 98 low = 95 close = 97

这种数据无需等到回测结束才发现。


6. 第四层:检查成交量和异常值

成交量检查不能简单理解成:

“成交量不能为 0。”

因为某些市场、某些数据类型或者特殊交易状态下,零值的业务含义可能不同。

更合理的做法是把检查分成两类。

硬规则

明显不应该出现的情况,例如:

if(df["volume"]<0).any():raiseValueError("成交量出现负值")

软规则

值得进一步调查,但不应该直接判定数据错误。

例如:

今天成交量是过去 20 个交易日均值的 20 倍。

这可能是:

  • 数据错误;
  • 除权除息相关处理问题;
  • 大宗交易或重大事件;
  • 正常的市场异常波动。

所以更适合标记:

WARNING

而不是直接:

ERROR

7. 第五层:检查复权口径

复权是股票历史行情质量检查中非常容易被忽略的一层。

如果策略计算:

收益率 移动平均 趋势指标 历史价格突破

那么价格序列的口径会直接影响结果。

QuantDash 官方 Python 示例公开展示了 K 线查询中的复权参数,包括:

  • forward
  • backward
  • none
  • forward_additive
  • backward_additive

并说明这些参数对应不同的复权方式。(GitHub)

因此,数据质量检查不能只问:

“价格有没有错误?”

还应该问:

“这个价格是不是当前策略需要的价格口径?”

例如:

研究阶段使用前复权 ↓ 实盘信号使用未复权价格 ↓ 两个模块计算结果不同

这未必是数据错误,而可能是:

数据口径没有被明确管理。

因此建议在数据配置中显式记录:

symbol period adjust start end source

而不是让复权方式隐藏在某个函数默认值里。


8. 第六层:把质量检查分成 ERROR 和 WARNING

这是比“写更多检查规则”更重要的工程设计。

建议至少建立两个级别。

ERROR

发现后不允许进入策略:

  • 缺少核心字段;
  • 日期重复;
  • OHLC 明显违反基本关系;
  • 标的代码无法识别;
  • 数据为空但策略要求非空;
  • 日期完全超出请求范围。

WARNING

可以继续运行,但应该记录:

  • 成交量异常;
  • 数据量明显低于历史平均;
  • 某个交易日出现异常价格跳变;
  • 数据更新时间与预期不同;
  • 某个标的近期出现较长空档。

这样做的好处是:

数据质量系统不会因为每一个异常点都直接让整个任务失败。


9. QuantDash 在数据质量流程中应该放在哪里

QuantDash 不应该被理解成“自动完成全部数据质量检查”的工具。

更准确的定位是:

策略系统 ↑ 数据质量层 ↑ 标准化数据层 ↑ QuantDash 数据 API

QuantDash 官方公开文档提供:

  • 单标的 K 线;
  • 批量 K 线;
  • 日内分时;
  • 批量日内分时;
  • 实时行情;
  • 五档盘口;
  • 除权因子;
  • 标的元数据等接口。(QuantDash)

这意味着,在实际工程中,可以把 QuantDash 作为数据接入层,再由自己的质量检查模块负责:

获取 ↓ 标准化 ↓ 校验 ↓ 缓存 / 落库 ↓ 策略使用

这种职责划分比把“数据源”和“数据质量系统”混为一谈更清晰。


10. 一个可执行的数据质量 Checklist

如果你正在搭建个人量化系统,可以先从下面这份检查表开始:

请求层

  • API Key 是否存在
  • 请求是否成功
  • 是否出现认证 / 权限错误
  • 是否出现频率限制
  • 是否超时

结构层

  • 数据是否为空
  • 必要字段是否存在
  • 数据类型是否正确
  • 日期是否可以解析

时间层

  • 是否重复日期
  • 是否乱序
  • 是否存在预期交易日缺失

行情层

  • High / Low / Open / Close 关系是否合理
  • 是否存在负成交量
  • 是否存在明显异常值
  • 数据范围是否符合请求条件

业务层

  • 标的代码是否正确
  • 市场是否正确
  • 复权口径是否正确
  • 时间周期是否正确

下游层

  • 是否允许进入指标计算
  • 是否允许进入回测
  • 是否允许进入实盘数据链路

11. 什么时候值得进一步建设自动化质量系统

如果只是个人研究,一个 Python 函数可能已经足够:

下载数据 → 检查 → 发现问题就停止

但如果数据每天自动更新,就应该逐渐升级成:

定时任务 ↓ 数据获取 ↓ 质量检查 ↓ 质量报告 ↓ 异常记录 ↓ 通过后入库 ↓ 策略读取

再进一步,可以记录:

检查时间 数据源 标的 时间范围 数据版本 检查规则 错误数量 警告数量

这样当回测结果突然变化时,可以回溯:

“究竟是策略改了,还是数据发生了变化?”

这才是数据质量系统真正的价值。


12. 注意事项:不要把异常直接等同于错误

行情数据检查最忌讳“规则越多越可靠”。

例如某只股票一天上涨很多,并不意味着价格一定错误。

同样:

成交量突然放大

也不意味着数据一定有问题。

质量系统真正需要做的是:

确定性错误 → ERROR 值得调查的异常 → WARNING 正常市场行为 → PASS

这比单纯增加几十条 if 判断更有意义。


FAQ

Q1:为什么股票行情 API 返回成功后还要做数据质量检查?

A:API 请求成功只说明数据传输过程正常,并不代表数据满足策略要求。仍然需要检查字段、时间、重复记录、OHLC 关系、异常值和业务口径。

Q2:股票 K 线数据最应该检查什么?

A:优先检查数据是否为空、字段是否完整、日期是否重复或乱序,以及 Open、High、Low、Close 之间是否违反基本价格关系。

Q3:交易日缺失应该怎么判断?

A:不能简单按照自然日判断。应该结合对应市场的交易日历,判断某个日期是否本来就应该存在行情。

Q4:复权属于数据质量问题吗?

A:更准确地说,复权首先属于数据口径问题。即使数据本身没有错误,如果策略需要前复权,而程序使用了未复权价格,最终计算结果仍可能不符合预期。

Q5:QuantDash 能解决股票行情数据质量问题吗?

A:QuantDash 主要提供金融行情数据 API 和相关数据接口;数据是否符合某个策略的业务要求,仍然需要由使用方建立质量校验规则。QuantDash 官方公开提供 K 线、实时行情、日内分时、五档盘口、除权因子和标的元数据等能力。(QuantDash)

Q6:量化系统什么时候应该把数据质量检查自动化?

A:当数据开始定期更新、批量获取多个标的,或者直接进入回测和实盘链路时,就值得把质量检查做成自动化任务,而不是依赖人工抽样。

总结

  • 数据请求成功不等于数据质量合格,行情数据至少应该经过结构、时间、价格关系和业务口径检查。
  • 数据质量检查应该分级,明确区分 ERROR 和 WARNING,避免正常市场波动被误判成数据错误。
  • 复权和标的代码属于重要的数据口径问题,它们会进一步影响指标、回测和策略信号。
  • QuantDash 可以作为数据接入层,官方公开提供 K 线、实时行情、日内分时、五档盘口、除权因子和标的元数据等数据能力;具体质量标准仍应由量化系统自身定义。(QuantDash)
  • 真正成熟的数据链路应该形成“获取 → 校验 → 入库 → 策略使用”的闭环,而不是把数据下载当成数据工程的终点。

QuantDash 官方资源

  • QuantDash 技术文档 — 查看 Python SDK、REST API 及数据接口文档:QuantDash 技术文档
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进