第二十四章:冲击成本模型评估:模型比较、预测误差、稳健性检验
模型建好了,参数也调了,然后呢?
说实话,很多人在这一步就停了。觉得模型跑通了,回测曲线漂亮,就万事大吉。但我个人的经验告诉我——模型评估才是真正见真章的地方。你想想看,一个模型在样本内表现再好,到了实盘里被打脸,那才是真疼。
24.1 为什么要做模型评估?
冲击成本模型,说白了就是预测「我这一单下去,市场会怎么动」。但预测这件事,天生就有误差。我们需要搞清楚三件事:
- 哪个模型更准?——模型比较
- 误差有多大?——预测误差分析
- 换个时间段还灵不灵?——稳健性检验
我在项目中遇到过这样的情况:一个模型在去年表现极好,今年突然就崩了。后来一查,是因为市场微观结构变了。嗯,这就是稳健性没做好的典型。
24.2 模型比较:谁才是真英雄?
常见的冲击成本模型就那么几种:线性模型、平方根模型、I-Star模型、以及一些机器学习模型。怎么比?不能光看R²。
24.2.1 比较框架
我个人习惯用三个维度来比较:
- 拟合优度:模型对历史数据的解释能力
- 预测精度:样本外预测的误差大小
- 经济意义:模型参数是否符合直觉
举个例子,我曾经见过一个模型,R²高达0.95,但参数是负的——交易量越大冲击成本越小?这明显违背常识。这种模型,再好看也不能用。
24.2.2 常用比较指标
| 指标 | 含义 | 适用场景 |
|---|---|---|
| R² | 解释方差比例 | 模型整体拟合度 |
| MAE | 平均绝对误差 | 误差的直观大小 |
| RMSE | 均方根误差 | 对大误差更敏感 |
| MAPE | 平均绝对百分比误差 | 相对误差比较 |
24.3 预测误差分析:误差从哪里来?
模型预测值和实际值之间的差距,就是误差。但误差不是随机噪声,它往往有规律可循。
24.3.1 误差分解
我把误差拆成三部分:
- 偏差(Bias):系统性的高估或低估
- 方差(Variance):预测值的波动程度
- 噪声(Noise):不可解释的随机部分
为什么会这样?说白了,偏差大说明模型结构有问题,方差大说明模型对数据太敏感。我见过一个团队,他们的模型偏差一直为正——永远低估冲击成本。后来发现是忘了考虑订单方向的影响。
24.3.2 误差诊断工具
我常用的几个工具:
# 残差分析示例
import numpy as np
import matplotlib.pyplot as plt
# 假设 y_true 和 y_pred 是真实值和预测值
residuals = y_true - y_pred
# 1. 残差 vs 预测值散点图
plt.scatter(y_pred, residuals)
plt.axhline(y=0, color='r', linestyle='--')
plt.xlabel('预测值')
plt.ylabel('残差')
plt.title('残差诊断图')
# 2. 残差自相关检验
from statsmodels.stats.stattools import durbin_watson
dw = durbin_watson(residuals)
print(f'Durbin-Watson统计量: {dw:.3f}')
# 接近2说明无自相关,远离2说明有问题
24.4 稳健性检验:换个环境还灵吗?
稳健性检验,说白了就是「折腾」你的模型。看看它在不同条件下还能不能打。
24.4.1 时间维度稳健性
我最常用的方法:
- 滚动窗口检验:用过去6个月的数据训练,预测下1个月,然后滚动
- 不同市场状态:牛市、熊市、震荡市分别测试
- 极端事件测试:比如2020年3月的流动性危机
我记得有一次,一个模型在正常市场下表现完美,但一遇到2020年3月的熔断行情,预测误差直接翻了5倍。嗯,这就是没做极端事件测试的后果。
24.4.2 参数敏感性分析
模型参数稍微变一点,结果会不会大变?如果会,那这个模型就不可靠。
# 参数敏感性分析示例
def sensitivity_analysis(model, param_name, param_range):
"""
对模型参数进行敏感性分析
param_name: 参数名称
param_range: 参数取值范围
"""
results = []
for param_value in param_range:
# 修改模型参数
model.set_params(**{param_name: param_value})
# 计算预测误差
error = evaluate_model(model)
results.append((param_value, error))
return results
# 分析衰减因子 lambda 的敏感性
lambda_range = np.linspace(0.5, 0.99, 20)
sensitivity = sensitivity_analysis(model, 'lambda', lambda_range)
核心观点: 一个稳健的模型,参数微调时预测误差应该变化平缓。如果某个参数稍微一动,误差就剧烈波动,那这个模型在实盘中很可能翻车。
24.5 知识体系总览
下面这张图,是我对冲击成本模型评估的完整理解框架:
24.6 实战建议
说了这么多,最后给几条实在的建议:
- 别迷信一个指标:R²高不代表一切,我见过R² 0.98的模型在实盘里亏钱
- 分场景评估:大单和小单的冲击成本特征完全不同,要分开测
- 留足样本外数据:我一般留30%的数据做样本外测试,绝不偷看
- 定期重新评估:市场在变,模型也会老化。建议每季度做一次全面评估