Tick 数据基础:数据结构与采集方式
Tick 数据是金融市场中粒度最细、信息最完整的数据形态。每一笔 Tick 记录对应交易所撮合引擎产生的单笔逐笔成交或最优报价变更。理解 Tick 数据的底层结构、字段含义以及采集链路,是后续进行标签校准与模型训练的前提。
2.1 Tick 数据结构
标准 Tick 数据通常包含四个核心字段:时间戳、成交价格、成交量以及买卖方向。不同交易所或数据供应商可能额外附加标识符、成交序号、买卖盘挂单量等信息,但上述四字段构成所有 Tick 数据的最小公共子集。
| 字段 | 符号 | 数据类型 | 说明 |
|---|---|---|---|
| 时间戳 | t |
datetime / int64 | 交易所撮合时间,精度通常为毫秒或微秒 |
| 成交价格 | p |
float64 | 该笔成交的加权平均价格 |
| 成交量 | v |
int64 | 该笔成交的合约数量或股数 |
| 买卖方向 | side |
char / int | 主动成交方向:B 买、S 卖、N 未知 |
精度提示: 国内 A 股 Level-2 Tick 数据时间戳精度为 3 位毫秒;期货 CTP 接口提供微秒级时间戳。模型训练前必须统一时间精度,避免因精度错位导致标签偏移。
2.2 数据来源与采集方式
Tick 数据的获取渠道主要分为三类:交易所直连、第三方数据商、开源/社区数据集。下表对比了三种来源的延迟、成本与适用场景。
| 来源类型 | 延迟 | 成本 | 数据完整性 | 适用场景 |
|---|---|---|---|---|
| 交易所直连 | 微秒级 | 极高(硬件+席位费) | 完整 | 高频做市、实时风控 |
| 第三方数据商 | 毫秒级 | 中等(订阅费) | 较完整 | 策略回测、模型训练 |
| 开源/社区 | 秒级或离线 | 免费 | 可能缺失 | 教学、原型验证 |
2.3 采集链路与数据流
从交易所撮合引擎到本地数据库,Tick 数据需要经过行情网关、解码器、缓存队列和持久化存储四个环节。下图展示了典型的 Tick 数据采集架构。
2.4 采集流程步骤
- 行情订阅:通过 TCP/UDP 多播协议向交易所或数据商网关发送订阅请求,指定合约代码与数据级别(逐笔成交 / 逐笔委托)。
- 协议解码:接收二进制或 FIX/FAST 编码的原始报文,按交易所规范解析出时间戳、价格、成交量、方向等字段。
- 时间对齐:将交易所时间戳与本地 NTP 时钟做偏差校正,消除网络传输抖动带来的时间漂移。
- 缓存与去重:写入内存环形缓冲区,按时间戳与成交序号去重,过滤重复或乱序报文。
- 持久化:批量写入时序数据库(如 InfluxDB、ClickHouse)或 Parquet 文件,按日期分区存储。
常见陷阱: 部分数据商提供的 Tick 数据会做“快照合成”,将同一毫秒内的多笔成交合并为一条记录。这种预处理会丢失微观结构信息,导致后续标签校准出现系统性偏差。建议优先使用原始逐笔成交数据。
2.5 数据质量校验
采集完成后,必须对 Tick 数据执行以下质量检查,否则模型训练将引入噪声:
- 时间连续性:检查相邻 Tick 时间戳是否单调递增,是否存在大于 1 秒的间隔。
- 价格合理性:价格是否在当日涨跌停板范围内,是否存在异常跳空。
- 成交量非负:成交量必须为正整数,零值或负值视为异常。
- 买卖方向完整性:方向字段缺失率应低于 0.1%,否则该交易日数据不可用。
以下 Python 代码片段展示了基本的 Tick 数据质量校验逻辑:
import pandas as pd
def validate_tick(df: pd.DataFrame) -> dict:
"""对 Tick DataFrame 执行基础质量校验"""
issues = {}
# 1. 时间单调性
if not df['timestamp'].is_monotonic_increasing:
issues['time_order'] = '时间戳非单调递增'
# 2. 价格范围
price_outliers = df[(df['price'] <= 0) | (df['price'] > 1e6)]
if len(price_outliers) > 0:
issues['price_range'] = f'发现 {len(price_outliers)} 笔异常价格'
# 3. 成交量非负
neg_vol = df[df['volume'] <= 0]
if len(neg_vol) > 0:
issues['volume_non_positive'] = f'发现 {len(neg_vol)} 笔非正成交量'
# 4. 方向缺失
missing_side = df['side'].isna().sum()
if missing_side / len(df) > 0.001:
issues['side_missing'] = f'方向缺失率 {missing_side/len(df):.4%}'
return issues
实践建议: 在模型训练流水线中,将上述校验封装为独立的预处理步骤,输出 JSON 格式的质量报告。只有通过全部校验的交易日数据才允许进入标签校准环节。