第二章:数据基础与预处理——高频数据获取、清洗、对齐与特征工程基础
各位同学,咱们今天聊点实在的。做市场操纵识别,说白了就是跟数据打交道。你模型再牛,算法再花哨,数据一塌糊涂,结果就是垃圾进垃圾出。我见过太多团队,上来就搞深度学习,结果连tick数据的时间戳都没对齐,那能抓到操纵信号才怪。
这一章,我就把高频数据从获取到清洗再到特征工程,整个流程给你捋一遍。都是我在项目里踩过的坑,你拿回去就能用。
2.1 高频数据获取:从哪里来,拿什么格式
高频数据,一般指逐笔成交数据(Tick)和逐笔委托数据(Order Book)。频率从毫秒到微秒不等。国内交易所,比如上交所、深交所,都有Level-2行情接口。
我个人习惯,数据源首选交易所直连或者券商提供的API。为什么?因为第三方数据商有时候会做数据平滑,把一些极端值给你抹掉了。你想想看,操纵行为往往就体现在那些极端值上,抹掉了你还分析个啥?
数据格式方面,我建议统一用Parquet或者HDF5。别用CSV,尤其是高频数据,CSV读写慢,占空间大,还容易丢精度。我在项目中遇到过,一个月的Tick数据用CSV存了200G,换成Parquet直接压缩到30G,读取速度还快了10倍。
- 时间戳(精确到毫秒或微秒)
- 成交价格
- 成交量
- 买卖方向(主动买/主动卖)
- 委托簿前5档(买一~买五,卖一~卖五)
- 委托量(对应档位的挂单量)
2.2 数据清洗:脏数据是最大的敌人
数据拿到手,别急着分析。先洗一遍。高频数据的脏数据主要有三类:
- 时间戳异常:比如某笔成交的时间戳比前一笔还早,或者时间戳为0。这通常是交易所撮合引擎的bug或者网络延迟导致的。
- 价格异常:比如涨停价突然出现一笔跌停价的成交,或者价格跳空超过阈值。这可能是数据解析错误。
- 量异常:比如某笔成交量突然是前一笔的100倍,或者委托量出现负数。
嗯,这里要注意。清洗不是简单地把异常值删掉。我曾经在清洗时,直接把所有价格超过3倍标准差的数据删了,结果发现删掉了很多真实的操纵信号。后来我改用“基于滚动窗口的异常检测”,比如用过去100笔成交的中位数加减5倍MAD(中位数绝对偏差)作为阈值,效果就好多了。
2.3 数据对齐:不同频率的数据怎么对齐
高频数据通常是非等间隔的。比如tick数据,有时候一秒成交100笔,有时候一秒成交1笔。但我们的模型往往需要等间隔的输入,比如每秒一个特征向量。
对齐的方法,我推荐两种:
- 时间桶聚合(Time Bucketing):把时间切成固定间隔的桶,比如1秒一个桶。桶内的数据,取最后一笔的价格作为该秒的收盘价,取所有成交量之和作为该秒的成交量。
- 线性插值:如果两个tick之间没有成交,用线性插值补一个价格。但这个方法在操纵识别中要慎用,因为操纵行为往往发生在成交稀疏的时刻,插值会掩盖掉这些信号。
我个人习惯,做操纵识别时只用时间桶聚合,不用插值。你想想看,如果某只股票在10:00:00到10:00:05之间没有任何成交,突然在10:00:06出现一笔巨量成交,这本身就是异常信号。插值会把这段空白填平,你就看不出来了。
2.4 特征工程基础:从原始数据到信号
特征工程,说白了就是把原始数据变成模型能理解的信号。做操纵识别,我一般把特征分成三类:
| 特征类别 | 典型特征 | 说明 |
|---|---|---|
| 价格特征 | 收益率、价格波动率、价格冲击系数 | 衡量价格变化的幅度和速度 |
| 量特征 | 成交量、成交笔数、大单占比 | 衡量资金活跃度和集中度 |
| 订单簿特征 | 买卖价差、订单簿斜率、挂单撤单比 | 衡量市场深度和委托行为异常 |
举个例子,价格冲击系数怎么算?
# 伪代码示例
def price_impact(volume, price_change):
# 价格冲击 = 价格变化 / 成交量
# 如果成交量很小,价格变化很大,说明冲击大
impact = abs(price_change) / (volume + 1e-8)
return impact
这个特征在操纵识别中非常有用。为什么?因为操纵者往往想用少量资金拉抬股价,价格冲击系数会异常高。我在项目中遇到过,某只股票在3秒内用不到10万的资金拉涨了2%,价格冲击系数是正常值的50倍,这就是典型的“对倒拉抬”信号。
另外,挂单撤单比也很关键。正常交易者挂单后,撤单率一般在20%-30%左右。如果某账户的撤单率突然飙升到80%以上,而且挂单价格总是刚好在买一或卖一附近,那大概率是在“虚假申报”,也就是挂单不成交,诱导别人跟单。
- 特征要有业务解释性,别搞黑盒特征
- 特征要能捕捉到“异常”,而不是“正常”
- 特征计算要快,高频数据量很大,别用循环,用向量化操作
2.5 本章知识体系总览
下面这张图,我把本章的核心逻辑画出来了。你一看就明白数据是怎么从原始tick变成特征矩阵的。
这张图里,我特意加了一个反馈循环。为什么?因为数据清洗和特征工程不是一次性的。你训练完模型,发现效果不好,回头一看,往往是数据预处理阶段出了问题。我做过一个项目,模型AUC一直上不去,折腾了两周,最后发现是时间戳对齐时用了错误的时区。所以,别怕回头改,这是常态。