kyle_作业
由bqmu1wjw创建,最终由bqmu1wjw 被浏览 3 用户
存档_1:学习老韵作业\n1️⃣ 这段代码在做什么
用横截面“分位数因子”训练一个轻量 XGBoost 回归器,每 60 个交易日重训,毎 5 日调仓,按预测分数等权买入 Top10。\n同时在每次训练后记录 MSE/MAE/R²/IC 与特征重要性,回测结束把训练历史与绩效打包保存。
2️⃣ 数据与因子(initialize / SQL)
- 数据源:cn_stock_prefactors(已过滤 is_risk_warning=0、list_days>100)。
- 因子全部做横截面分位数:pct_rank_by(date, …),把不同量纲压到 0–1,适合线/树混用。
- fac_rank_total_market_cap:ln(total_market_cap) 当日分位数(规模)。
- fac_rank_turn:换手率分位数(流动性/情绪)。
- fac_ret_5:close/m_lag(close,5) 当日分位数(近 5 日动量)。
- 若干候选因子被注释掉(close 分位、net_profit_mrq_yoy、量能比、20 日波动、momentum5),注释缘由写在文件头注释里:净利同比多次为 0、为提速先精简。
- 标签(label):pct_rank_by(date, m_lead(close,2)/m_lead(close,1))\n解释:看 明天到后天这一段“相对收益”的横截面分位数(0–1)。这是短期相对强弱的目标,不是绝对收益。
3️⃣ 训练与预测时序(before_trading_start)
-
关键参数:
- 训练窗 train_days=252(≈1 年交易日)
- 重训间隔 retrain=60(为了提速)
- 调仓周期 holding_days=5
- lookback_days=10(保证 m_lag/m_lead 有足够的数据边界)
-
什么时候训练:当 trading_day_index % 60 == 0。
- 查询 [train_days + lookback_days] 的原始窗口;
- 再截出真正的训练期 [train_days];
- dropna 清洗,样本 < 50 或 y.std() 太小就跳过;
- 特征做 StandardScaler(树模型其实不需要,但保留也不伤);
- 训练 XGBRegressor(极速参数:20 棵树、深度 2、lr=0.1、subsample=0.7,n_jobs=4);
- 计算训练内 MSE/MAE/R² 与 IC(y 与 ŷ 相关系数);记录 特征重要性;把这些塞进 context.training_history。
-
什么时候预测/下单:当 trading_day_index % 5 == 0。
- 取 lookback_days 内数据,但只保留 当天 current_date 的一行截面;
- 用训练时的 scaler 做 transform,喂给 XGB,得到 score;
- 把 instrument, score 放进 context.pred 交给盘中执行。
4️⃣ 交易执行(handle_data)
- 从 context.pred 里挑 Top 10 得分股票等权买入;
- 卖出当前持有但不在目标集合的股票;
- 成交按 开盘价(order_price_field_*='open'),与“盘前计算信号”逻辑一致。
5️⃣ 结果保存与回顾
- 训练历史:在 after_trading 的最后一天(硬编码 '2025-08-08')调用 save_training_history_only,把每次训练的评估指标与特征重要性序列化到 pkl。
- 整体绩效:回测后调用 save_strategy_simple,把 performance.stats、净值序列、收益率序列和训练历史一起保存。
6️⃣ 优缺点
👍 优点
- 时序安全:标签用 m_lead,训练只到“今天”,靠 dropna 避免用到“未来不可得”的行。
- 轻量稳妥:分位数因子 + 浅树 + 降采样,计算快、抗异常值。
- 可解释:记录了 MSE/MAE/R²/IC 与 XGB 的 feature_importances_。
⚠️ 风险点 / 兼容性
- 目标-持有期不一致(上面已提醒)。
- StandardScaler 对树无必要:可以直接喂分位数特征(0–1),节省少量时间。
- 只用 3 个因子:容量足够但 α 限;可酌情把注释的低波动或量能比加回。
- global_training_history 的使用:在 initialize 里把全局变量指向了 context.training_history,之后每次 append 都会反映到全局引用,因此能在末尾 save_strategy_simple(..., global_training_history) 正常保存——这点是 OK 的。
- 如果要更稳,建议把 after_trading 的 end_date='2025-08-08' 改成读取 context.end_date(避免换日期就忘了改常量)。
\
https://bigquant.com/codesharev3/aaef2ff6-7540-4885-93f4-0af39e4b45e0
\