第十八章:机器学习在基差预测中的应用
说实话,基差交易做到一定程度,你会发现传统统计方法有点不够用了。为什么?因为基差的波动背后,藏着太多非线性关系。比如库存数据对基差的影响,在牛熊市里完全不一样。这时候,机器学习就该上场了。
我个人习惯把机器学习在基差预测里的应用分成三类:特征工程、时间序列预测、分类模型。今天咱们一个一个聊。
18.1 特征工程:技术指标与宏观因子
做机器学习,最怕的就是「垃圾进,垃圾出」。特征工程做不好,再牛的模型也白搭。
技术指标类特征,我一般会构建这么几类:
- 动量类:过去N日的基差变化率、RSI、MACD
- 波动率类:基差的滚动标准差、ATR(平均真实波幅)
- 价差结构:近月与远月合约的价差斜率、期限结构曲率
- 成交量与持仓量:基差变化时的成交量配合情况
宏观因子类特征,这个我踩过不少坑。一开始我把所有能想到的宏观数据都往里塞,结果模型过拟合得一塌糊涂。后来我总结出几个真正有用的:
| 宏观因子 | 具体指标 | 我常用的窗口期 |
|---|---|---|
| 利率环境 | SHIBOR、国债收益率曲线斜率 | 1周、1月 |
| 库存周期 | 显性库存变化率、仓单注销比例 | 2周、1季 |
| 汇率波动 | 人民币汇率指数、实际有效汇率 | 1月 |
| 市场情绪 | VIX指数、商品波动率指数 | 1日、1周 |
18.2 LSTM时间序列预测
基差预测本质上是个时间序列问题。传统的ARIMA模型假设线性关系,但基差这东西,你想想看,它受情绪、资金、政策多重影响,哪能是线性的?
LSTM(长短期记忆网络)的优势在于,它能记住长期依赖关系。比如去年同期的季节性规律,或者某个政策出台后的市场反应模式。
下面是我在实际项目中用过的LSTM基差预测框架:
import numpy as np
import pandas as pd
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
from sklearn.preprocessing import MinMaxScaler
# 数据准备
def prepare_lstm_data(df, lookback=60):
"""
df: 包含基差和特征的数据框
lookback: 用过去多少天预测未来
"""
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(df)
X, y = [], []
for i in range(lookback, len(scaled_data)):
X.append(scaled_data[i-lookback:i])
y.append(scaled_data[i, 0]) # 假设基差在第0列
return np.array(X), np.array(y), scaler
# 构建LSTM模型
def build_lstm_model(input_shape):
model = Sequential([
LSTM(64, return_sequences=True, input_shape=input_shape),
Dropout(0.2),
LSTM(32, return_sequences=False),
Dropout(0.2),
Dense(16, activation='relu'),
Dense(1)
])
model.compile(optimizer='adam', loss='mse', metrics=['mae'])
return model
# 训练
X_train, y_train, scaler = prepare_lstm_data(data)
model = build_lstm_model((X_train.shape[1], X_train.shape[2]))
history = model.fit(X_train, y_train, epochs=50, batch_size=32, validation_split=0.2)
LSTM预测出来的结果,我一般不会直接用来交易。我会把它作为一个「基准预测」,然后结合其他信号做综合判断。为什么?因为LSTM在极端行情下容易失效——比如2020年3月的原油暴跌,模型完全没预料到。
18.3 XGBoost分类模型
有时候我们不需要精确预测基差是多少,只需要知道「基差会不会扩大」或者「套利机会是否出现」。这时候,分类模型比回归模型更实用。
XGBoost是我在分类任务中的首选。原因有三:
- 处理缺失值能力强——宏观数据经常有缺失,XGBoost自带处理机制
- 特征重要性可解释——能告诉你哪个因子最影响基差方向
- 训练速度快——相比深度学习,XGBoost在中等规模数据上效率高得多
我通常把问题定义为三分类:
- 类别0:基差收窄(套利空间缩小)
- 类别1:基差维持(无明确机会)
- 类别2:基差扩大(套利机会出现)
import xgboost as xgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
# 构建标签:未来5日基差变化方向
def create_labels(df, horizon=5):
df['future_basis'] = df['basis'].shift(-horizon)
df['label'] = 1 # 默认维持
df.loc[df['future_basis'] - df['basis'] > threshold, 'label'] = 2 # 扩大
df.loc[df['future_basis'] - df['basis'] < -threshold, 'label'] = 0 # 收窄
return df.dropna()
# 特征选择
features = ['basis_momentum_5d', 'basis_vol_10d', 'inventory_change',
'term_structure_slope', 'shibor_1w', 'vix_index']
X = data[features]
y = data['label']
# 训练XGBoost
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)
model = xgb.XGBClassifier(
n_estimators=200,
max_depth=5,
learning_rate=0.05,
subsample=0.8,
colsample_bytree=0.7,
random_state=42
)
model.fit(X_train, y_train,
eval_set=[(X_test, y_test)],
early_stopping_rounds=20,
verbose=False)
# 特征重要性
importance = pd.DataFrame({
'feature': features,
'importance': model.feature_importances_
}).sort_values('importance', ascending=False)
print(importance)
嗯,这里还要提一句。XGBoost虽然好用,但它对时序数据的处理有个天然缺陷——它假设样本独立。但基差数据是高度自相关的。所以我建议:
- 训练集和测试集一定要按时间分割,不能随机打乱
- 可以加入滞后特征(比如过去3天的基差变化)来引入时序信息
- 用rolling window的方式做回测,模拟真实交易场景
下面这张图是我自己总结的机器学习基差预测流程,你可以参考:
最后说一句,机器学习不是银弹。我见过太多人把LSTM和XGBoost当黑盒子用,结果亏得底朝天。记住:模型只是工具,你对市场的理解才是核心。特征工程做扎实了,哪怕用简单的逻辑回归,效果也可能比花里胡哨的深度学习好。
公众号:蓝海数据掘金营,微信deep3321