返回列表

9th Place Solution

598. Optiver - Trading at the Close | optiver-trading-at-the-close

开始: 2023-09-20 结束: 2024-03-22 量化投资 数据算法赛

第9名解决方案

作者: ADAM. (Kaggle Grandmaster)

排名: 第9名

发布日期: 2024年3月26日

得票数: 67票

非常感谢Optiver和Kaggle举办这次比赛。这场比赛的本地CV分数与LB分数之间的相关性非常稳定。

实际上我参赛较晚,距离比赛结束大约只有30天,而且我不太擅长神经网络,因此我只专注于梯度提升树模型及其特征工程。我注意到许多顶级解决方案都使用了神经网络,这对我来说是一个很好的学习神经网络的机会。

模型

  • 使用Xgboost配合3个不同的随机种子,使用相同的157个特征
    • 在LB分数上,Xgboost和Lightgbm之间没有太大差异。但是GPU版本的Xgboost比GPU版本的Lightgbm训练更快。

特征工程

  • 首先,基于原始特征创建一些"基本特征"(即对原始特征进行加、减、乘、除运算)。同时,创建一些经过中位数缩放后的原始规模特征。
    size_col = ['imbalance_size','matched_size','bid_size','ask_size']
    for _ in size_col:
        train[f"scale_{_}"] = train[_] / train.groupby(['stock_id'])[_].transform('median')
  • 其次,对原始特征和"基本特征"进行进一步的特征工程/聚合操作:
    • imb1, imb2 特征
    • market_urgency 特征(从公开笔记中复制)
    • 不同时间窗口的差值特征
    • 不同时间窗口的平移特征
    • 不同时间窗口的滚动均值/标准差特征
    • 使用历史WAP计算6秒前的目标值,然后进行滚动均值计算
    • 一些全局的date_id+seconds加权特征
    • MACD特征
    • 基于stock_id + seconds_in_bucket的目标滚动均值

特征选择

  • 由于我们在推理时间和内存方面有限制,进行特征选择至关重要。我按组添加特征,并检查本地CV是否有所改善。每个特征组通常包含10-30个特征。如果一个组的添加使本地CV提升,我会逐一添加该组内的特征,通常只保留最有效的5-10个特征。
  • 我在最终模型中保留了157个特征。

后处理

  • 减去加权和。根据目标值的定义,所有股票的加权和应该为零。
    test_df['pred'] = lgb_predictions
    test_df['w_pred'] = test_df['weight'] * test_df['pred']
    test_df["post_num"] = test_df.groupby(["date_id","seconds_in_bucket"])['w_pred'].transform('sum') / test_df.groupby(["date_id","seconds_in_bucket"])['weight'].transform('sum')
    test_df['pred'] = test_df['pred'] - test_df['post_num']

其他要点

  • XGB使用MAE目标函数
  • XGB样本权重:对最近45天的数据赋予1.5倍的权重
  • 在线训练:我只重新训练了模型两次,一次是第N天(N是私有LB的开始日期),另一次是第N+30天
  • Polars库和reduce_mem_usage函数帮助很大

代码链接

同比赛其他方案