第七章:基差预测模型

基差预测,说白了就是猜未来价差会怎么走。

我做了十几年交易,见过太多人在这上面栽跟头。有人靠直觉,有人靠画线,还有人靠抛硬币——嗯,最后一种其实比前两种靠谱点,至少你知道自己在赌。

但真正的风控体系,不能靠赌。我们需要数学模型。

这一章,我会把常用的基差预测模型掰开揉碎讲清楚。从经典的ARIMA,到处理波动率的GARCH,再到这两年火得不行的机器学习模型。每个模型我都会说说它的适用场景,以及——我踩过的坑。

核心观点:没有完美的模型,只有合适的模型。基差预测的本质,是在「解释性」和「预测精度」之间做取舍。

基差预测模型体系 基差预测模型 统计模型 ARIMA GARCH 机器学习模型 随机森林 XGBoost 模型评估与回测 回测框架 评估指标 实战应用与避坑 统计模型 机器学习 评估回测 实战应用

7.1 ARIMA模型:经典时序方法

ARIMA,全称是自回归积分滑动平均模型。名字听着唬人,其实逻辑很简单:用过去的数据预测未来的数据。

我刚开始做基差预测时,第一个用的就是ARIMA。为什么?因为它稳定、可解释、而且——说实话——大部分基差序列确实有自相关性。

ARIMA的三个核心参数:

  • p(自回归阶数):用过去几个点的数据来预测当前点。比如p=2,就是用t-1和t-2的值预测t的值。
  • d(差分阶数):让非平稳序列变平稳。基差序列通常d=1就够了,差一次基本就稳了。
  • q(移动平均阶数):用过去几个预测误差来修正当前预测。

我的经验:ARIMA的参数选择,别迷信自动定阶。我习惯先用ACF和PACF图肉眼看一下,再结合AIC/BIC做微调。自动定阶有时候会选出过拟合的模型,尤其是数据量不大的时候。

# Python示例:ARIMA模型拟合
import pandas as pd
import numpy as np
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
import matplotlib.pyplot as plt

# 加载基差数据
basis_data = pd.read_csv('basis_data.csv', index_col='date', parse_dates=True)

# 先看ACF和PACF图
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6))
plot_acf(basis_data['basis'].dropna(), lags=20, ax=ax1)
plot_pacf(basis_data['basis'].dropna(), lags=20, ax=ax2)
plt.show()

# 拟合ARIMA(2,1,2)模型
model = ARIMA(basis_data['basis'], order=(2, 1, 2))
result = model.fit()
print(result.summary())

# 预测未来5个交易日
forecast = result.forecast(steps=5)
print("预测值:", forecast)

注意:ARIMA假设数据是线性的。基差如果出现结构性突变(比如政策变化、交割月切换),ARIMA会死得很惨。我曾经在2018年用ARIMA预测豆粕基差,结果中美贸易战一打,模型直接崩了——嗯,从那以后我学会了给模型加「开关」。

7.2 GARCH模型:捕捉波动率聚集

ARIMA只预测均值,但基差的风险在于波动率。你想想看,有时候基差连续几天不动,突然一天波动几个点——这种「波动率聚集」现象,GARCH模型就是专门处理这个的。

GARCH(广义自回归条件异方差模型)的核心思想:今天的波动率,和昨天的波动率有关。

我个人的习惯是:先用ARIMA预测基差的均值,再用GARCH预测基差的波动率。两者结合,给出一个「预测区间」,而不是单点预测。

# Python示例:ARIMA-GARCH联合模型
from arch import arch_model

# 先拟合ARIMA,提取残差
arima_model = ARIMA(basis_data['basis'], order=(2, 1, 2))
arima_result = arima_model.fit()
residuals = arima_result.resid

# 对残差拟合GARCH(1,1)模型
garch_model = arch_model(residuals * 100, vol='Garch', p=1, q=1)
garch_result = garch_model.fit(update_freq=5)
print(garch_result.summary())

# 预测波动率
garch_forecast = garch_result.forecast(horizon=5)
print("波动率预测:", garch_forecast.variance.dropna() / 10000)

关键点:GARCH模型对异常值非常敏感。数据里如果有一个极端值,波动率预测会飙升好几天。我建议在拟合GARCH之前,先做一下异常值处理——比如用中位数替换3倍标准差以外的值。

7.3 随机森林:非线性的利器

ARIMA和GARCH都是线性模型。但基差的影响因素往往是非线性的——比如库存和基差的关系,不是简单的正相关或负相关,而是有阈值效应的。

这时候,随机森林就派上用场了。

随机森林的本质是集成学习:用很多棵决策树一起投票,每棵树看数据的不同侧面。它的好处是:不需要假设数据分布,能自动捕捉非线性关系,而且不容易过拟合。

我记得有一次做螺纹钢基差预测,用ARIMA的R²只有0.3,换成随机森林直接干到0.6。为什么?因为随机森林把「库存天数」、「钢厂开工率」、「下游采购节奏」这些特征都吃进去了,而ARIMA只能看历史价格。

# Python示例:随机森林预测基差
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score

# 构造特征:历史基差、库存、开工率、期货价格等
features = ['basis_lag1', 'basis_lag2', 'inventory', 'capacity_util', 'futures_price']
X = data[features]
y = data['basis']

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, shuffle=False
)

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

