本项目研究股票预测中的三类任务:
- 点预测:对下一交易日横截面收益率做排序,核心指标为 IC、RankIC、ICIR、RankICIR。
- 分布预测:生成每只股票下一交易日收益率的多个可能场景,核心指标为 CRPS、NLL、RMSE、Cov90。
- 组合优化:把点预测分数或 diffusion 生成场景转化为 top-k long-only / long-short 投资组合,核心指标为 Sharpe、年化收益、波动率和最大回撤。
核心方法包括:
- DYCOR+:在 DYCOR 的动态关系建模框架上,引入可学习的 market prototypes、soft subcluster prototypes、stock-wise relation gate 和 residual gate,使关系结构直接服务于收益率排序。
- Conditional residual diffusion:在点预测模型输出的 alpha 上学习残差分布,生成多组未来收益率场景,用于分布评价和组合评分。
DLFDA-Project-2/
.gitignore
LICENSE
README.md
requirements.txt
src/
main.py # 点预测训练入口
config.py # 数据集与模型默认配置
data_loader.py # 股票面板数据读取
train.py # 训练、验证、保存 checkpoint
visualization.py # 训练曲线绘图
model/
aggregation.py # cluster 表示聚合
clustering.py # 动态聚类与分组工具
dlinear.py # DLinear 组件
dycor.py # DYCOR
dycor_plus.py # DYCOR+
encoding.py # 股票窗口编码器
intra_corr.py # cluster 内注意力模块
sequence_baselines.py # MLP/CNN/LSTM/Transformer/TimeMixer/iTransformer/Mamba
utils/
evaluator.py # DYCOR 风格 IC / RankIC 评价
loss.py # Huber loss、correlation-aware loss、rank loss
scripts/
build_crsp_clean_panels.py # 生成 BASIC/RICH/QONLY/QRICH 四组 CRSP 面板
build_qlib_style_dataset.py # 从已有面板追加 Qlib-style rolling factors
subset_npz_features.py # 特征子集抽取
evaluate_predictions.py # 点预测与 top-k 评价
evaluate_portfolio_decisions.py
# 成本敏感 portfolio 评价
export_dycor_predictions.py # 导出点预测与 diffusion 条件输入
export_panel_for_diffusion.py
# 从原始 npz 面板导出 diffusion split
export_point_result_from_npz_split.py
# 将导出 split 转成 result_data 格式
train_return_diffusion.py # residual diffusion 训练与分布评价
eval_diffusion_samples_only.py
# 只评估 diffusion checkpoint 并保存 samples
rebuild_diffusion_metrics_from_saved_arrays.py
# 从保存 samples 重建 diffusion 指标
select_portfolio_by_validation.py
# 用 validation 选择 portfolio 策略
paper/
main.pdf # 最终论文 PDF
slides.pdf # 最终展示 PDF
data/
README.md # 数据放置说明
建议使用 Python 3.10 或 3.11。
conda create -n dlfda python=3.10 -y
conda activate dlfda
pip install -r requirements.txtGPU 训练需要安装与 CUDA 版本匹配的 PyTorch,并确认 torch.cuda.is_available() 为 True。
将 CRSP Daily Stock Flat File 放到:
data/us.csv
主要字段包括 PERMNO、Ticker、DlyCalDt、DlyRet、DlyPrc、DlyPrcVol、DlyVol、DlyOpen、DlyHigh、DlyLow、DlyClose、DlyCap、ShrOut 等。
推荐使用统一预处理脚本生成 3000 支股票版本:
python scripts/build_crsp_clean_panels.py \
--input data/us.csv \
--output-dir data \
--prefix US_CRSP \
--start-date 2008-01-01 \
--valid-start 2019-01-01 \
--test-start 2021-01-01 \
--end-date 2022-12-31 \
--max-stocks 3000 \
--min-train-coverage 0.70 \
--min-avg-price 3.0脚本会生成:
data/US_CRSP_BASIC3000.npz
data/US_CRSP_RICH3000.npz
data/US_CRSP_QONLY3000.npz
data/US_CRSP_QRICH3000.npz
data/US_CRSP_clean_universe.csv
四组特征含义:
| Setting | 维度 | 含义 |
|---|---|---|
| BASIC | 5 | DYCOR 风格基础特征:收益指数、日收益、短期动量、波动率、成交额 |
| RICH | 27 | CRSP 派生特征:收益、动量、波动率、下行风险、流动性、市值、beta、市场状态、复权因子 |
| QONLY | 144 | Qlib-style rolling factors:多窗口动量、均值收益、正收益比例、波动率、beta、市场相关性、相对收益及横截面标准化版本 |
| QRICH | 171 | RICH 与 QONLY 拼接 |
1500 支股票版本可通过修改 --max-stocks 1500 生成,对应文件名中的 3000 改为 1500。
训练入口为 src/main.py。--market 对应 src/config.py 中的数据集名称,--architecture 对应模型结构。
python src/main.py \
--market US_CRSP_QRICH3000 \
--architecture dycor_plus \
--gpu 0 \
--seed 2605 \
--selection-metric RankIC \
--run-name qrich3000_dycor_plus_seed2605python src/main.py \
--market US_CRSP_QRICH3000 \
--architecture dycor \
--gpu 0 \
--seed 2605 \
--selection-metric RankIC \
--run-name qrich3000_dycor_seed2605for model in lstm transformer timemixer itransformer; do
python src/main.py \
--market US_CRSP_QRICH3000 \
--architecture "$model" \
--gpu 0 \
--seed 2605 \
--selection-metric RankIC \
--run-name "qrich3000_${model}_seed2605"
done训练产物位于:
results/<market>/<run-name>/
best_model.pth
point_metrics_final.json
metrics_history.json
training_history.json
result_data/
prediction.npy
gt.npy
mask.npy
price.npy
python scripts/evaluate_predictions.py \
--result-dir results/US_CRSP_QRICH3000/qrich3000_dycor_plus_seed2605 \
--output results/US_CRSP_QRICH3000/qrich3000_dycor_plus_seed2605/extended_metrics.json对训练好的点预测 checkpoint 导出 train/valid/test 三个 split:
python scripts/export_dycor_predictions.py \
--market US_CRSP_QRICH3000 \
--architecture dycor_plus \
--checkpoint results/US_CRSP_QRICH3000/qrich3000_dycor_plus_seed2605/best_model.pth \
--output-dir exports/qrich3000_dycor_plus_seed2605 \
--gpu 0 \
--include-reps输出:
exports/qrich3000_dycor_plus_seed2605/
train.npz
valid.npz
test.npz
其中包含点预测 prediction、真实收益 target、有效交易 mask、最新特征 last_features,以及可选的股票关系表示 stock_reps。
Residual diffusion 学习:
残差 = 真实收益 - 点预测 alpha
训练命令:
python scripts/train_return_diffusion.py \
--export-dir exports/qrich3000_dycor_plus_seed2605 \
--output-dir results/US_CRSP_QRICH3000/qrich3000_dycor_plus_seed2605_diffusion \
--gpu 0 \
--seed 1 \
--model-type mlp \
--diffusion-target residual \
--condition-source alpha_features \
--use-stock-reps \
--condition-mode gated_reps \
--epochs 40 \
--batch-size 16 \
--learning-rate 1e-4 \
--diffusion-steps 50 \
--d-model 64 \
--layers 3 \
--eval-every 2 \
--patience 8 \
--valid-samples 8 \
--test-samples 32 \
--sample-batch-days 16 \
--save-samples主要输出:
results/..._diffusion/
best_model.pth
metrics.json
valid_samples.npy
test_samples.npy
result_data/
metrics.json 中包含分布指标、点预测基准指标、diffusion sample score 指标和 portfolio 指标。
先把导出的 valid/test 点预测 split 转成 portfolio 评价脚本读取的 result_data/ 格式:
python scripts/export_point_result_from_npz_split.py \
--input exports/qrich3000_dycor_plus_seed2605/valid.npz \
--output-dir exports/qrich3000_dycor_plus_seed2605/point_valid
python scripts/export_point_result_from_npz_split.py \
--input exports/qrich3000_dycor_plus_seed2605/test.npz \
--output-dir exports/qrich3000_dycor_plus_seed2605/point_test对 validation split 进行成本敏感组合评价:
python scripts/evaluate_portfolio_decisions.py \
--point-result-dir exports/qrich3000_dycor_plus_seed2605/point_valid \
--diffusion-result-dir results/US_CRSP_QRICH3000/qrich3000_dycor_plus_seed2605_diffusion \
--diffusion-result-data-subdir valid_result_data \
--output results/US_CRSP_QRICH3000/qrich3000_dycor_plus_seed2605_diffusion/portfolio_valid.json \
--topk 30 \
--cost-bps 0 5 10 20 \
--long-short \
--optimize-distribution \
--candidate-k 30 50 75 100 150 200 \
--risk-aversion 0.1 0.25 0.5 1.0 2.0 5.0对 test split 使用相同策略池进行评价:
python scripts/evaluate_portfolio_decisions.py \
--point-result-dir exports/qrich3000_dycor_plus_seed2605/point_test \
--diffusion-result-dir results/US_CRSP_QRICH3000/qrich3000_dycor_plus_seed2605_diffusion \
--diffusion-result-data-subdir result_data \
--output results/US_CRSP_QRICH3000/qrich3000_dycor_plus_seed2605_diffusion/portfolio_test.json \
--topk 30 \
--cost-bps 0 5 10 20 \
--long-short \
--optimize-distribution \
--candidate-k 30 50 75 100 150 200 \
--risk-aversion 0.1 0.25 0.5 1.0 2.0 5.0用 validation 选择组合策略,并报告 test 表现:
python scripts/select_portfolio_by_validation.py \
--valid-json results/US_CRSP_QRICH3000/qrich3000_dycor_plus_seed2605_diffusion/portfolio_valid.json \
--test-json results/US_CRSP_QRICH3000/qrich3000_dycor_plus_seed2605_diffusion/portfolio_test.json \
--output results/US_CRSP_QRICH3000/qrich3000_dycor_plus_seed2605_diffusion/portfolio_selected.json \
--topk 30 \
--cost-bps 10 \
--side long \
--metric sharpe多 GPU 实验建议显式指定 CUDA_VISIBLE_DEVICES 或为每个进程传入不同 --gpu。例如:
CUDA_VISIBLE_DEVICES=0 python src/main.py --market US_CRSP_QRICH3000 --architecture dycor_plus --gpu 0 --seed 2605
CUDA_VISIBLE_DEVICES=1 python src/main.py --market US_CRSP_QRICH3000 --architecture transformer --gpu 0 --seed 2605最终论文位于 paper/:
paper/main.pdf
paper/slides.pdf
Git 仓库只保存代码、最终论文、小型说明文件。以下内容由脚本生成,不进入 Git:
data/*.npz、data/*.csv、data/*.pklresults/logs/exports/experiment_artifacts/*.pth、*.pt、*.npy
这样可以保证仓库轻量,并让实验结果通过命令重新生成。