第二十五讲:基差的机器学习预测——随机森林与LSTM在基差预测中的实战

各位同学,今天我们来聊点硬核的。前面我们讲了统计模型、讲了时间序列,但说实话,在真实的交易环境里,基差这东西太复杂了。它受库存、受情绪、受政策、受资金面……你想想看,这么多因素搅在一起,传统模型有时候真不够用。

所以,我个人的习惯是——遇到这种“多因子、非线性、高噪声”的问题,直接上机器学习。今天我们就拿两个最典型的模型来开刀:随机森林LSTM。一个代表“传统机器学习”的巅峰,一个代表“深度学习时序”的利器。

核心观点:基差预测不是“预测未来价格”,而是“预测价差的波动规律”。你只要比市场早半步识别出基差的异常偏离,就能吃到回归的利润。

一、为什么是随机森林和LSTM?

我先说说我的选型逻辑。

随机森林,说白了就是一群决策树投票。它不怕过拟合,能处理缺失值,还能输出特征重要性——这一点在金融里太重要了。我在项目中遇到过好几次,用随机森林跑完,发现“近月持仓量变化”这个特征的权重远高于其他,后来我专门盯着这个因子做策略,效果不错。

LSTM呢,它是专门为序列数据设计的。基差本身就是一个时间序列,今天的基差跟昨天、前天、甚至前一周都有关系。LSTM能记住这些“长期依赖”,这是普通神经网络做不到的。

嗯,这里要注意:随机森林适合“截面数据”,比如你拿当前时刻的库存、持仓、波动率去预测当前基差的异常程度;而LSTM适合“时序数据”,比如你用过去N天的基差序列去预测未来1天的基差。

二、数据准备:别让模型“吃垃圾”

做机器学习,有一句话我特别认同:垃圾进,垃圾出。你模型再牛,数据不对也是白搭。

我建议你准备以下特征(以螺纹钢为例):

特征类别 具体特征 说明
价格类 现货价格、近月期货价、远月期货价 基差计算的基础
持仓类 近月持仓量、远月持仓量、持仓变化率 反映资金博弈
库存类 社会库存、钢厂库存、库存变化率 供需的直接体现
波动类 历史波动率、隐含波动率 市场情绪指标
时间类 距离交割日天数、星期几、月份 季节性规律

我的小技巧:特征不是越多越好。我一般先用随机森林跑一次,看特征重要性排序,把排名后20%的砍掉。这样既能减少噪声,又能提升训练速度。

三、随机森林实战:特征工程与模型训练

好,我们直接上代码。以下是我在实际项目中用过的简化版本。

import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error

# 加载数据(假设你已经有了特征矩阵X和标签y)
# X: 包含库存、持仓、波动率等特征
# y: 未来1天的基差变化值

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, shuffle=False
)

# 训练随机森林
rf = RandomForestRegressor(
    n_estimators=200,
    max_depth=10,
    min_samples_leaf=5,
    random_state=42
)
rf.fit(X_train, y_train)

# 预测
y_pred = rf.predict(X_test)

# 评估
mae = mean_absolute_error(y_test, y_pred)
print(f"测试集MAE: {mae:.4f}")

# 特征重要性
importance = pd.DataFrame({
    'feature': X.columns,
    'importance': rf.feature_importances_
}).sort_values('importance', ascending=False)
print(importance.head(10))

我曾经在一次实盘测试中,用这个模型预测沪铜的基差。一开始我加了20多个特征,结果MAE一直下不去。后来我砍掉了“宏观经济指标”这类低频数据,只保留日频数据,MAE直接降了15%。记住:高频预测用高频特征,低频特征只会引入滞后。

四、LSTM实战:时序建模与序列预测

LSTM的用法跟随机森林完全不同。它需要你把数据整理成“样本-时间步-特征”的三维结构。

import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
from sklearn.preprocessing import MinMaxScaler

# 假设你有一个基差序列:basis_series
# 用过去60天的基差预测未来1天

def create_sequences(data, seq_length):
    X, y = [], []
    for i in range(len(data) - seq_length):
        X.append(data[i:i+seq_length])
        y.append(data[i+seq_length])
    return np.array(X), np.array(y)

# 归一化
scaler = MinMaxScaler()
basis_scaled = scaler.fit_transform(basis_series.reshape(-1, 1))

seq_length = 60
X, y = create_sequences(basis_scaled, seq_length)

# 划分训练集和测试集
split = int(0.8 * len(X))
X_train, X_test = X[:split], X[split:]
y_train, y_test = y[:split], y[split:]

# 构建LSTM模型
model = Sequential([
    LSTM(50, return_sequences=True, input_shape=(seq_length, 1)),
    Dropout(0.2),
    LSTM(50, return_sequences=False),
    Dropout(0.2),
    Dense(1)
])

model.compile(optimizer='adam', loss='mse')
model.fit(X_train, y_train, epochs=50, batch_size=32, validation_split=0.1)

# 预测
y_pred_scaled = model.predict(X_test)
y_pred = scaler.inverse_transform(y_pred_scaled)
y_test_actual = scaler.inverse_transform(y_test.reshape(-1, 1))

避坑指南:我曾经犯过一个错误——直接用原始基差训练LSTM,结果模型死活不收敛。后来发现是数据尺度问题。基差有时候是-200,有时候是+500,这种大范围波动会让LSTM的梯度爆炸。一定要做归一化!

五、随机森林 vs LSTM:到底选哪个?

这个问题我经常被问到。我的回答是:看你的数据形态和预测目标。

  • 如果你做“截面预测”——比如今天收盘后,用当前所有品种的数据判断哪个品种的基差被高估/低估,用随机森林。它快,可解释性强。
  • 如果你做“时序预测”——比如用过去60天的基差序列预测明天的基差,用LSTM。它能捕捉到趋势和周期。
  • 如果你两个都想做——我建议你把随机森林的特征输出作为LSTM的额外输入,做一个“混合模型”。我在一次比赛中用过这个思路,效果比单独用任何一个都好。

六、核心逻辑框架图

下面这张图是我自己总结的基差机器学习预测流程,你照着这个框架走,基本不会跑偏。

基差机器学习预测核心流程 数据采集与清洗 特征工程与选择 随机森林(截面) LSTM(时序) 模型评估与回测 基差预测信号

七、实战中的几个坑

最后,我掏心窝子说几个我踩过的坑:

  1. 不要用未来数据。 我见过有人用“当天的收盘价”去预测“当天的基差”,这等于作弊。一定要确保你的特征在预测时点是已知的。
  2. 注意样本外测试。 时间序列数据不能随机打乱。我习惯按时间顺序划分,前80%训练,后20%测试。
  3. 别迷信深度学习。 有时候随机森林的效果比LSTM还好,尤其是数据量不大的时候。我建议你先跑随机森林,把它作为baseline,再考虑要不要上LSTM。
  4. 回测要带交易成本。 基差策略通常需要频繁换月,手续费和滑点会吃掉不少利润。我吃过这个亏,后来在回测里强制加了2个跳点的滑点成本。

总结一句话:随机森林帮你“看截面”,LSTM帮你“看时序”。两个模型结合起来,你就能从不同维度捕捉基差的波动规律。剩下的,就是不断迭代、不断优化。


公众号:蓝海资料掘金营,微信deep3321