本文概述了我们在Optiver收盘价交易竞赛中荣获私人排行榜第14名的解决方案。
首先,感谢@ravi20076、@mcpenguin、@madarshbb、@cody11null的协作,以及Optiver组织本次竞赛。
同时感谢@wenxuanxx、@zhangyue199、@lblhandsome秉承Kaggle精神分享特征思路和notebook。
背景
业务背景:https://www.kaggle.com/competitions/optiver-trading-at-the-close
数据背景:https://www.kaggle.com/competitions/optiver-trading-at-the-close/data
方法概述
首先,我们修复了公开notebook中的错误,并对本地验证方式做了小修改以避免全局特征处理时的数据泄露:
df['mid_price_movement'] = df['mid_price'].diff(periods=5).apply(lambda x: 1 if x > 0 else (-1 if x < 0 else 0))
改为
df['mid_price_movement'] = df.groupby(["stock_id"])['mid_price'].diff(periods=5).apply(lambda x: 1 if x > 0 else (-1 if x < 0 else 0))
(顺便说一句,这个修复改善了CV分数但降低了公开LB分数。不知道为啥哈哈)
此外,我们重写了RSI、MACD和布林带指标函数,因为公开的实现在推理时结果不准确。
有效方法(对CV的影响)
- 基于已揭示目标值的特征。我们使用按stock_id和seconds_in_bucket分组的目标值滞后1、2、3期作为模型特征(-0.005)
- imbalance_size的有符号表示(-0.003)
- 持续使用已揭示目标值训练模型。我们以固定间隔重新训练LGB和CatBoost模型(稍后详述)(-0.006)
- 流式CV验证。我们将每个时间段的数据保存为<date_id>_<seconds_in_bucket>.csv格式,计算CV时按时间顺序逐个处理。虽然耗时更长但与公开LB相关性更好
- 零和后置处理(-0.005)(由于不确定在私人LB的效果,我们只选用了一个带此处理的提交)
- 全局特征(-0.004)。重新训练模型时需要重新初始化这些值以保持更新
- 技术指标RSI、MACD和布林带。我们重写后获得了更好效果(-0.002)
无效方法(对CV的影响)
- 按date_id和stock_id分组计算滚动特征而非仅stock_id(+0.003)。最终未采用此方法
- 较大x值的滞后特征shift(x)。改善了CV但降低了LB
- 较大窗口x的滚动特征。改善了CV但降低了LB
- 板块特征(+0.002)
- 神经网络
- 三重不平衡特征(+0.001)。发现该特征因精度问题产生极不稳定值,尽管改善了公开LB分数(从5.3315到5.3327),我们仍决定弃用
- 基于特征重要性的特征删除
- 零均值后置处理。会使集成效果和LB/CV相关性变差,因此未选用。实际上零均值集成(5.333)比零和(5.3327)更差
关于该方法的更多讨论点详见此处
提交详情
经过综合考虑,我们最终选择了以下两个提交。感谢@cody11null进行参数调优并使用其大型91模型脚本进行测试。
170个特征,无后置处理。 公开分数5.3384,私人分数5.4457。LGB + CatBoost
重训练策略(假设第X天是首个currently_scored为True的日期):
- 第X天:重训练LGB和CAT
- 第X+6天:重训练LGB
- 第X+12天:重训练CAT
- 第X+18天:重训练LGB
… - 第X+54天:重训练LGB
- 第X+60天:重训练CAT
193个特征,零和后置处理。 公开分数5.3327,私人分数5.4458。LGB + CatBoost
重训练策略(假设第X天是首个currently_scored为True的日期):
- 第X天:重训练LGB和CAT
- 第X+9天:重训练LGB
- 第X+18天:重训练CAT
- 第X+27天:重训练LGB
… - 第X+54天:重训练CAT
每个时间段我们都使用最新的LGB和CAT模型,并提交两个模型预测的平均值。
我们曾尝试使用股票权重,但在重训练时遇到提交评分错误,因此未能继续推进 😢