特征工程(上):基础统计特征、时序特征与微观结构特征
各位同学,今天我们进入特征工程这个重头戏。说实话,特征工程做得好不好,直接决定了你模型的天花板。我见过太多人一上来就堆深度学习,结果连基础统计特征都没算明白——嗯,这其实挺可惜的。
今天我们先聊三个核心方向:基础统计特征、时序特征、微观结构特征。这三板斧用好了,你的虚拟交易对手行为模型就已经有了七成功力。
一、基础统计特征:别小看这些"老古董"
很多人觉得均值、方差太基础了,不屑于用。但我告诉你,在虚拟交易对手行为建模中,这些"老古董"往往是最稳定的信号。
均值反映的是交易对手的"常态"。比如某个对手过去100笔订单的平均报价,如果突然偏离了3个标准差——嗯,这就有意思了。
方差衡量的是"稳定性"。我记得有个项目,我们监控一个做市商的报价方差,发现方差突然缩小到原来的1/10,结果第二天它就爆仓了。为什么?因为它在硬撑流动性,不敢调价。
滑动窗口均值:μ_t = (1/N) * Σ(x_i) for i in [t-N+1, t]
指数加权方差:σ²_t = λ * σ²_{t-1} + (1-λ) * (x_t - μ_t)²
偏度和峰度这两个东西,我建议你一定要加上。偏度告诉你交易对手的报价是偏向买方还是卖方,峰度则暴露了它的"极端行为倾向"。
二、时序特征:捕捉行为的"惯性"与"反转"
交易对手的行为不是随机的,它有记忆。这就是时序特征存在的意义。
动量因子衡量的是"趋势的持续性"。你想想看,如果一个对手连续10笔都在加价,那第11笔继续加价的概率有多大?动量因子就是量化这个的。
# 动量因子计算示例
def momentum_factor(price_series, window=10):
# 我个人习惯用对数收益率
returns = np.log(price_series / price_series.shift(1))
momentum = returns.rolling(window).mean() * np.sqrt(window)
return momentum
反转因子则是动量的对立面。有些交易对手喜欢"均值回归"——涨多了就跌,跌多了就涨。我曾经遇到过一个量化基金,它的交易策略就是纯反转,每次偏离均值2个标准差就反向开仓。
除了动量和反转,自相关系数也很有用。它告诉你当前行为与过去行为的"相似度"。比如一个交易对手的报价自相关系数在滞后1阶时高达0.9,说明它是个"惯性选手"。
三、微观结构特征:从"订单簿"里挖金子
这部分是我个人最喜欢的。微观结构特征就像金融市场的"显微镜",能让你看到别人看不到的细节。
买卖价差是最直接的流动性指标。价差越小,说明市场越活跃,交易对手越"真诚"。我见过一个做市商,平时价差只有0.5个tick,但某天突然扩大到5个tick——后来发现它在偷偷撤单。
绝对价差 = 卖一价 - 买一价
相对价差 = (卖一价 - 买一价) / 中间价
对数价差 = ln(卖一价) - ln(买一价)
订单簿斜率这个特征,说实话,很多教材里都没讲。但它非常强大。斜率衡量的是订单簿的"深度分布"——是集中在最优价位,还是均匀分布在各个价位?
| 订单簿形态 | 斜率值 | 含义 |
|---|---|---|
| 陡峭型 | 高(>0.5) | 流动性集中在最优价位,容易被击穿 |
| 平缓型 | 低(<0.2) | 流动性分布均匀,抗冲击能力强 |
| 倒挂型 | 负值 | 深度异常,可能存在操纵行为 |
怎么计算订单簿斜率?我一般用前5档的累计深度做线性回归,斜率就是回归系数。代码实现也很简单:
def order_book_slope(depth_levels, volumes):
# depth_levels: [1, 2, 3, 4, 5] 对应第1到第5档
# volumes: 对应档位的累计成交量
slope, intercept = np.polyfit(depth_levels, volumes, 1)
return slope
四、特征组合的"化学反应"
单个特征再强,也不如组合起来威力大。我个人习惯把这三类特征做交叉:
- 均值 × 价差:如果均值上升但价差也在扩大,说明对手在"虚张声势"
- 动量 × 斜率:动量向上但斜率变陡,说明趋势可能很快衰竭
- 偏度 × 反转因子:偏度为正且反转因子为负,说明对手在"追涨杀跌"
这些组合特征,往往比原始特征更有预测能力。你想想看,单一特征就像单兵作战,组合特征就是特种部队。
好了,今天的内容就到这里。特征工程的下半部分,我们会聊更高级的东西——比如傅里叶变换、小波分析、图特征。但先把今天这三个基础打牢,你的模型就已经能跑赢大多数人了。