4. 特征工程基础:时间序列特征、统计特征、量价关系特征的构建方法
大家好,我是老张。今天咱们聊聊特征工程。
说实话,在市场监管这个领域摸爬滚打这么多年,我最大的体会就是:特征工程做得好,模型就成功了一半。你想想看,原始的交易数据就像一堆散落的拼图碎片,特征工程就是把这些碎片拼成有意义的图案。没有这一步,再牛的算法也白搭。
核心观点:特征工程不是简单的数据搬运,而是把业务理解转化为数学表达的过程。我见过太多团队,模型调参调得飞起,结果特征没选好,最后效果惨不忍睹。
4.1 时间序列特征:捕捉交易行为的时序规律
时间序列特征,说白了就是利用时间维度上的信息。为什么重要?因为市场操纵行为往往有特定的时间模式。比如尾盘拉升、开盘打压,这些都是典型的时间序列特征。
我个人习惯把时间序列特征分成三类:
- 滞后特征:过去N个时间点的值。比如过去5分钟的成交量、过去10笔的成交价。
- 窗口统计特征:滑动窗口内的统计量。比如过去1小时的均值、标准差、最大值、最小值。
- 差分特征:当前值与过去值的差值。比如价格变化量、成交量变化量。
我在项目中遇到过这样一个案例:某只股票每天尾盘最后5分钟成交量突然放大,但价格波动很小。这明显是异常行为。我们用滞后特征和窗口统计特征,成功捕捉到了这个模式。
来看一段代码示例:
import pandas as pd
import numpy as np
# 假设df是包含交易数据的DataFrame,索引是时间
df['volume_lag_1'] = df['volume'].shift(1) # 滞后1期
df['volume_lag_5'] = df['volume'].shift(5) # 滞后5期
# 滚动窗口统计
df['volume_ma_10'] = df['volume'].rolling(window=10).mean() # 10期移动平均
df['volume_std_10'] = df['volume'].rolling(window=10).std() # 10期标准差
# 差分特征
df['price_diff'] = df['close'].diff() # 价格变化
df['volume_diff'] = df['volume'].diff() # 成交量变化
小技巧:窗口大小的选择很关键。我个人建议先试试5、10、20、60这几个常用窗口,然后根据业务场景调整。比如捕捉日内操纵,5分钟窗口就够;如果是跨日操纵,可能需要20天以上的窗口。
4.2 统计特征:用数学语言描述交易行为
统计特征,就是用量化的方式描述数据的分布特征。嗯,这里要注意,统计特征不是简单的均值方差,而是要结合业务场景去设计。
我常用的统计特征包括:
- 集中趋势:均值、中位数、众数
- 离散程度:标准差、方差、极差、四分位距
- 分布形态:偏度、峰度
- 异常检测:Z-score、箱线图异常值
举个例子,偏度这个特征在识别操纵行为时特别好用。为什么?因为正常的交易数据往往近似正态分布,而操纵行为会导致数据分布严重偏斜。比如对倒交易,会在某个价格区间形成异常密集的成交,导致偏度值异常。
我曾经用偏度特征成功识别出一个典型的"老鼠仓"案例。那个账户的交易数据偏度值高达3.8,而正常账户一般在-0.5到0.5之间。你看,一个简单的统计特征就能发现问题。
# 计算统计特征
def extract_statistical_features(df, window=20):
features = pd.DataFrame(index=df.index)
# 滚动窗口内的统计量
features['mean'] = df['volume'].rolling(window).mean()
features['std'] = df['volume'].rolling(window).std()
features['skew'] = df['volume'].rolling(window).skew() # 偏度
features['kurt'] = df['volume'].rolling(window).kurt() # 峰度
# Z-score异常检测
features['z_score'] = (df['volume'] - features['mean']) / features['std']
return features
避坑指南:我曾经在计算统计特征时,忽略了数据中的缺失值和异常值,结果偏度值直接爆表。后来我养成了一个习惯:先做数据清洗,再做特征工程。缺失值用前向填充或插值处理,异常值用分位数截断。
4.3 量价关系特征:揭示交易行为的本质
量价关系,是市场监管中最核心的分析维度。你想想看,任何交易行为最终都会体现在成交量和价格的变化上。量价关系特征,就是把这些变化用数学公式表达出来。
我常用的量价关系特征有:
| 特征名称 | 计算公式 | 业务含义 |
|---|---|---|
| 量价相关系数 | corr(volume, price) | 量价是否同步变化 |
| 量价背离指数 | price_change / volume_change | 价格变化是否由成交量支撑 |
| 成交量加权价格 | ∑(price * volume) / ∑volume | 真实成交价格水平 |
| 量价弹性 | Δprice / Δvolume | 单位成交量引起的价格变化 |
| 资金流向强度 | (buy_volume - sell_volume) / total_volume | 买卖力量对比 |
这里我要特别强调一下量价背离指数。正常交易中,价格上涨通常伴随着成交量放大。但如果价格大幅上涨而成交量萎缩,这就是典型的量价背离,很可能是操纵行为。
我记得有一次,某只股票连续三天涨停,但成交量却逐日递减。量价背离指数从正常的0.8降到了0.2。我们立即发出预警,后来证实是庄家在对倒拉升。
# 量价关系特征构建
def extract_volume_price_features(df):
features = pd.DataFrame(index=df.index)
# 量价相关系数(滚动窗口)
features['corr_vp'] = df['volume'].rolling(20).corr(df['close'])
# 量价背离指数
price_change = df['close'].pct_change()
volume_change = df['volume'].pct_change()
features['divergence'] = price_change / (volume_change + 1e-8) # 加小值防除零
# 成交量加权价格
features['vwap'] = (df['close'] * df['volume']).rolling(20).sum() / df['volume'].rolling(20).sum()
# 量价弹性
features['elasticity'] = price_change / (volume_change + 1e-8)
return features
实战经验:量价关系特征最好组合使用。单一特征可能误报,但多个特征同时异常,基本就能锁定问题。我一般会设置一个"异常评分",把多个量价特征的结果加权求和,超过阈值就触发预警。
4.4 特征构建的整体框架
好了,三种特征都讲完了。你可能觉得有点乱,我画个图帮你理清思路。
这个框架图很直观。原始数据进来后,分三条路走:时间序列、统计、量价关系。每条路都有自己的子特征,最后汇聚成特征矩阵,喂给模型。
在实际项目中,我一般会先构建时间序列特征,因为这是基础。然后加上统计特征,最后用量价关系特征做补充。三个维度都覆盖了,特征空间就比较完整了。
总结一下:特征工程没有标准答案,关键是要理解业务。你做的特征越多,不代表效果越好。我建议从10-20个核心特征开始,逐步迭代优化。记住,好的特征工程,是用业务理解驱动的,不是用代码堆出来的。