quant-concept-drift
Description
Concept Drift Adaptation in Stock Prediction on CSI300
Objective
Design and implement a stock prediction model that handles concept drift and temporal distribution shift in CSI300 stocks. Your code goes in custom_model.py. Three reference implementations (TRA, AdaRNN, LightGBM) are provided as read-only.
Evaluation
Signal quality: IC, ICIR, Rank IC. Portfolio (TopkDropout, top 50, drop 5): Annualized Return, Max Drawdown, Information Ratio. Automatic via qlib's workflow.
Evaluation uses three fixed temporal regimes on the same CSI300 universe:
csi300: long-horizon split ending in the 2017-2020 regimecsi300_shifted: shifted split with a 2016-2018 test regimecsi300_recent(hidden): the most recent 2019-2020 regime
This task is about temporal drift adaptation, not cross-universe transfer.
Workflow Configuration
workflow_config.yaml lines 13-26 and 32-45 are editable. This covers the model plus dataset adapter/processor configuration needed by methods like TRA. Instruments, date ranges, train/valid/test splits, and evaluation settings are fixed.
Code
1# Custom stock prediction model for MLS-Bench (concept drift adaptation)2#3# EDITABLE section: CustomModel class with fit() and predict() methods.4# FIXED sections: imports below.5import numpy as np6import pandas as pd7import torch8import torch.nn as nn9import torch.nn.functional as F10from qlib.model.base import Model11from qlib.data.dataset import DatasetH12from qlib.data.dataset.handler import DataHandlerLP1314DEVICE = "cuda" if torch.cuda.is_available() else "cpu"15
1# Qlib workflow configuration for CSI300 concept drift adaptation benchmark.2# Used by run_workflow.py — default Alpha158/CSI300/DatasetH pipeline.3# Alpha158: 158 engineered features per stock per day.45qlib_init:6provider_uri: "~/.qlib/qlib_data/cn_data"7region: cn89sys:10rel_path:11- "." # So custom_model.py is importable via module_path1213task:14model:15class: CustomModel
Additional context files (read-only):
qlib/qlib/model/base.py
Results
| Model | Type | ic csi300 shifted ↑ | icir csi300 shifted ↑ | rank ic csi300 shifted ↑ | rank icir csi300 shifted ↑ | annualized return csi300 shifted ↑ | max drawdown csi300 shifted ↓ | information ratio csi300 shifted ↑ | ic csi300 recent ↑ | icir csi300 recent ↑ | rank ic csi300 recent ↑ | rank icir csi300 recent ↑ | annualized return csi300 recent ↑ | max drawdown csi300 recent ↓ | information ratio csi300 recent ↑ | ic csi300 ↑ | icir csi300 ↑ | rank ic csi300 ↑ | rank icir csi300 ↑ | annualized return csi300 ↑ | max drawdown csi300 ↓ | information ratio csi300 ↑ |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| adarnn | baseline | 0.045 | 0.439 | 0.045 | 0.438 | 0.138 | -0.081 | 1.815 | 0.017 | 0.154 | 0.028 | 0.253 | 0.021 | -0.065 | 0.283 | 0.036 | 0.319 | 0.040 | 0.365 | 0.050 | -0.104 | 0.673 |
| adarnn | baseline | 0.057 | 0.516 | 0.059 | 0.519 | 0.122 | -0.081 | 1.482 | 0.017 | 0.169 | 0.028 | 0.274 | 0.000 | -0.083 | 0.004 | 0.039 | 0.310 | 0.050 | 0.392 | 0.076 | -0.087 | 1.195 |
| adarnn | baseline | 0.056 | 0.450 | 0.061 | 0.483 | 0.151 | -0.148 | 1.691 | 0.026 | 0.207 | 0.040 | 0.329 | 0.084 | -0.049 | 1.118 | 0.040 | 0.331 | 0.050 | 0.413 | 0.097 | -0.082 | 1.399 |
| lgbm | baseline | 0.055 | 0.430 | 0.064 | 0.510 | 0.103 | -0.079 | 1.299 | 0.025 | 0.185 | 0.044 | 0.322 | 0.081 | -0.051 | 1.104 | 0.046 | 0.364 | 0.057 | 0.466 | 0.092 | -0.058 | 1.347 |
| lgbm | baseline | 0.055 | 0.430 | 0.064 | 0.510 | 0.103 | -0.079 | 1.299 | 0.025 | 0.185 | 0.044 | 0.322 | 0.081 | -0.051 | 1.104 | 0.046 | 0.364 | 0.057 | 0.466 | 0.092 | -0.058 | 1.347 |
| lgbm | baseline | 0.055 | 0.430 | 0.064 | 0.510 | 0.103 | -0.079 | 1.299 | 0.025 | 0.185 | 0.044 | 0.322 | 0.081 | -0.051 | 1.104 | 0.046 | 0.364 | 0.057 | 0.466 | 0.092 | -0.058 | 1.347 |
| lgbm | baseline | 0.055 | 0.430 | 0.064 | 0.510 | 0.103 | -0.079 | 1.299 | 0.025 | 0.185 | 0.044 | 0.322 | 0.081 | -0.051 | 1.104 | 0.046 | 0.364 | 0.057 | 0.466 | 0.092 | -0.058 | 1.347 |
| tra | baseline | 0.051 | 0.428 | 0.055 | 0.459 | 0.122 | -0.084 | 1.587 | 0.024 | 0.192 | 0.040 | 0.330 | 0.033 | -0.071 | 0.480 | 0.042 | 0.335 | 0.050 | 0.423 | 0.064 | -0.100 | 1.008 |
| tra | baseline | 0.051 | 0.428 | 0.055 | 0.459 | 0.122 | -0.084 | 1.587 | 0.024 | 0.192 | 0.040 | 0.330 | 0.033 | -0.071 | 0.480 | 0.042 | 0.335 | 0.050 | 0.423 | 0.064 | -0.100 | 1.008 |
| tra | baseline | 0.051 | 0.428 | 0.055 | 0.459 | 0.122 | -0.084 | 1.587 | 0.024 | 0.192 | 0.040 | 0.330 | 0.033 | -0.071 | 0.480 | 0.042 | 0.335 | 0.050 | 0.423 | 0.064 | -0.100 | 1.008 |
| anthropic/claude-opus-4.6 | vanilla | 0.054 | 0.408 | 0.065 | 0.500 | 0.157 | -0.088 | 1.841 | 0.025 | 0.175 | 0.046 | 0.324 | 0.048 | -0.058 | 0.655 | 0.043 | 0.323 | 0.056 | 0.426 | 0.102 | -0.055 | 1.420 |
| google/gemini-3.1-pro-preview | vanilla | 0.047 | 0.326 | 0.063 | 0.427 | 0.149 | -0.082 | 1.764 | 0.016 | 0.105 | 0.037 | 0.238 | -0.016 | -0.094 | -0.219 | 0.041 | 0.292 | 0.055 | 0.384 | 0.008 | -0.119 | 0.113 |
| gpt-5.4-pro | vanilla | 0.020 | 0.118 | 0.034 | 0.190 | -0.050 | -0.354 | -0.457 | 0.019 | 0.131 | 0.036 | 0.265 | 0.031 | -0.076 | 0.402 | 0.012 | 0.075 | 0.029 | 0.171 | -0.086 | -0.361 | -0.823 |
| anthropic/claude-opus-4.6 | agent | 0.054 | 0.400 | 0.066 | 0.497 | 0.189 | -0.086 | 2.210 | 0.024 | 0.168 | 0.046 | 0.322 | 0.051 | -0.052 | 0.699 | 0.043 | 0.319 | 0.055 | 0.422 | 0.060 | -0.114 | 0.843 |
| google/gemini-3.1-pro-preview | agent | 0.047 | 0.326 | 0.063 | 0.427 | 0.149 | -0.082 | 1.764 | 0.016 | 0.105 | 0.037 | 0.238 | -0.016 | -0.094 | -0.219 | 0.041 | 0.292 | 0.055 | 0.384 | 0.008 | -0.119 | 0.113 |
| gpt-5.4-pro | agent | 0.050 | 0.344 | 0.067 | 0.501 | 0.167 | -0.040 | 2.153 | 0.020 | 0.148 | 0.044 | 0.313 | -0.030 | -0.121 | -0.406 | 0.029 | 0.198 | 0.051 | 0.368 | -0.011 | -0.134 | -0.149 |