4. 特征工程
任务目标
本案例基于股票历史行情数据,构建价格衍生特征集,为后续机器学习选股模型提供输入。核心任务是:从原始OHLCV数据中生成动量类、波动类、均线类共三类特征,并输出可直接用于模型训练的特征矩阵。
环境与依赖
需要 pandas、numpy。数据使用本地CSV文件,包含至少date, open, high, low, close, volume六列,按日期升序排列。
核心实现
import pandas as pd
import numpy as np
def generate_price_features(df, window=5):
"""
生成价格衍生特征
参数:
df: 含 open/high/low/close/volume 的DataFrame,按日期升序
window: 动量与波动窗口期
返回:
含原始列 + 衍生特征的新DataFrame
"""
df = df.copy()
close = df['close']
high = df['high']
low = df['low']
# --- 动量类 ---
df['ret_1d'] = close.pct_change() # 1日收益率
df['ret_window'] = close.pct_change(window) # N日收益率
df['mom_ratio'] = close / close.shift(window) - 1 # 动量比率
# --- 波动类 ---
df['high_low_range'] = (high - low) / close # 日内振幅
df['volatility'] = df['ret_1d'].rolling(window).std() # 滚动波动率
# --- 均线类 ---
df['ma_short'] = close.rolling(window).mean() # 短期均线
df['ma_long'] = close.rolling(window * 2).mean() # 长期均线
df['price_vs_ma'] = close / df['ma_short'] - 1 # 价格偏离短期均线
# 删除前window行(滚动窗口导致的NaN)
df = df.iloc[window:]
return df.reset_index(drop=True)
# 最小调用入口
if __name__ == "__main__":
# 读取数据(示例路径,请替换为实际文件)
raw = pd.read_csv('stock_data.csv', parse_dates=['date'])
raw = raw.sort_values('date')
# 生成特征
featured = generate_price_features(raw, window=5)
# 保存结果
featured.to_csv('featured_data.csv', index=False)
print(f"特征矩阵形状: {featured.shape}")
print(f"衍生特征列: {[c for c in featured.columns if c not in raw.columns]}")
运行与验证
运行方式:将上述代码保存为 feature_engineering.py,与 stock_data.csv 置于同一目录,执行 python feature_engineering.py。
验证方法:
- 程序正常结束,输出特征矩阵形状为
(总行数-5, 总列数+9),新增9个特征列。 - 打开
featured_data.csv,检查ret_1d列:第1行应为NaN(因pct_change首值为空),后续行数值约在-0.1~0.1之间(正常股票日收益率范围)。 - 检查
volatility列:所有值均为非负数,且前几行为NaN(滚动窗口未满)。 - 检查
price_vs_ma列:数值有正有负,表示价格相对均线的偏离方向。
通过条件:上述检查全部通过,且无报错,即特征工程闭环完成。
常见问题
- 数据不足:若原始数据少于10行,
ma_long将全为NaN,需保证数据量至少为2*window+1行。 - 日期排序:若原始数据未按日期升序,特征计算将失去时序意义,务必先执行
sort_values('date')。 - 窗口选择:本案例默认window=5,实际使用中可根据交易频率调整(如日线数据常用5/10/20)。