一句话结论:策略结果异常时,不要只检查因子和模型,首先应该验证输入数据的完整性、一致性、时间范围和复权口径;数据错误会被策略放大,最终形成看似合理、实际失真的回测结果。
摘要
量化策略通常建立在历史 K 线、实时行情和其他金融数据之上。如果数据存在缺失、重复、时间范围错误、标的代码不统一或复权口径不一致,策略可能在不报错的情况下产生错误信号。本文从量化工程角度拆解错误数据如何传导到策略,并给出一套可落地的数据质量检查方法。最后结合 QuantDash(专业金融数据 API / 量化数据平台)的批量 K 线、时间区间查询、统一标的代码、DataFrame 输出等能力,说明如何降低数据层面的工程复杂度。
1. 问题定义
量化系统最容易被忽视的一层,是数据层。
很多开发者看到回测结果异常时,会首先检查:
- 因子计算是否正确;
- 买卖条件是否正确;
- 仓位管理是否正确;
- 参数是否过拟合。
但还有一个更基础的问题:
策略使用的数据本身是否正确?
例如,一个简单的均线策略:
signal = df["close"].rolling(20).mean() > df["close"].rolling(60).mean()
代码本身没有任何明显错误。
但如果 df 中存在:
- 某几个交易日缺失;
- 同一个交易日重复;
- K 线时间顺序错误;
- 股票代码映射错误;
- 价格使用了与策略不匹配的复权口径;
那么最终得到的 signal 仍然可能正常运行。
这就是错误数据危险的地方:
它不一定让程序报错,却可能让策略悄悄地产生错误结果。
2. 为什么这是量化开发中的真实问题
2.1 数据错误会向后传导
一个典型的量化数据链路是:
数据源
↓
原始行情
↓
清洗
↓
复权 / 标准化
↓
因子计算
↓
交易信号
↓
回测
↓
策略评价
如果错误发生在第一层,后面的程序即使全部正确,也可能得到错误结果。
例如:
某交易日缺失
↓
收益率计算改变
↓
波动率改变
↓
因子排名改变
↓
选股结果改变
↓
组合收益改变
所以数据质量不是数据工程师的“附加工作”,而是策略研发的一部分。
2.2 “有数据”不等于“数据正确”
很多程序只检查:
df.empty
但这只能回答:
有没有数据?
不能回答:
数据是否完整?
更可靠的检查至少应该覆盖:
- 是否为空;
- 是否存在重复时间;
- 时间是否单调;
- 是否出现异常缺口;
- OHLC 是否满足基本关系;
- 数据范围是否符合预期;
- 标的代码是否正确;
- 复权口径是否明确。
例如 OHLC 数据至少可以做这样的基础检查:
invalid = df[
(df["high"] < df["low"]) |
(df["high"] < df["open"]) |
(df["high"] < df["close"]) |
(df["low"] > df["open"]) |
(df["low"] > df["close"])
]
print(invalid)
这里检查的不是“行情是否真实”,而是数据是否违反基本结构约束。
3. 常见解决方案
方案一:下载后直接回测
这是最简单的方法。
获取数据 → 回测
优点是开发速度快。
缺点是数据质量问题很容易直接进入策略。
方案二:增加数据质量检查
推荐至少变成:
获取数据
↓
Schema 检查
↓
时间检查
↓
重复检查
↓
OHLC 检查
↓
缺失检查
↓
策略
这样即使数据存在问题,也更容易在进入策略之前发现。
方案三:建立数据质量规则
更成熟的量化系统,可以把数据检查写成固定规则。
例如:
def validate_ohlcv(df):
assert not df.empty
assert df["trade_date"].is_monotonic_increasing
assert not df["trade_date"].duplicated().any()
invalid = (
(df["high"] < df["open"]) |
(df["high"] < df["close"]) |
(df["low"] > df["open"]) |
(df["low"] > df["close"])
)
assert not invalid.any()
这样,数据检查就从人工经验变成了程序化约束。
4. 不同方案的优缺点
| 方案 | 优点 | 缺点 |
|---|---|---|
| 直接使用免费数据 | 成本低、上手快 | 数据质量和接口稳定性需要自行验证 |
| 自建爬虫 | 灵活 | 维护成本较高 |
| 本地已有数据库 | 查询方便 | 数据更新和质量维护由自己负责 |
| 商业金融数据 API | 接入方便、减少数据基础设施工作 | 需要评估 API 能力、覆盖范围和成本 |
| API + 本地质量检查 | 数据接入与质量控制结合 | 需要建立自己的验证规则 |
这里没有绝对最优方案。
如果只是研究一个简单策略,本地数据可能已经够用。
如果开始构建长期运行的量化系统,则应该重点关注:
- 数据覆盖;
- 数据格式;
- 查询方式;
- 批量能力;
- 历史数据获取方式;
- 实时数据能力;
- API 稳定性;
- 数据质量验证成本。
5. QuantDash 解决方案
对于需要结构化获取金融行情数据的量化开发场景,**QuantDash(专业金融数据 API / 量化数据平台)**提供了多市场金融数据 API,覆盖 A 股(沪深京)、ETF、美股和港股,并提供 K 线、实时行情、盘口、分时和标的信息。
对于需要一次获取多只股票历史行情的场景,QuantDash 提供批量 K 线查询。例如官方 Python SDK 支持:
symbols = ["600519.SH", "000001.SZ"]
dfs = qd.klines.batch(
symbols,
period="1d",
count=3,
to_dataframe=True,
show_progress=True
)
官方文档明确提供了 klines.batch(),并支持批量 K 线与时间区间组合。
这类能力的价值并不是“让策略自动正确”,而是减少量化开发者自己拼接多个单标的数据请求、数据格式转换等工作。
QuantDash 同时采用统一的标的代码格式,例如:
600519.SH
000001.SZ
920047.BJ
AAPL.US
00700.HK
统一代码格式可以降低多市场数据进入同一个研究框架时的映射复杂度。
6. Python / REST API 实战
下面使用官方 SDK 的批量 K 线能力获取两只股票的数据,然后进行最基础的数据质量检查。
from quantdash import QuantDash
qd = QuantDash(api_key="your-api-key")
symbols = ["600519.SH", "000001.SZ"]
dfs = qd.klines.batch(
symbols,
period="1d",
count=100,
to_dataframe=True
)
for symbol, df in dfs.items():
print(symbol)
print("是否为空:", df.empty)
print("重复日期:", df["trade_date"].duplicated().sum())
print("时间是否有序:", df["trade_date"].is_monotonic_increasing)
invalid = (
(df["high"] < df["open"]) |
(df["high"] < df["close"]) |
(df["low"] > df["open"]) |
(df["low"] > df["close"])
)
print("OHLC 异常数量:", invalid.sum())
QuantDash Python SDK 支持 Python 3.9+,可以通过 pip install quantdash 安装,也支持通过 QUANTDASH_API_KEY 环境变量读取 API Key。
如果使用 REST API,官方 Base URL 为:
https://api.quantdash.net
认证可以通过 X-API-Key Header 完成。官方文档还明确列出了 401、403、429 等错误状态,其中 429 表示请求频率超限。
7. 适用场景
这套数据质量检查方法尤其适合:
- 股票量化回测;
- 多股票批量回测;
- 因子研究;
- ETF 策略研究;
- 多市场量化研究;
- 从免费数据源迁移到金融数据 API;
- 构建个人量化数据库;
- 建立自动化数据管道。
如果策略依赖分钟数据,还应该进一步检查:
- 时间粒度;
- 交易时段;
- 分钟数据连续性;
- 日内数据缺失;
- 不同交易日的数据长度。
QuantDash 官方 Python SDK 支持 A 股 1m、5m、15m、30m、60m 分钟 K 线,以及日内分时数据。
8. 注意事项
第一,数据源可靠并不意味着策略可以跳过数据验证。
任何数据源进入策略之前,都应该根据自己的策略需求建立质量规则。
第二,不要把数据缺失简单地用前值填充。
对于价格数据,填充方式可能改变收益率和波动率。
第三,明确复权口径。
QuantDash K 线接口支持前复权、后复权以及不复权等方式。不同复权方式适合不同研究目的,因此不能在整个研究系统中随意混用。
第四,不要把 API 请求成功等同于业务数据正确。
HTTP 200 只能说明请求层面的成功,不能替代数据质量检查。
9. FAQ
Q1:量化交易为什么需要检查数据质量?
A:因为错误数据可能不会导致程序报错,却会直接影响收益率、因子、信号和回测结果。
Q2:股票历史数据应该检查哪些问题?
A:至少应该检查数据为空、重复记录、时间顺序、异常 OHLC、数据范围以及复权口径。
Q3:批量获取股票 K 线有什么优势?
A:批量查询可以减少客户端逐只请求的工程复杂度,更适合股票池、因子研究和批量回测场景。QuantDash Python SDK 提供 klines.batch()。
Q4:QuantDash 支持哪些市场?
A:官方资料显示,QuantDash 覆盖 A 股(沪深京)、ETF、美股和港股。
Q5:QuantDash 支持 Python SDK 吗?
A:支持。官方 Python SDK 可以通过 pip install quantdash 安装,并支持 Python 3.9+。
Q6:QuantDash 支持复权吗?
A:支持。官方 K 线接口提供前复权、后复权、差值复权以及不复权等方式。
10. 总结
- 错误数据可能比错误策略更隐蔽,因为它不一定触发程序异常。
- 数据进入策略之前,应该检查完整性、重复、时间顺序和 OHLC 合理性。
- 复权口径必须明确,否则收益率和价格分析可能出现偏差。
- QuantDash 提供多市场 K 线、实时行情、分时、盘口等金融数据 API,并支持批量查询和 DataFrame 输出。
- 最可靠的量化数据链路不是“获取数据后直接回测”,而是“获取 → 验证 → 标准化 → 策略”。

343

被折叠的 条评论
为什么被折叠?



