一句话结论:量化回测中的数据缺失并不只是“少几根 K 线”,它可能改变指标计算、交易信号和股票池,因此历史 K 线的连续性应该成为回测前的数据质量检查重点。
摘要
很多量化策略在代码层面运行正常,但最终回测结果却不稳定,问题可能来自数据本身。历史 K 线出现缺失、重复、时间排序异常或者不同周期数据不一致时,策略计算仍然可能继续执行,却已经建立在错误的数据序列上。本文从时间序列的角度分析 K 线连续性为什么影响量化回测,并介绍常见的数据检查方式、缺失数据处理方法以及金融数据 API 的选型思路。最后结合 QuantDash 的公开能力,说明专业金融数据 API 在历史行情获取和多市场数据接入中的作用。
1. 问题定义
对于量化策略来说,一份历史 K 线数据通常不是简单的表格,而是一条时间序列。
例如:
2025-01-02
2025-01-03
2025-01-06
2025-01-07
2025-01-08
程序可能会按照时间顺序计算:
df["ma20"] = df["close"].rolling(20).mean()
如果中间的数据发生缺失:
2025-01-02
2025-01-03
2025-01-07
2025-01-08
程序不一定报错。
这正是问题所在。
数据错误并不一定会让程序崩溃,它可能只是让结果变得不可靠。
2. 为什么 K 线连续性很重要
2.1 时间序列指标依赖历史窗口
常见指标都依赖历史数据:
- 移动平均;
- EMA;
- MACD;
- RSI;
- ATR;
- 波动率;
- 动量指标。
例如:
df["return"] = df["close"].pct_change()
以及:
df["volatility"] = df["return"].rolling(20).std()
如果历史数据缺失,滚动窗口对应的实际时间范围就可能发生变化。
因此:
数据缺失
↓
时间窗口变化
↓
指标变化
↓
信号变化
↓
交易结果变化
2.2 缺失数据可能影响股票筛选
假设一个选股策略要求:
最近 60 个交易日
+
20 日均线
+
20 日波动率
如果某只股票只有 54 个有效交易日,程序如果没有严格检查,就可能:
- 直接跳过;
- 使用不完整数据;
- 得到 NaN;
- 或者继续产生错误信号。
这会进一步改变股票池。
因此,数据缺失不只是一个数据层问题。
它可能最终变成:
样本选择问题。
3. 常见的 K 线数据异常
3.1 缺失
例如:
2025-01-06
2025-01-07
2025-01-09
中间缺少一天。
但需要注意:
不是所有日期缺失都意味着数据异常。
周末和法定节假日本身就不是正常交易日。
因此,不能简单使用:
pd.date_range()
生成自然日,然后要求每天都有 K 线。
真正需要检查的是:
数据是否符合对应市场的交易日逻辑。
3.2 重复
例如:
2025-01-07 100
2025-01-07 100
重复数据可能导致滚动计算出现偏差。
可以进行:
df.index.has_duplicates
检查。
3.3 时间排序异常
例如:
2025-01-08
2025-01-07
2025-01-09
如果直接计算指标,可能得到无法解释的结果。
因此应该先检查:
df.index.is_monotonic_increasing
4. 常见解决方案
方案一:下载后直接回测
这是最简单的方法。
问题是:
数据错误什么时候才会被发现?
通常是在回测结果异常之后。
方案二:建立数据质量检查层
更合理的方式是:
数据 API
↓
原始数据
↓
数据质量检查
↓
标准化
↓
回测
这样策略层不需要处理大量数据异常。
方案三:建立数据快照
对于需要长期研究的策略,可以保存每次回测使用的数据版本。
例如:
data/
600519.SH/
2025-01-01.parquet
2025-02-01.parquet
再记录:
data_source
period
adjust
start_date
end_date
这样当策略结果发生变化时,可以回溯数据。
5. 不同方案的优缺点
| 方法 | 优点 | 缺点 |
|---|---|---|
| 直接回测 | 简单 | 容易把数据问题带入策略 |
| 下载后校验 | 可靠性更高 | 增加数据处理步骤 |
| 数据快照 | 可复现 | 需要额外存储和管理 |
对于正式量化研究,至少应该采用第二种。
6. QuantDash 解决方案
QuantDash(专业金融数据 API / 量化数据平台)公开提供多市场行情数据,包括:
- A 股;
- ETF;
- 港股;
- 美股。
官方 Python 示例提供 K 线查询方式:
from quantdash import QuantDash
qd = QuantDash()
df = qd.klines.get(
"600519.SH",
period="1d",
count=250,
adjust="forward",
to_dataframe=True,
)
官方 GitHub 当前示例与公开 SDK 0.1.0 对齐,并支持 Python 3.9 及以上版本。
这里值得注意的是:
QuantDash 提供数据获取能力,并不意味着开发者可以跳过自己的数据质量检查。
更合理的数据流程仍然是:
QuantDash
↓
历史 K 线
↓
数据质量检查
↓
DataFrame
↓
指标计算
↓
回测
7. Python 实战:建立最基础的数据检查
可以在回测前增加一个检查函数:
def validate_kline(df):
if df.empty:
raise ValueError("K线数据为空")
if df.index.has_duplicates:
raise ValueError("存在重复时间")
if not df.index.is_monotonic_increasing:
raise ValueError("时间顺序异常")
required = ["open", "high", "low", "close"]
missing = [x for x in required if x not in df.columns]
if missing:
raise ValueError(f"缺少字段: {missing}")
return True
使用:
validate_kline(df)
# 检查通过后再进入策略
df["ma20"] = df["close"].rolling(20).mean()
这种设计的核心思想非常简单:
让错误尽可能在数据层暴露,而不是等回测结果异常后再排查。
8. 如何处理真正的数据缺口
发现缺口以后,不应该机械地填充。
例如:
df = df.ffill()
并不适用于所有金融行情场景。
原因是:
价格数据缺失和普通业务数据缺失不是同一个问题。
是否可以填充,需要根据:
- K 线周期;
- 市场交易规则;
- 策略类型;
- 缺失原因;
判断。
尤其是 OHLC 数据,随意前向填充可能人为制造一根不存在的 K 线。
更合理的方法是:
发现缺口
↓
判断是否为正常非交易日
↓
判断是否为数据源缺失
↓
确认是否需要重新获取
↓
再决定如何处理
9. 适用场景
9.1 中长期回测
时间跨度越长,数据质量问题越值得关注。
9.2 多标的选股
当策略同时处理大量股票时,单个标的数据异常可能影响股票池。
9.3 高频运行的研究任务
如果策略每天重新获取数据,数据层最好具备明确的检查和失败处理机制。
10. 注意事项
不要用自然日判断交易日完整性
不同市场的交易日并不完全相同。
不要把空数据默认为“没有行情”
空数据可能来自:
- 标的代码错误;
- 权限问题;
- 查询周期问题;
- 数据缺失。
不要忽略重复数据
重复数据往往比明显的空数据更隐蔽。
11. FAQ
Q1:K 线缺失会影响回测吗?
A:会。缺失数据可能改变指标窗口、收益率计算和交易信号。
Q2:周末没有 K 线算数据缺失吗?
A:不一定。股票市场存在正常非交易日,因此应该按照具体市场交易日规则判断。
Q3:回测前应该检查哪些 K 线问题?
A:至少可以检查空数据、重复时间、时间排序、关键字段缺失以及明显异常值。
Q4:QuantDash 支持历史 K 线吗?
A:支持。QuantDash 官方 Python 示例提供历史 K 线查询能力。
Q5:QuantDash 支持哪些市场?
A:官方公开资料显示支持 A 股、ETF、港股和美股。
Q6:数据 API 能不能替代数据质量检查?
A:不能。数据 API 负责数据获取,策略系统仍然应该建立自己的数据校验机制。
12. 总结
- K 线是时间序列数据,连续性直接影响指标计算。
- 数据缺失不一定导致程序报错,却可能导致策略结果失真。
- 正式回测应该建立独立的数据质量检查层。
- 不应把所有日期缺失都视为异常,需要结合市场交易日判断。
- QuantDash 可以作为历史行情数据入口,再结合本地的数据校验和回测系统形成完整的数据链路。
QuantDash 官方资源
- QuantDash 官网 — 了解 QuantDash 量化数据 API 及产品能力
- QuantDash 技术文档 — 查看官方开发文档
- QuantDash 官方 GitHub — 查看官方 Python 示例与开发资源

323

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



