3. 行情数据采集与存储:实时数据流接入、分布式存储方案与数据清洗对齐
高频行情数据的采集与存储是整个A/B测试管线的基石。数据流的实时性、存储的可扩展性以及清洗对齐的精度,直接决定了后续策略回测与效果评估的可靠性。本节将深入剖析从交易所原始行情到可分析数据集的完整技术链路。
3.1 实时数据流接入架构
高频行情数据源通常包括交易所的Level-2快照、逐笔成交、订单簿变更等。接入层需要解决高吞吐、低延迟、断线重连与数据完整性校验四大挑战。
核心指标参考: 国内主流交易所Level-2行情峰值可达每秒10万笔以上,单日数据量超过200GB。接入层设计需满足99.99%的可用性与微秒级延迟。
3.1.1 接入层组件与职责
| 组件 | 职责 | 典型实现 |
|---|---|---|
| 行情网关 | 对接交易所API,解析二进制协议,生成统一内部消息 | C++/Rust 低延迟网关 |
| 消息队列 | 缓冲、削峰、解耦生产与消费 | Kafka / Pulsar |
| 数据分发器 | 按主题(Topic)路由行情至不同消费者 | Kafka Streams / 自研分发 |
| 监控与告警 | 检测数据延迟、断流、序列号跳跃 | Prometheus + Grafana |
3.1.2 实时数据流接入流程
- 连接建立: 行情网关通过TCP/UDP多播连接交易所数据源,采用心跳机制维持会话。
- 协议解析: 将二进制报文(如STEP、Binary、FIX/FAST)解码为结构化行情事件。
- 序列号校验: 检查消息序列号连续性,发现缺失时触发重传请求或从备份通道补数。
- 消息序列化: 将行情事件序列化为Avro/Protobuf格式,写入Kafka Topic。
- 数据持久化: Kafka Broker将消息落盘,并保留指定时间窗口(通常7-30天)。
3.2 分布式存储方案:Kafka 与 InfluxDB
高频行情数据具有写多读少、时序性强、数据量大的特点。传统关系型数据库难以胜任,业界普遍采用分层存储策略:Kafka 负责实时消息缓冲与短期存储,InfluxDB 负责时序数据的长期存储与高效查询。
3.2.1 Kafka:实时消息总线
Kafka 作为分布式消息队列,在高频行情场景中承担数据管道核心角色。其关键配置直接影响A/B测试的数据完整性。
| 配置项 | 推荐值 | 说明 |
|---|---|---|
| 分区数 | 合约数量 × 2~4 | 保证同一合约行情顺序写入同一分区 |
| 副本因子 | 3 | 防止Broker宕机导致数据丢失 |
| 保留时间 | 7天 | 短期回溯与重放需求 |
| 压缩类型 | lz4 / zstd | 降低存储与网络带宽开销 |
| acks | all | 确保数据写入所有副本后才确认 |
3.2.2 InfluxDB:时序数据存储
InfluxDB 专为时序数据优化,支持高写入吞吐、自动降采样与高效范围查询。在A/B测试场景中,通常将清洗对齐后的行情数据写入InfluxDB,用于策略回测与效果分析。
存储模型建议: 使用 Tag 存储合约代码、交易所、数据类型(快照/逐笔);使用 Field 存储价格、成交量、买卖盘口等数值;时间戳精度设为纳秒级以匹配高频需求。
3.2.3 分层存储策略对比
| 存储层 | 技术选型 | 数据保留周期 | 主要用途 |
|---|---|---|---|
| 热存储 | Kafka | 7天 | 实时消费、短时回溯、流式计算 |
| 温存储 | InfluxDB | 30~90天 | 策略回测、A/B效果分析、可视化 |
| 冷存储 | Parquet + S3/HDFS | 永久 | 历史复盘、监管审计、模型训练 |
3.3 数据清洗与对齐
原始行情数据存在缺失、重复、乱序、时间戳不一致等问题。在A/B测试中,这些噪声会直接污染策略效果评估结果。数据清洗与对齐是保证测试结论可信的关键步骤。
3.3.1 常见数据质量问题
| 问题类型 | 产生原因 | 影响 |
|---|---|---|
| 数据缺失 | 网络抖动、交易所限流、网关宕机 | 策略信号中断,回测结果失真 |
| 数据重复 | 重传机制、多通道冗余 | 成交量虚高,统计指标偏差 |
| 时间戳乱序 | 多源时钟不同步、网络延迟波动 | 订单簿重建错误,策略执行时序错乱 |
| 价格异常 | 交易所故障、数据解析错误 | 产生虚假交易信号,回测收益失真 |
3.3.2 清洗流程
- 去重: 基于交易所消息序列号(SeqNo)或(时间戳+价格+成交量)组合键,保留首条记录。
- 排序: 按交易所原始时间戳(Exchange Timestamp)排序,而非网关接收时间。
- 缺失填充: 对于短时间(< 1ms)缺失,使用前一条数据填充;长时间缺失则标记为“数据空洞”。
- 异常过滤: 使用3σ原则或固定阈值过滤价格/成交量异常值,并记录日志供人工审核。
- 时间戳对齐: 将不同数据源(快照、逐笔、订单簿)的时间戳统一到同一时钟基准(如NTP同步后的纳秒时间戳)。
重要提醒: 清洗逻辑必须在A/B测试的对照组与实验组中完全一致,否则会引入系统性偏差。建议将清洗模块封装为独立组件,在两组数据上并行执行。
3.3.3 数据对齐策略
在A/B测试中,需要将不同频率、不同来源的行情数据对齐到统一的时间网格上,以便进行策略信号计算与效果对比。
- 时间桶对齐: 将连续行情按固定时间窗口(如1ms、10ms)切分,每个桶内取首笔或末笔数据。
- 事件驱动对齐: 以逐笔成交或订单簿变更为触发事件,将快照数据对齐到最近的事件时间戳。
- 插值对齐: 对于缺失的时间点,使用线性插值或前值填充法生成对齐数据。
# 示例:基于Pandas的时间桶对齐
import pandas as pd
def align_to_time_bucket(df, bucket_ms=10):
"""
将原始行情数据对齐到固定时间桶
df: DataFrame 包含 'timestamp' 列(纳秒)
bucket_ms: 时间桶宽度(毫秒)
"""
df['bucket'] = (df['timestamp'] // (bucket_ms * 1_000_000)) * (bucket_ms * 1_000_000)
aligned = df.groupby('bucket').agg({
'price': 'last', # 取桶内最后一笔价格
'volume': 'sum', # 桶内成交量累加
'bid': 'last',
'ask': 'last'
}).reset_index()
return aligned
3.4 数据质量监控与校验
建立自动化数据质量监控体系,是保障A/B测试数据可靠性的最后一道防线。建议在清洗对齐后,对每个数据批次执行以下校验:
| 校验项 | 阈值 | 告警级别 |
|---|---|---|
| 数据延迟 | > 100ms | Warning |
| 缺失率 | > 0.1% | Critical |
| 重复率 | > 0.05% | Warning |
| 价格异常比例 | > 0.01% | Critical |
| 时间戳乱序比例 | > 0.1% | Warning |
最佳实践: 将数据质量指标作为A/B测试的协变量纳入效果评估模型。例如,当实验组的数据缺失率显著高于对照组时,需在统计模型中加以校正,避免因数据质量差异导致虚假结论。