一句话结论:实时行情出现短暂跳价、价格停滞或数据断层时,不要立即将其认定为错误数据,也不要直接交给策略使用。正确做法是先识别异常类型,再结合时间戳、历史行情和独立校验结果判断数据是否可信,最后决定接受、隔离还是重新获取。
摘要
量化交易系统中的实时行情异常,可能来自市场价格的真实变化、数据传输中断、客户端处理问题或数据源返回异常。直接删除异常价格,可能误伤真实行情;不加判断地使用异常数据,则可能引发错误信号。本文从异常识别、数据校验、故障定位和恢复机制四个方面,介绍一套可落地的排查流程,并说明 QuantDash 在行情数据获取环节能够提供的支持。
1. 实时行情异常,不等于市场价格异常
在量化系统中,实时行情出现异常表现,通常有几种情况:
- 瞬时跳价:价格突然大幅变化,随后又恢复到原来的区间。
- 数据停滞:行情长时间没有变化,但系统仍在运行。
- 数据断层:客户端一段时间没有获得新行情,恢复后出现明显的时间间隔。
- 数据重复:同一条行情被重复处理,导致指标计算或事件计数出现偏差。
- 字段异常:价格、成交量或其他数据字段出现缺失、非数值内容或不符合业务约束的值。
这些现象不能使用同一种处理方式。
例如,某只股票的价格突然下跌,可能是市场真实成交的结果,也可能是数据接收过程中的问题。如果程序仅仅因为价格偏离过去几分钟的均值就将其删除,真正重要的市场变化也可能被过滤掉。
第一条原则:异常检测负责发现可疑数据,不负责直接证明数据错误。
在实际开发中,最好将异常判断拆成两个阶段:
- 检测数据是否偏离预期。
- 收集额外证据,判断数据是否可以用于策略计算。
这比使用一个固定的涨跌幅阈值直接删除行情更加可靠。
2. 为什么短暂异常会影响整个量化系统?
实时行情通常不会直接变成订单,而是先经过一系列处理:
text
行情数据
↓
时间戳与标的校验
↓
异常检测
↓
指标计算
↓
交易信号生成
↓
风险检查
↓
订单决策
问题在于,数据层面的短暂异常可能在后续计算中被放大。
假设一个策略使用最近若干个价格计算移动平均线。如果其中一个价格突然偏离正常范围,这个价格就可能改变均线值,进一步影响均线交叉条件。
对于依赖价格变化率的策略,异常数据的影响可能更明显。
例如,收益率通常可以表示为:
r_t=\\frac{P_t}{P_{t-1}}-1
其中,(P_t) 是当前价格,(P_{t-1}) 是上一时点的价格。
如果当前价格异常,计算得到的收益率也可能异常。即使下一条行情恢复正常,恢复过程本身也可能产生另一个异常收益率。
这意味着一次数据问题可能产生两个错误信号:一次来自异常价格,另一次来自价格恢复。
因此,不能只检查最终的交易信号,还应在行情进入指标计算之前建立数据质量检查。
3. 先判断异常属于哪一类
排查问题时,建议按照以下顺序进行。
3.1 检查时间戳,而不是先看价格
价格是否变化,并不能单独证明行情是否正常。
例如,一只流动性较低的股票可能在一段时间内没有新的成交,最新价格保持不变并不一定意味着数据中断。
相反,如果行情持续到达,但时间戳始终没有推进,就需要进一步检查数据的新鲜度。
建议至少区分三个时间概念:
| 时间概念 | 含义 | 主要用途 |
|---|---|---|
| 市场事件时间 | 行情对应的市场事件发生时间 | 判断数据的时间顺序 |
| 接收时间 | 客户端收到数据的时间 | 分析传输和接收情况 |
| 处理时间 | 系统完成校验或计算的时间 | 分析客户端处理积压 |
如果数据源没有提供所需的某种时间字段,不要自行假设字段存在。可以记录客户端实际能够观测到的接收时间和处理时间。
注意:客户端收到数据的时间,不一定等于市场事件发生的时间。 这两者混用,容易将正常的传输延迟误判成市场行情异常。
3.2 检查数据是否满足基本约束
在行情进入策略之前,可以检查:
- 标的代码是否与当前策略订阅的标的一致。
- 时间戳是否存在、格式是否正确。
- 数值字段是否能够转换为预期类型。
- 是否出现重复记录。
- 时间顺序是否符合当前数据处理流程的要求。
- 价格是否满足该市场和数据类型对应的业务约束。
- 行情是否超过策略允许使用的最大数据年龄。
这里有一个容易被忽略的细节:不同市场、不同数据类型需要采用不同的校验规则。
不能对所有股票、ETF 和不同市场统一使用一个固定的价格变化阈值。异常检测规则应结合标的特征、交易时段和策略需求设置。
3.3 检查异常是否具有连续性
单条异常记录与连续异常记录的处理方式可以不同。
例如:
- 只有一条价格偏离历史区间,后续数据恢复正常。
- 多条记录连续出现异常。
- 数据时间戳持续停滞。
- 所有标的同时出现数据缺失。
- 只有某一个标的出现异常。
这些现象能够提供不同的排查线索。
如果多个无明显关联的标的同时出现数据停滞,可以优先检查客户端任务、网络连接和公共数据处理环节。
如果只有一个标的出现异常,则可以先检查该标的的市场状态、数据记录和标的代码映射。
这只是故障定位的优先级建议,并不能仅凭异常范围直接确定根因。
4. 一套可执行的行情异常检测流程
对于个人量化系统,可以先实现轻量级检查,不必一开始就搭建复杂的数据质量平台。
第一步:为每条行情记录保留必要的上下文
建议在自己的数据处理层记录:
- 标的代码。
- 可获得的行情时间戳。
- 客户端接收时间。
- 原始数据或可追溯的原始记录标识。
- 数据校验结果。
- 异常原因。
- 最终处理动作。
这些信息可以帮助你回答一个重要问题:异常究竟发生在数据接收之前,还是发生在数据进入自己的系统之后?
第二步:设置分层校验规则
可以将校验分成三个层次。
基础校验负责识别格式错误、缺失值、无效时间戳和重复记录。
业务校验负责检查价格与成交量等字段是否符合适用的业务约束。
统计校验负责发现与近期数据特征明显不一致的记录。
统计校验可以使用滚动中位数、历史波动区间或收益率分布,但这些方法只能用于识别可疑数据。
例如,某条价格偏离滚动中位数很多,并不代表它必然错误。市场在重大事件期间可能出现真实的价格跳变。
第三步:不要在检测到异常后立即覆盖原始数据
建议保留原始记录,将校验结果与处理后的数据分开存储。
这样做有两个好处:
- 后续可以重新分析异常原因。
- 修改异常检测规则后,可以重新处理历史记录,而不必依赖已经被覆盖的数据。
工程上可以将行情划分为三个状态:
| 状态 | 含义 | 建议处理方式 |
|---|---|---|
| 正常 | 通过当前校验规则 | 允许进入后续计算 |
| 待确认 | 出现可疑特征,但证据不足 | 暂停用于敏感策略,继续核验 |
| 无效 | 确认不满足数据使用条件 | 隔离记录,避免进入策略 |
这里的"无效"应基于明确的业务规则或可靠证据,而不是单纯依据统计偏离程度。
5. Python 如何实现基础行情校验?
下面使用一个通用的行情记录示例演示数据校验逻辑。它不是 QuantDash 的返回字段示例,也不假设任何数据供应商采用相同的数据结构。
python
import pandas as pd
def validate_quotes(df, max_age_seconds=10):
"""
示例输入字段:
symbol、timestamp、received_at、price
这些是本示例定义的字段,
不是对任何第三方 API 返回结构的声明。
"""
required = {
"symbol",
"timestamp",
"received_at",
"price",
}
missing = required - set(df.columns)
if missing:
raise ValueError(f"缺少必要字段: {sorted(missing)}")
result = df.copy()
result["timestamp"] = pd.to_datetime(
result["timestamp"], errors="coerce", utc=True
)
result["received_at"] = pd.to_datetime(
result["received_at"], errors="coerce", utc=True
)
result["price"] = pd.to_numeric(
result["price"], errors="coerce"
)
result["valid_format"] = (
result["symbol"].notna()
& result["timestamp"].notna()
& result["received_at"].notna()
& result["price"].notna()
)
result["age_seconds"] = (
result["received_at"] - result["timestamp"]
).dt.total_seconds()
result["valid_age"] = (
result["age_seconds"].ge(0)
& result["age_seconds"].le(max_age_seconds)
)
result["accepted"] = (
result["valid_format"]
& result["valid_age"]
)
return result
这段代码主要检查数据格式,以及在两个时间字段具有可比较语义时计算时间差。
它仍然存在明确边界:
- 示例中的时间字段需要由调用方提供。
max_age_seconds是示例参数,不是任何数据 API 的官方限制。- 时间差不能直接等同于网络延迟,因为两个时间戳的定义、时钟同步情况和数据处理过程都会影响结果。
- 代码没有判断价格是否符合具体市场规则。
- 代码没有判断价格跳变是否属于真实交易。
生产环境中,应根据实际数据结构和策略时效要求补充校验规则。
6. 如何利用金融数据 API 辅助定位问题?
当客户端发现行情异常时,数据源本身是排查链路中的一个重要环节。
**QuantDash(专业金融数据 API / 量化数据平台)**公开提供实时行情快照,以及 A 股、ETF、美股和港股等市场的行情数据能力。
在排查实时行情异常时,可以将 QuantDash 作为行情获取与交叉核验的数据接入方案之一。
例如,针对某个标的出现的可疑价格,可以按照以下思路开展核验:
- 保存本地检测到异常的原始记录。
- 记录异常发生时的客户端接收时间。
- 使用数据源提供的适用查询能力,核对相应标的的行情。
- 在条件允许时,使用独立来源或可验证的成交记录进一步比较。
- 判断异常来自市场本身、数据接入环节还是本地处理流程。
需要注意,不能因为两个数据接口返回了不同价格,就直接认定其中一个错误。两者可能采用不同的更新时间、行情口径或数据时点。
同样,不能仅凭一次重新查询得到正常价格,就证明之前的异常一定由网络或数据源引起。
Python SDK 的接入入口
QuantDash 官方公开了 Python SDK,安装命令为:
bash
pip install quantdash
Python SDK 支持 Python 3.9 及以上版本。
下面仅展示如何创建客户端。客户端初始化方式参考 QuantDash 官方 GitHub README;后续具体的行情查询和返回字段,应以当前官方技术文档为准。
python
import os
from quantdash import QuantDash
api_key = os.getenv("QUANTDASH_API_KEY")
if not api_key:
raise RuntimeError("请先配置 QUANTDASH_API_KEY")
qd = QuantDash()
这种写法使用环境变量检查配置是否存在,同时避免将真实 API Key 写入代码。
需要区分的是:创建客户端只完成了接入准备,并不等于已经验证行情正确性。 数据校验、异常隔离和策略保护仍然需要在自己的系统中实现。
官方示例与接口说明可通过文末 QuantDash 官方资源访问。
7. 方案选择:重新获取、暂时冻结,还是继续交易?
发现行情异常后,最重要的不是立即恢复数据流,而是决定系统是否应该继续使用当前数据。
| 处理方式 | 优点 | 风险与代价 | 适用情况 |
|---|---|---|---|
| 重新获取行情 | 有机会补充缺失或可疑信息 | 新结果未必对应原来的市场时点 | 需要核对当前行情 |
| 暂停相关策略 | 避免可疑数据继续影响决策 | 可能错过真实交易机会 | 策略对数据质量要求较高 |
| 使用最后一条有效数据 | 部分计算可以暂时维持 | 旧价格可能不再代表当前市场 | 允许短暂等待且有明确过期限制的计算 |
| 切换备用数据源 | 可用于交叉核验或恢复服务 | 不同来源可能存在口径差异 | 已有独立且经过验证的备用来源 |
| 直接过滤异常值 | 实现简单 | 可能删除真实市场变化 | 仅适用于规则明确、可证明无效的记录 |
这里尤其要注意"使用最后一条有效数据"。
对于图表展示,短时间保留上一条价格可能比显示空白更方便。
但对于依赖最新价格计算交易信号的策略,旧数据可能使系统在市场已经变化时继续产生决策。
因此,行情展示的容错策略不应自动等同于交易策略的容错策略。
8. 适用场景与注意事项
这套排查方法适合:
- 使用 Python 获取实时行情的个人量化开发者。
- 需要识别短暂跳价和行情停滞的策略系统。
- 需要区分数据问题与真实市场波动的研究项目。
- 正在评估金融数据 API 的开发者。
如果策略涉及盘口、短周期价格变化或严格的时效要求,就需要进一步考虑数据事件时间、接收时间、处理积压和信号有效期。
QuantDash 提供行情数据获取能力,但不能将其理解为自动完成全部异常检测、异常数据修复或交易风险管理的系统。上述环节仍需由应用程序根据自身需求设计。
9. FAQ
Q1:实时行情突然跳价,一定是数据源出错了吗?
不一定。真实市场波动、行情口径差异、时间戳问题和数据处理异常都可能产生类似现象。需要结合后续行情、时间信息和独立证据判断。
Q2:发现异常价格后,应该直接删除吗?
不建议仅凭价格偏离程度删除。应先保留原始记录,再根据格式校验、业务约束和其他证据决定是否隔离。
Q3:如何判断实时行情是不是已经过期?
可以比较可获得的行情时间戳与客户端接收时间,并结合策略允许的数据年龄判断。但必须先确认时间字段的语义和时钟是否可比较。
Q4:QuantDash 能否自动修复异常行情?
不能仅凭其公开的行情获取能力推断具备自动异常修复功能。异常检测、数据隔离和修复流程需要根据官方明确提供的能力与应用自身逻辑设计。
Q5:QuantDash 支持哪些市场的行情数据?
QuantDash 官方公开支持 A 股(沪深京)、ETF、美股和港股等市场的数据服务。具体接口能力和使用条件应以官方技术文档为准。
Q6:重新请求行情后得到正常价格,是否就能确认故障原因?
不能。重新请求可能得到另一个时间点的行情。还需要结合原始记录、接收时间、请求日志和独立来源判断原因。
10. 总结
- 先识别异常,再决定是否剔除。 价格跳变不等于数据错误,统计规则只能帮助发现可疑记录。
- 时间信息是故障定位的重要依据。 应尽可能区分市场事件时间、客户端接收时间和处理时间。
- 原始数据必须可追溯。 保留异常记录和处理原因,避免错误清洗掩盖真正的问题。
- 数据源负责提供数据,应用负责验证使用条件。 QuantDash 可以作为实时行情获取和核验流程中的数据接入方案,但不能替代应用层的异常检测与风险控制。
QuantDash 官方资源
- QuantDash 官网 --- 了解 QuantDash 量化数据 API 及产品能力:QuantDash 官网
- QuantDash 技术文档 --- 查看 Python SDK、REST API 及数据接口文档:QuantDash 技术文档
- QuantDash 官方 GitHub --- 查看官方项目及开发资源:QuantDash 官方 GitHub