4、数据质量初探:缺失值检测、异常值识别、重复数据检查、时间戳连续性验证
Tick 数据是高频交易的“原油”,其质量直接决定回测与实盘策略的可靠性。在进入标签校准之前,必须对原始数据进行系统性质量初探。本章聚焦四个核心维度:缺失值、异常值、重复数据与时间戳连续性,建立第一道数据防线。
核心原则: 数据清洗不是“删除一切可疑数据”,而是“标记、分类、决策”。保留可修复的记录,仅剔除无法恢复的噪声。
4.1 缺失值检测
Tick 数据中的缺失值通常表现为 NaN、空字符串或占位符(如 -1、0)。缺失可能发生在价格、成交量或买卖盘口字段。
| 缺失类型 | 常见原因 | 处理策略 |
|---|---|---|
| 价格缺失 | 交易所撮合中断、行情推送延迟 | 前向填充(ffill)或插值 |
| 成交量缺失 | 零成交时段、数据记录截断 | 填充 0 或剔除该 tick |
| 买卖盘口缺失 | 深度快照丢失、Level2 数据不完整 | 使用上一档位数据填充 |
# Python 示例:缺失值检测与统计
import pandas as pd
df = pd.read_parquet('tick_data.parquet')
missing_summary = df.isnull().sum()
missing_ratio = df.isnull().mean()
print("=== 缺失值统计 ===")
print(missing_summary[missing_summary > 0])
print("\n缺失比例:")
print(missing_ratio[missing_ratio > 0])
4.2 异常值识别
异常值指偏离正常市场行为的极端数据点,常见于价格跳空、负价格、成交量暴增等场景。识别方法包括统计阈值法与业务规则法。
- 统计阈值法: 使用 Z-score(|Z| > 3)或 IQR(Q1 - 1.5*IQR, Q3 + 1.5*IQR)识别离群点。
- 业务规则法: 价格 ≤ 0、成交量 < 0、买卖价差为负等明显违反市场逻辑的记录。
- 上下文验证: 单笔价格变动超过前一 tick 的 10% 且无成交配合,视为可疑。
# 异常值识别:IQR 方法
Q1 = df['price'].quantile(0.25)
Q3 = df['price'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = df[(df['price'] < lower_bound) | (df['price'] > upper_bound)]
print(f"检测到异常值数量:{len(outliers)}")
注意: 统计阈值法在极端行情(如闪崩、新闻冲击)下会误判正常波动。建议结合市场事件日历进行二次校验。
4.3 重复数据检查
重复数据通常由数据源推送重复、存储写入重试或拼接错误导致。重复记录会扭曲统计指标(如成交量累加、波动率计算)。
| 重复类型 | 特征 | 检测方法 |
|---|---|---|
| 完全重复 | 所有字段完全相同 | df.duplicated() |
| 时间戳重复 | 同一毫秒出现多条记录 | 按时间戳分组计数 > 1 |
| 价格成交量重复 | 价格与成交量相同但时间戳不同 | 按价格+成交量分组 |
# 重复数据检测
full_dups = df[df.duplicated(keep=False)]
ts_dups = df[df.duplicated(subset=['timestamp'], keep=False)]
print(f"完全重复行数:{len(full_dups)}")
print(f"时间戳重复行数:{len(ts_dups)}")
4.4 时间戳连续性验证
Tick 数据的时间戳必须严格递增且间隔合理。连续性验证可以发现数据缺失、排序错乱或时钟同步问题。
- 单调性检查: 确保
timestamp列严格递增,无回退。 - 间隔分布分析: 计算相邻 tick 的时间差,识别异常大间隔(数据缺失)或异常小间隔(重复或微秒级抖动)。
- 交易日边界: 检查每日首尾 tick 是否对齐交易所交易时段。
# 时间戳连续性验证
df = df.sort_values('timestamp').reset_index(drop=True)
df['time_diff'] = df['timestamp'].diff().dt.total_seconds()
# 检查单调性
is_monotonic = df['timestamp'].is_monotonic_increasing
print(f"时间戳是否单调递增:{is_monotonic}")
# 异常间隔
large_gaps = df[df['time_diff'] > 1.0] # 大于1秒视为异常
print(f"异常大间隔数量:{len(large_gaps)}")
实战建议: 对于间隔超过 5 秒的缺失段,建议标记为“数据空洞”,在后续标签校准中跳过该区间,避免生成虚假信号。
4.5 综合质量报告
完成上述四项检测后,应生成一份结构化质量报告,记录每个维度的检测结果与处理建议。报告格式建议如下:
| 检测维度 | 通过/失败 | 问题记录数 | 处理建议 |
|---|---|---|---|
| 缺失值检测 | ⚠️ 部分缺失 | 1,234 | 前向填充价格字段 |
| 异常值识别 | ❌ 失败 | 89 | 人工复核极端行情区间 |
| 重复数据检查 | ✅ 通过 | 0 | 无需处理 |
| 时间戳连续性 | ⚠️ 部分异常 | 5 个空洞 | 标记空洞区间,跳过标签校准 |
最佳实践: 将质量报告以 JSON 格式持久化存储,与清洗后的数据一同归档。后续每次回测或策略迭代时,先加载质量报告,确保数据版本可追溯。