数据采集与清洗:交易数据源与质量管控
做量化风控这些年,我最大的体会就是:数据质量决定了模型的天花板。你算法再牛,喂进去的是垃圾,出来的还是垃圾。今天咱们就聊聊交易对手行为建模中最基础也最容易被忽视的一环——数据采集与清洗。
核心观点:数据清洗不是体力活,是技术活。它占掉整个建模流程60%以上的时间,但恰恰是这60%,决定了剩下40%的价值。
一、交易数据源:Level2与逐笔委托
先说说数据源。我个人习惯把交易数据分成两类:快照型数据和流水型数据。
- Level2行情数据:每3秒一张快照,包含十档买卖盘口、逐笔成交、委托队列等。说白了,就是市场在某个时刻的“照片”。
- 逐笔委托数据:每一笔挂单、撤单、成交的完整记录。这是“录像”,能还原交易的全过程。
我在项目中遇到过一个问题:用Level2数据做对手行为分析,发现某些账户的挂单模式很奇怪。后来换成逐笔委托数据一查,才发现是高频交易者在用“冰山订单”策略。Level2快照根本抓不到这种细节。
我的建议:如果条件允许,尽量用逐笔委托数据。Level2适合做宏观流动性分析,但对手行为建模需要微观层面的订单流信息。
二、数据清洗规则:别让脏数据毁了模型
数据清洗,说白了就是给数据“洗澡”。我总结了一套自己的清洗规则,分享给你:
| 清洗类型 | 具体规则 | 我踩过的坑 |
|---|---|---|
| 格式统一 | 时间戳转统一时区,价格单位统一 | 曾经遇到港股和A股时间戳混用,导致回测结果完全错位 |
| 去重 | 同一笔委托出现多次,保留最早一条 | 交易所数据偶尔会重传,不处理的话特征会翻倍 |
| 范围校验 | 价格不能为负,成交量不能为0 | 这个看似简单,但真有人把价格填成-1.00 |
| 逻辑校验 | 委托时间 < 成交时间 < 撤单时间 | 时间顺序错乱,通常是数据拼接时出的问题 |
嗯,这里要注意:清洗规则不是越严越好。太严会把正常数据也干掉,太松又留了脏数据。我一般会先跑一遍统计,看看异常值的分布,再定阈值。
三、缺失值处理:别随便填0
缺失值处理,很多人上来就填0或者填均值。你想想看,这合理吗?
举个例子:某只股票全天没有成交,那“逐笔成交”字段就是空的。如果你填0,模型会以为这只股票流动性极差。但实际情况可能是——它涨停了,没人卖。
我常用的几种处理方式:
- 时间序列插值:用前后时刻的数据做线性插值,适合价格类字段
- 业务规则填充:比如停牌期间的数据,直接标记为“停牌状态”
- 模型预测填充:用其他特征预测缺失值,适合关键字段
- 直接删除:缺失比例超过70%的字段,我建议直接扔掉
警告:千万不要在缺失值上偷懒。我曾经因为图省事,把所有缺失值填了-1,结果模型学出了一个“-1代表异常”的假规律。上线后遇到正常数据,模型直接崩了。
四、异常交易识别:抓出那些“不对劲”的订单
异常交易识别,是数据清洗中最有意思的部分。说白了,就是找出那些“不该出现”的交易行为。
我总结了几类常见异常:
- 价格异常:成交价偏离市场均价超过5%
- 数量异常:单笔委托量超过该股票日均成交量的10%
- 时间异常:在非交易时段出现的委托
- 频率异常:同一账户在1秒内提交超过100笔委托
- 模式异常:典型的“老鼠仓”交易——大单买入后小单卖出
怎么识别?我一般用统计方法+规则引擎的组合拳:
# 伪代码示例:异常交易识别流程
def detect_anomalous_trades(df):
# 1. 统计方法:3-sigma原则
price_mean = df['price'].mean()
price_std = df['price'].std()
df['price_anomaly'] = abs(df['price'] - price_mean) > 3 * price_std
# 2. 规则引擎:硬阈值
df['qty_anomaly'] = df['quantity'] > df['avg_daily_volume'] * 0.1
# 3. 组合判断
df['is_anomaly'] = df['price_anomaly'] | df['qty_anomaly']
return df[df['is_anomaly'] == True]
我曾经遇到过一个案例:某账户每天固定时间点,用固定金额买入某只股票。从数据上看,这完全符合“正常交易”的定义。但结合时间序列分析,发现这个模式持续了整整3个月——明显是程序化交易。这种“正常中的异常”,才是最难抓的。
五、知识体系总览
说了这么多,咱们用一张图把整个数据采集与清洗的流程串起来:
这张图把整个流程分成了四层:数据源层、清洗层、处理层、输出层。每一层都有明确的输入输出,环环相扣。我每次做新项目,都会先画这么一张图,确保流程没有遗漏。
避坑指南:我曾经在数据清洗阶段漏掉了“时间戳对齐”这一步。结果模型训练时,把9:30:00的委托和9:30:03的快照当成同一时刻的数据。你想想看,3秒的延迟在高频交易里能差出多少个价位?从那以后,我每次都会专门写一个时间对齐的校验函数。
好了,数据采集与清洗这部分就聊到这儿。记住一句话:数据清洗不是苦力活,是建模的基石。你花在清洗上的每一分钟,都会在模型效果上得到回报。
公众号:蓝海数据掘金营,微信deep3321