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个核心特征开始,逐步迭代优化。记住,好的特征工程,是用业务理解驱动的,不是用代码堆出来的


专注资料整理