基于Python的策略开发与回测:传统机器学习 - 随机森林分类策略
1. 策略原理深度解析
核心逻辑:
使用历史价格、技术指标和基本面数据构建特征矩阵,通过随机森林模型预测次日股价涨跌方向(分类问题),根据预测概率生成交易信号:
- 预测上涨概率 > 60%:买入
- 预测下跌概率 > 60%:卖出
- 其他情况:持有现金
关键技术点:
-
特征工程:
- 时间序列特征:N日收益率、波动率、量价背离
- 技术指标:MACD直方图、RSI超卖/超买状态、布林带宽度
- 市场环境:行业指数相对强弱、市场宽幅指标
-
标签构造:
# 次日收益率二值化(涨=1,跌=0) data['Target'] = (data['Close'].shift(-1) > data['Close']).astype(int)
-
模型优势:
- 自动处理非线性关系与特征交互
- 内置特征重要性评估防止过拟合
2. 完整策略实现代码
步骤1:生成带噪声的模拟数据
import numpy as np
import pandas as pd
# 生成基准价格序列(带趋势和波动聚集)
np.random.seed(42)
days = 1000
trend = np.linspace(100, 200, days)
noise = np.concatenate([
np.random.normal(0, 2, 300),
np.random.normal(0, 5, 400),
np.random.normal(0, 3, 300)
])
price = trend + np.cumsum(noise)
# 构建DataFrame
data = pd.DataFrame({'Close': price},
index=pd.date_range('2020-01-01', periods=days))
步骤2:特征工程
# 技术指标计算
data['Return_1D'] = data['Close'].pct_change()
data['MA10'] = data['Close'].rolling(10).mean()
data['MA50'] = data['Close'].rolling(50).mean()
data['Volatility_20D'] = data['Return_1D'].rolling(20).std() * np.sqrt(252)
# 构造滞后特征
for lag in [1, 2, 3, 5]:
data[f'Return_Lag{lag}'] = data['Return_1D'].shift(lag)
# 目标变量(次日涨跌)
data['Target'] = (data['Close'].shift(-1) > data['Close']).astype(int)
# 清理缺失值
data.dropna(inplace=True)
步骤3:模型训练与预测
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
# 特征/标签拆分
features = data.columns.drop(['Close', 'Target'])
X = data[features]
y = data['Target']
# 时间序列分割(避免前瞻偏差)
train_size = int(len(data)*0.7)
X_train, X_test = X.iloc[:train_size], X.iloc[train_size:]
y_train, y_test = y.iloc[:train_size], y.iloc[train_size:]
# 模型训练
model = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=42)
model.fit(X_train, y_train)
# 生成预测概率
data['Pred_Prob'] = model.predict_proba(X)[:, 1]
3. 可视化代码与解析
可视化1:特征重要性分析
import matplotlib.pyplot as plt
# 提取特征重要性
importance = pd.Series(model.feature_importances_, index=features)
importance = importance.sort_values(ascending=True)
# 绘制水平条形图
plt.figure(figsize=(10,6))
importance.plot(kind='barh', color='#1f77b4')
plt.title('Random Forest Feature Importance', pad=15)
plt.xlabel('Importance Score')
plt.grid(alpha=0.3, axis='x')
plt.tight_layout()
plt.show()
图表说明:
- 横轴为特征重要性得分(Gini重要性)
- 纵轴显示特征名称,重要性越高表明对预测贡献越大
可视化2:预测概率分布
plt.figure(figsize=(12,5))
# 正负样本概率分布
plt.hist(data[data['Target']==1]['Pred_Prob'],
bins=30, alpha=0.7, color='green', label='Up Days')
plt.hist(data[data['Target']==0]['Pred_Prob'],
bins=30, alpha=0.7, color='red', label='Down Days')
# 标注交易阈值
plt.axvline(0.6, color='black', linestyle='--', label='Buy Threshold')
plt.axvline(0.4, color='gray', linestyle='--', label='Sell Threshold')
# 图表装饰
plt.title('Prediction Probability Distribution', pad=15)
plt.xlabel('Predicted Probability of Rising')
plt.ylabel('Frequency')
plt.legend()
plt.grid(alpha=0.3)
plt.show()
图表说明:
- 绿色直方图显示实际上涨日的预测概率分布
- 红色直方图显示实际下跌日的预测概率分布
- 黑色虚线为买入阈值(>60%),灰色虚线为卖出阈值(<40%)
4. 策略回测实现
信号生成与收益计算
# 生成交易信号
data['Signal'] = 0
data.loc[data['Pred_Prob'] > 0.6, 'Signal'] = 1 # 做多
data.loc[data['Pred_Prob'] < 0.4, 'Signal'] = -1 # 做空
# 计算策略收益
data['Strategy_Return'] = data['Signal'].shift(1) * data['Return_1D']
# 累计收益
data['Cumulative_Market'] = (1 + data['Return_1D']).cumprod()
data['Cumulative_Strategy'] = (1 + data['Strategy_Return']).cumprod()
可视化3:策略与基准对比
plt.figure(figsize=(12,6))
# 绘制净值曲线
plt.plot(data['Cumulative_Market'], label='Buy & Hold', color='#1f77b4', alpha=0.8)
plt.plot(data['Cumulative_Strategy'], label='RF Strategy', color='#ff7f0e', linewidth=2)
# 标注信号点
buy_dates = data[data['Signal'] == 1].index
sell_dates = data[data['Signal'] == -1].index
plt.scatter(buy_dates, data.loc[buy_dates, 'Cumulative_Strategy'],
marker='^', color='lime', s=50, edgecolors='black', label='Long')
plt.scatter(sell_dates, data.loc[sell_dates, 'Cumulative_Strategy'],
marker='v', color='red', s=50, edgecolors='black', label='Short')
# 图表装饰
plt.title('Strategy vs Buy & Hold Performance', pad=15)
plt.xlabel('Date')
plt.ylabel('Cumulative Return')
plt.legend()
plt.grid(alpha=0.3)
plt.yscale('log') # 对数坐标更好展示长期收益
plt.tight_layout()
plt.show()
图表说明:
- 蓝色曲线为买入持有策略净值
- 橙色曲线为随机森林策略净值
- 绿色▲标记做多信号,红色▼标记做空信号
5. 关键风险控制
- 过拟合防范:
# 使用Walk-Forward验证 for i in range(train_size, len(data), 30): model.fit(X.iloc[i-180:i], y.iloc[i-180:i]) # 滚动180天训练窗口 data.loc[i:i+30, 'Pred_Prob'] = model.predict_proba(X.iloc[i:i+30])[:,1]
- 交易成本模型:
transaction_cost = 0.001 # 单边千分之一手续费 data['Strategy_Return'] = data['Strategy_Return'] - \ abs(data['Signal'].diff()) * transaction_cost
- 杠杆控制:
max_leverage = 2 # 最大杠杆倍数 data['Signal'] = np.clip(data['Signal'], -max_leverage, max_leverage)