
Qlib 增强指数化策略实战EnhancedIndexingStrategy 的收益-风险优化与端到端回测全指南【免费下载链接】qlibQlib is an AI-oriented Quant investment platform that aims to use AI tech to empower Quant Research, from exploring ideas to implementing productions. Qlib supports diverse ML modeling paradigms, including supervised learning, market dynamics modeling, and RL, and is now equipped with https://github.com/microsoft/RD-Agent to automate RD process.项目地址: https://gitcode.com/GitHub_Trending/qli/qlib导读本篇指南围绕 QlibAI 量化投资平台的组合优化策略展开聚焦于 examples/portfolio 目录下的增强指数化Enhanced Indexing方案使用EnhancedIndexingStrategy以 AI 模型预测的收益信号为基础在给定基准指数如沪深 300的跟踪误差约束下求解最优权重实现既主动跑赢基准、又被动控制风险的目标。文中将完整覆盖数据准备、统计风险模型生成、优化器数学原理、端到端 YAML 配置解读以及可落地的执行细节读者完成后可直接在本仓库数据集上复现一遍完整的增强指数化回测流程。一、为什么需要组合优化策略在 examples/benchmarks 目录中Qlib 提供了大量alpha 模型如 LightGBM、MLP、Transformer 等用于预测股票收益并统一通过一个简单的基于规则的TopkDropoutStrategy来评估这些模型的投资绩效。但TopkDropoutStrategy这类规则型策略存在明显局限从 qlib/contrib/strategy/signal_strategy.py 的源码可以看到它的核心逻辑本质上是按预测分数排序卖出排名靠后的n_drop只股票、买入新的 topk 股票几乎不做组合层面的风险控制——它无法显式约束组合与指数之间的相关性、波动率等风险暴露。也就是说它无法回答组合相对基准的偏离有多大这类问题它无法在收益与风险之间做结构化权衡当股票间相关性上升时组合可能隐含巨大的集中风险。增强指数化正是为此设计的优化型策略在最大化组合收益的同时最小化相对基准指数的跟踪误差tracking error即用数学优化的方式替代规则打新与剔除。二、数据准备运行示例的前置条件示例使用中国 A 股数据region: cn市场csi300基准SH000300在运行端到端工作流之前需要准备两类数据。2.1 准备 CSI300 成分股权重由于公开免费渠道难以获取指数成分股权重数据原文档说明团队手工构建了这份权重数据并提供了下载脚本wget https://github.com/SunsetWolf/qlib_dataset/releases/releases/download/v0/csi300_weight.zip unzip -d ~/.qlib/qlib_data/cn_data csi300_weight.zip rm -f csi300_weight.zip权重数据解压后放在 Qlib 数据目录~/.qlib/qlib_data/cn_data下与cn_data中原有市场行情数据并列。注意这份权重以$csi300_weight特征的形式被策略读取详见下文 4.3 节源码分析。同时配置文件中的provider_uri默认即指向~/.qlib/qlib_data/cn_data如果你的数据不在默认位置请同步修改 config_enhanced_indexing.yaml 中的qlib_init.provider_uri。2.2 准备风险模型数据运行仓库自带的脚本生成风险数据python prepare_riskdata.py该脚本examples/portfolio/prepare_riskdata.py所做的工作可以拆成五步理解加载股票池与全市场价格通过D.features(D.instruments(csi300), [$close], ...)获取 csi300 成分股的收盘价同时获取全体股票instruments(all)的收盘价并按 instrument 展开为宽表用于后续逐日滚动估计。构造统计风险模型实例化StructuredCovEstimator()这是 Qlib 内置在 qlib/model/riskmodel/structured.py 中的一个统计风险模型Statistical Risk Model。滑动窗口计算以T240个交易日为窗口从2016-01-01起逐日推进取出窗口内的价格序列。收益预处理price.pct_change()计算日收益率并用ret.clip(ret.quantile(0.025), ret.quantile(0.975), axis1)将极端收益截断在 2.5%97.5% 分位数内防止异常值污染协方差估计。风险模型预测并落盘调用riskmodel.predict(ret, is_priceFalse, return_decomposed_componentsTrue)返回因子暴露F、因子协方差cov_b、特质方差var_u三个分解分量然后按交易日YYYYMMDD分目录保存为 pickle 文件。2.3 关于风险模型的选型建议原文档特别强调示例中使用的是统计风险模型但为了获得更好的风险估计质量强烈建议在生产环境中替换为质量更高的风险模型例如基本面风险模型Fundamental Risk Model如 MSCI BARRA 风格因子体系深度风险模型Deep Risk Model基于神经网络学习隐式风险因子以改进协方差矩阵估计的一类方法。从 qlib/model/riskmodel/base.py 的类设计可以看出Qlib 的风险模型统一继承自RiskModel对外暴露统一的predict(X, return_corr, is_price, return_decomposed_components)接口——这意味着无论底层换成 BARRA 风格的基本面模型还是深度模型只要遵循同一接口并返回分解分量EnhancedIndexingStrategy都可以无缝消费其输出。三、EnhancedIndexingStrategy 的架构与工作流EnhancedIndexingStrategy是 Qlib 三类内置策略体系中的权重型策略代表。以 qlib/contrib/strategy/signal_strategy.py 为参照其继承关系为BaseStrategy └── BaseSignalStrategy # 持有 signal模型数据集risk_degree 控制仓位比例 └── WeightStrategyBase # 基于目标权重生成交易决策接入 OrderGenerator └── EnhancedIndexingStrategy # 用组合优化器求解目标权重与TopkDropoutStrategy直接产出买卖订单不同WeightStrategyBase把决策拆成两步先由子类实现generate_target_weight_position(score, current, ...)得到目标权重持仓再统一交给订单生成器OrderGenWOInteractqlib.contrib.strategy.order_generator根据当前持仓与目标权重生成实际委托单。EnhancedIndexingStrategy的构造参数源码 qlib/contrib/strategy/signal_strategy.py#L406-L416参数默认值含义riskmodel_root必填风险模型数据的根目录marketcsi500指数权重特征对应的市场名示例配置中实际使用csi300turn_limitNone调仓约束预留扩展name_mapping{}风险数据文件名的替代映射可覆盖默认的factor_exp/factor_cov/specific_risk/blacklist四个文件名optimizer_kwargs{}透传给EnhancedIndexingOptimizer的参数verboseFalse是否打印优化过程日志3.1 风险数据的目录规范策略要求riskmodel_root下按交易日组织风险数据标准目录结构如下├── /path/to/riskmodel ├──── 20210101 ├────── factor_exp.{csv|pkl|h5} # 因子暴露 F股票 × 因子 ├────── factor_cov.{csv|pkl|h5} # 因子协方差矩阵 cov_b ├────── specific_risk.{csv|pkl|h5} # 特质风险存储波动率即 var_u 的平方根 ├────── blacklist.{csv|pkl|h5} # 可选强制卖出名单实现细节体现在 qlib/contrib/strategy/signal_strategy.py#L436-L460 的get_risk_data(date)方法中日期目录名为riskmodel_root/YYYYMMDD即上文prepare_riskdata.py保存的格式文件通过load_dataset(...)统一加载兼容 csv/pkl/h5 三种格式缺失处理若某股票缺少specific_risk策略会以全市场最大特质风险填充保守假设其波动最大若缺失预测分数则以全部股票中的最低分填充对应组合中该股权重趋近于 0 的倾向当日数据加载后缓存在_riskdata_cache中避免重复 I/Oblacklist若存在其成分股将作为mask_force_sell强制卖出。3.2 逐日目标权重求解过程generate_target_weight_positionqlib/contrib/strategy/signal_strategy.py#L462-L522在每一个交易日执行如下流水线取前一交易日get_pre_trading_date(..., futureTrue)的风险数据若无风险数据则跳过当日优化并告警将模型分数对齐到风险模型股票池 universe 并按缺省补最低分读取当前持仓权重cur_weight并除以risk_degree归一化组合总权重默认等于风险度同时从行情中读取前一日的$csi300_weight作为基准权重wb用前一交易日成交量判断股票可交易性成交量大于 0 视为可交易停牌股进入mask_force_hold强制持有原仓位组合blacklist构造mask_force_sell调用优化器self.optimizer(r, F, cov_b, var_u, w0, wb, mfh, mfs)得到最优权重向量仅保留权重大于 0 的股票构成目标权重持仓返回。这条链路同时解释了 2.1 节中为什么需要额外准备权重数据基准权重不是内置的而是通过D.features(..., [f${market}_weight], ...)从cn_data的$csi300_weight字段读取的。四、EnhancedIndexingOptimizer背后的凸优化问题组合优化的数学内核实现在 qlib/contrib/strategy/optimizer/enhanced_indexing.py并继承自 base.py 中定义的抽象优化器接口BaseOptimizer同样派生自该接口的还有 optimizer.py 中的通用PortfolioOptimizer支持 GMV/MVO/Risk Parity 等。EnhancedIndexingOptimizer与通用PortfolioOptimizer在 qlib/contrib/strategy/optimizer/init.py 中一起导出可按需选用。4.1 数学模型设优化变量为组合权重w记基准权重为wb则基准偏离d w - wb因子偏离v d F原文档所描述的增强指数化目标即最大化收益 − λ × 风险max_w d r - lamb * (v cov_b v var_u d**2) s.t. w 0 sum(w) 1 sum(|w - w0|) delta -b_dev d b_dev -f_dev v f_dev其中风险项v cov_b v var_u d**2是因子风险与特质风险之和正是跟踪误差的方差分解形式约束里包含非负权重、满仓权重和为 1、总换手率上限delta、相对基准的单票偏离上限b_dev、以及相对基准的因子偏离上限f_dev。4.2 关键参数详解以源码 docstring 与实际实现为准各参数含义如下参数默认值含义与影响lamb1风险厌恶系数越大越偏向控制风险delta0.2总换手率上限sum(|w - w0|) delta控制调仓幅度、降低交易成本b_dev0.01相对基准权重的单票偏离上限None时不设该约束f_devNone相对基准的因子偏离上限标量或数组None时不约束因子暴露scale_returnTrue是否将收益信号缩放使其与组合波动率同量级先r r / r.std()再乘上平均风险的对角量epsilon5e-5最小权重阈值优化后低于该值的权重被置 0 并重新归一化以消除噪音仓位solver_kwargs{}透传给 cvxpy 求解器的额外参数4.3 求解器的容错设计源码中值得注意的一个工程细节是两阶段求解降级策略第一次尝试使用cvxpy的ECOS求解器开启warm_start以基准权重wb作为热启动初值要求状态为optimal若失败例如约束过紧导致无解则去掉换手率约束再解一次只要达到optimal或optimal_inaccurate即视为成功若两次都失败策略不会崩溃而是返回当前持仓权重w0即当日不调仓保证回测流程的鲁棒性。这一设计使EnhancedIndexingStrategy在遇到停牌、涨跌停导致可行域退化时仍能稳健运行不会因为单日求解失败而中断整个回测。4.4 与规则策略的定位差异在 qlib/contrib/strategy/init.py 中可以一览 Qlib 内置的完整策略族TopkDropoutStrategy规则打新、WeightStrategyBase及其子类权重优化、TWAPStrategy/SBBStrategyBase/SBBStrategyEMA执行层面、以及SoftTopkStrategy成本控制。增强指数化属于其中显式管理风险暴露的一支更贴近机构投资者指数增强基金的实操形态。五、端到端工作流配置解读运行 examples/portfolio/config_enhanced_indexing.yaml 即可复现完整流程在仓库根目录执行qrun examples/portfolio/config_enhanced_indexing.yamlqrun是 Qlib 提供的配置驱动工作流命令对应 qlib/cli/run.py它会根据 YAML 中声明的 model → dataset → record 链路依次执行训练、信号生成与绩效记录。该配置与基准模型示例 examples/benchmarks/workflow_config_lightgbm_Alpha158.yaml 相比主要改动集中在策略部分把原本的TopkDropoutStrategy替换为优化型策略并新增PortAnaRecord的组合分析环节。各段要点如下。5.1 数据与特征qlib_init / data_handler_configqlib_init: provider_uri: ~/.qlib/qlib_data/cn_data region: cn market: market csi300 benchmark: benchmark SH000300 data_handler_config: data_handler_config start_time: 2008-01-01 end_time: 2020-08-01 fit_start_time: 2008-01-01 fit_end_time: 2014-12-31 instruments: *market股票池固定为csi300基准为上证 300 指数SH000300特征工程使用Alpha158因子集qlib/contrib/data/handler.py训练拟合窗口为 2008-01-01 至 2014-12-31。5.2 模型与数据集tasktask: model: class: LGBModel module_path: qlib.contrib.model.gbdt kwargs: loss: mse colsample_bytree: 0.8879 learning_rate: 0.2 subsample: 0.8789 lambda_l1: 205.6999 lambda_l2: 580.9768 max_depth: 8 num_leaves: 210 num_threads: 20 dataset: class: DatasetH module_path: qlib.data.dataset kwargs: handler: class: Alpha158 module_path: qlib.contrib.data.handler kwargs: *data_handler_config segments: train: [2008-01-01, 2014-12-31] valid: [2015-01-01, 2016-12-31] test: [2017-01-01, 2020-08-01]收益预测模型采用LightGBM 回归器LGBModelmse 损失超参数学习率 0.2、叶子数 210、L1/L2 正则等来自 Alpha158 基准实验的调优结果。数据切分训练 2008–2014、验证 2015–2016、测试 2017–2020-08。可见增强指数化并不要求特殊的预测模型任何能输出收益预测的 alpha 模型都可接入。5.3 组合分析与回测port_analysis_config / recordport_analysis_config: port_analysis_config strategy: class: EnhancedIndexingStrategy module_path: qlib.contrib.strategy kwargs: model: MODEL dataset: DATASET riskmodel_root: ./riskdata backtest: start_time: 2017-01-01 end_time: 2020-08-01 account: 100000000 benchmark: *benchmark exchange_kwargs: limit_threshold: 0.095 deal_price: close open_cost: 0.0005 close_cost: 0.0015 min_cost: 5这部分是全配置的灵魂逐项说明strategy声明使用EnhancedIndexingStrategy模块路径qlib.contrib.strategyriskmodel_root: ./riskdata指向 2.2 节脚本生成的riskdata目录。MODEL、DATASET是配置模板占位符会被qrun自动替换为上方 task 中声明的模型与数据集实例backtest回测区间 2017-01-012020-08-01与测试段一致初始资金 1 亿元exchange_kwargs模拟 A 股交易环境——涨跌停阈值limit_threshold: 0.095约 ±9.5%贴近 10% 涨跌停与价格的取整差异、按收盘价deal_price: close撮合、开仓成本 0.05%、平仓成本 0.15%、单笔最低佣金 5 元。这些参数与基准实验保持一致保证与 TopkDropout 结果的横向可比性。最后通过三段 record 把信号、信号分析和组合绩效串起来record: - class: SignalRecord # 记录预测信号 module_path: qlib.workflow.record_temp kwargs: model: MODEL dataset: DATASET - class: SigAnaRecord # 信号质量分析IC 等 module_path: qlib.workflow.record_temp kwargs: ana_long_short: False ann_scaler: 252 - class: PortAnaRecord # 组合回测分析走 port_analysis_config module_path: qlib.workflow.record_temp kwargs: config: *port_analysis_config其中PortAnaRecord会读取port_analysis_config执行组合回测并生成收益曲线、跟踪误差等分析报告。六、执行顺序与注意事项完整复现的推荐顺序如下准备数据先按 2.1 节解压csi300_weight.zip到~/.qlib/qlib_data/cn_data生成风险数据确认 prepare_riskdata.py 中qlib.init的provider_uri与你的数据路径一致后执行python prepare_riskdata.py脚本会默认在./riskdata/YYYYMMDD/下输出factor_exp.pkl、factor_cov.pkl、specific_risk.pkl三个文件运行工作流执行qrun examples/portfolio/config_enhanced_indexing.yaml期间策略每个调仓日都会加载对应日期的风险模型文件并求解凸优化问题。需要注意几点权重数据依赖基准权重来自行情特征$csi300_weight若未准备该数据策略在读取基准权重时会得到空值示例将无法按预期运行统计风险模型的局限StructuredCovEstimator默认pca、10 个因子也可选fa是从历史收益中学习的潜在因子模型属于轻量级内置方案。其底层实现在 qlib/model/riskmodel/structured.py估计公式为cov F cov_b F.T diag(var_u)若追求更精细的风格暴露刻画可按 2.3 节建议替换为基本面或深度风险模型predict(..., return_decomposed_componentsTrue)的接口约定详见 qlib/model/riskmodel/base.py求解鲁棒性当某日无风险数据时策略会跳过优化并保持原仓位属于预期行为而非错误若配置了过紧的delta/b_dev/f_dev导致不可行优化器会自动降级到去掉换手率约束再解、仍失败则维持现仓因此调大riskmodel_root覆盖的历史范围有助于减少跳过次数。七、扩展思路参数调优EnhancedIndexingOptimizer的lamb风险厌恶、delta换手限制、b_dev跟踪误差上限共同决定了组合的激进程度。delta0.2意味着单次调仓最多改变 20% 的权重更保守的设置可显著降低交易成本风险源替换将riskmodel_root指向更高质量风险模型生成的同构数据目录即可完成升级目录规范与文件名可通过name_mapping调整保持不变组合绩效分析运行结束后可在 MLflow 记录中查看PortAnaRecord产出的组合级绩效对比同一 alpha 模型在TopkDropoutStrategy与EnhancedIndexingStrategy下的回测结果可以直观体会到风险约束对回撤与波动率的改善。【免费下载链接】qlibQlib is an AI-oriented Quant investment platform that aims to use AI tech to empower Quant Research, from exploring ideas to implementing productions. Qlib supports diverse ML modeling paradigms, including supervised learning, market dynamics modeling, and RL, and is now equipped with https://github.com/microsoft/RD-Agent to automate RD process.项目地址: https://gitcode.com/GitHub_Trending/qli/qlib创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考