# 预测和评估
y_pred = rf_model.predict(X_test)
print("R²:", r2_score(y_test, y_pred))
print("RMSE:", np.sqrt(mean_squared_error(y_test, y_pred)))

# 特征重要性
importance = pd.DataFrame({
    'feature': features,
    'importance': rf_model.feature_importances_
}).sort_values('importance', ascending=False)
print(importance)

避坑指南:随机森林虽然不容易过拟合,但也不是万能的。我曾经犯过一个错误——把「未来信息」当特征用了。比如用t+1的期货价格预测t的基差,结果回测漂亮得不行,实盘一塌糊涂。记住:任何预测模型,只能用t时刻及之前的信息。

7.4 XGBoost:梯度提升的王者

如果说随机森林是「民主投票」,那XGBoost就是「精英迭代」——每一棵新树都在纠正前一棵树的错误。

XGBoost这两年在大宗商品预测领域特别火。为什么?因为它精度高、速度快、而且自带正则化。说白了,就是比随机森林更「聪明」一点。

但要注意:XGBoost的参数调起来比随机森林复杂得多。我刚开始用的时候,调参调了整整一周——嗯,后来发现有个更简单的方法:用Optuna自动调参。

# Python示例:XGBoost预测基差
import xgboost as xgb
from sklearn.model_selection import GridSearchCV

# 定义XGBoost模型
xgb_model = xgb.XGBRegressor(
    n_estimators=500,
    learning_rate=0.05,
    max_depth=5,
    subsample=0.8,
    colsample_bytree=0.8,
    random_state=42
)

# 训练
xgb_model.fit(
    X_train, y_train,
    eval_set=[(X_test, y_test)],
    early_stopping_rounds=50,
    verbose=False
)

# 预测
y_pred_xgb = xgb_model.predict(X_test)
print("XGBoost R²:", r2_score(y_test, y_pred_xgb))

# 特征重要性可视化
xgb.plot_importance(xgb_model, max_num_features=10)
plt.show()

注意:XGBoost虽然精度高,但解释性差。你很难说清楚为什么模型预测基差会涨。在风控场景下,我建议把XGBoost作为「辅助模型」,而不是唯一决策依据。毕竟,风控需要的是可解释性,不是黑箱。

7.5 模型评估与回测

模型建好了,怎么知道它好不好?

我见过太多人犯一个错误:用全部数据训练,再用全部数据评估——这叫「自欺欺人」。正确的做法是:时间序列回测,不能用随机划分。

回测的核心原则:

  • 滚动窗口回测:固定训练集长度,每次向前滚动一步,预测下一步。
  • 扩展窗口回测:训练集不断累积,每次用全部历史数据预测未来。
  • 避免未来信息:回测时,每一步只能用截止到当前时刻的数据。
评估指标 公式 说明
MAE mean(|y_true - y_pred|) 平均绝对误差,直观易懂
RMSE sqrt(mean((y_true - y_pred)²)) 对大误差惩罚更大
MAPE mean(|(y_true - y_pred)/y_true|) 百分比误差,适合比较不同品种
1 - SS_res/SS_tot 解释方差比例,越接近1越好
方向准确率 mean(sign(y_true) == sign(y_pred)) 预测涨跌方向的准确率

我的回测框架:我个人习惯用「滚动窗口+多指标评估」。具体来说:

  1. 用2年数据做训练集,滚动预测未来1个月
  2. 同时看RMSE和方向准确率——RMSE低但方向总猜错,说明模型没用
  3. 加上「最大回撤」指标:如果模型预测的基差和实际基差偏差超过2倍标准差,触发预警
# Python示例:滚动窗口回测
def rolling_backtest(data, model_func, window=500, horizon=5):
    predictions = []
    actuals = []
    
    for i in range(window, len(data) - horizon):
        # 训练数据:i-window 到 i
        train_data = data.iloc[i-window:i]
        
        # 测试数据:i 到 i+horizon
        test_data = data.iloc[i:i+horizon]
        
        # 训练模型
        model = model_func(train_data)
        
        # 预测
        pred = model.forecast(steps=horizon)
        predictions.extend(pred)
        actuals.extend(test_data['basis'].values)
    
    # 计算评估指标
    rmse = np.sqrt(mean_squared_error(actuals, predictions))
    mae = mean_absolute_error(actuals, predictions)
    
    return {'RMSE': rmse, 'MAE': mae, 'predictions': predictions, 'actuals': actuals}

# 使用示例
results = rolling_backtest(basis_data, arima_model_func)
print("回测结果:", results['RMSE'], results['MAE'])

避坑指南:回测结果好,不代表实盘好。我曾经有一个模型,回测R²高达0.85,结果实盘第一个月就亏了——后来发现是数据泄露了。所以我现在做回测有个习惯:留出最后3个月的数据完全不碰,等模型「定型」了再用这3个月做最终验证。

好了,模型讲完了。但记住一句话:模型是工具,不是信仰。再好的模型,也要结合基本面判断。我见过太多人迷信模型,结果被市场狠狠教育了一顿。

下一节,我们会把这些模型整合到风控体系中,看看怎么用它们来管理基差风险。


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