Qlib QlibRL 使用指南:面向不同背景开发者的强化学习量化策略上手路径
【免费下载链接】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 R&D process.项目地址: https://gitcode.com/GitHub_Trending/qli/qlib
本文基于 Qlib 官方文档中的 QlibRL Guidance 指南编写,面向三类读者(RL 新手、RL 算法研究者、量化研究员)给出各自定制化的 QlibRL 学习路径,并结合 examples/rl_order_execution/ 中单资产订单执行(SAOE)示例的配置文件与 qlib/rl/order_execution/ 下的 MDP 组件源码,帮助你在读完之后掌握"按自身背景选路径 → 跑通训练与回测 → 自定义 State/Action/Reward 等组件"的完整实操能力。
QlibRL 是什么,为哪类人解决什么问题
QlibRL 是 Qlib 中的强化学习(Reinforcement Learning, RL)工具包,用于帮助用户快速上手、便捷地实现基于 RL 算法的量化策略。与"一锅端"的教程不同,官方指南(docs/component/rl/guidance.rst)的核心思路是:按读者的知识背景给出差异化路径。不同读者在"RL 算法知识"与"金融领域知识"两个维度上的储备不同,需要补齐的东西也不同:
| 读者类型 | 已具备 | 需要补齐 | 指南推荐路径 |
|---|---|---|---|
| 强化学习算法新手 | 基本编程/量化常识 | RL 基础、RL 适用场景、QlibRL 框架 | 基础 → 场景 → 示例 → 框架与定制 |
| RL 算法研究者 | RL 算法知识 | 金融交易领域知识 | 场景 → 跑通示例 → 改写 policy 注入自己的算法 |
| 量化研究员 | 金融领域知识、编码能力 | RL 算法、MDP 建模方法 | 基础 → 场景 → 示例 → 框架 → 选算法 → 设计 MDP |
下面按"路径中的每一步"展开:先讲 RL 基础与适用场景(对应 part1/part2),再讲如何跑通官方示例(对应 part3),最后讲框架结构与组件级定制(对应 part4)。
Part 1:RL 基础——四个要素与"试错学习"
这一部分继承自指南的 part1(docs/component/rl/overall.rst)。与分类、回归等监督学习任务不同,RL 是机器学习的另一大范式:智能体(agent)通过与环境的直接交互来优化累积的数值奖励信号,并通常在马尔可夫决策过程(MDP)等假设下建模问题。
一个 RL 系统由四个要素构成:
- Agent(智能体):决策主体;
- Environment(环境):智能体交互的对象;
- Policy(策略):智能体据以对环境影响采取动作的规则;
- Reward(奖励信号):环境反馈给智能体的标量信号。
整体上,智能体感知并解释环境、执行动作、并通过奖励学习,以求长期总奖励最大化为目标。与监督学习从标签学习不同,RL 通过"试错"采样动作,观察哪些动作带来期望结果,从而得到能产生最优动作的策略——奖励是一个延迟标签,告诉我们当前结果是好是坏。一句话概括:RL 的目标就是采取行动使奖励最大化。
Part 2:RL 在量化交易中的潜在应用场景
这一部分继承自指南的 part2(docs/component/rl/overall.rst)。投资本质上是一个持续决策过程:投资者通过买卖行为管理持仓与持股,并在每次决策前评估市场状态与个股信息——这正是"与交互环境驱动的连续决策",也是 RL 的优势场景。文档归纳了两类典型场景:
订单执行(Order Execution)
订单执行任务要求在执行订单时综合考虑:最优价格、最小化交易成本、降低市场冲击、最大化订单完成率(fill rate)、在指定时间窗口内完成执行。RL 的做法是把这些目标全部编码进奖励函数与动作选择过程:智能体与市场环境交互、从市场信息中观察状态、决定下一步执行量,通过试错学习最优执行策略以最大化期望累积奖励。其一般化 MDP 设定为:
- Environment(环境):订单执行发生的金融市场,包含订单簿动态、流动性、价格波动与市场状态等变量;
- State(状态):某时刻智能体可用的信息,通常包括订单簿状态(买卖价差、订单深度)、历史价格、历史成交量、市场波动率等;
- Action(动作):基于观察状态做出的决策,包括选择下单量、价格与执行时机;
- Reward(奖励):指示动作效果的标量信号,通常同时考虑最大化价格优势、最小化交易成本(手续费与滑点)、降低市场冲击、提高完成率等多个目标。
具体场景又分两种:
- 单资产订单执行(Single-asset order execution):针对某一特定资产(股票或加密货币)执行单笔订单,目标是在价格优势、成本、冲击与完成率之间取得最优;
- 多资产订单执行(Multi-asset order execution):同时对组合中多个资产执行订单,除了单笔订单效率,还要管理资产间相互作用与依赖,以及现金约束、市场条件与交易成本,目标是在单资产效率与组合整体目标之间取得平衡。
组合构建(Portfolio Construction)
组合构建是选取与配置资产的过程。RL 提供"与市场交互、在考虑风险管理的前提下最大化长期收益"的决策优化框架,一般设定为:
- State:市场与组合的当前信息,如历史价格与成交量、技术指标等;
- Action:向不同资产分配资本量的决策,即各资产的权重或比例;
- Reward:评估组合表现的指标,可以定义为总收益、风险调整后收益,或最大化夏普比率、最小化回撤等目标。
按市场可细分为股票市场、加密货币市场、外汇市场等。文档同时提醒:基础设定与算法的选择取决于具体任务需求、可用数据与期望的性能目标。
Part 3:跑通官方示例——单资产订单执行(SAOE)
指南中三类读者都要经过的一步:运行示例(part3,docs/component/rl/quickstart.rst),用 RL 解决一个真实交易问题。当前 QlibRL 实现了两个场景示例:订单执行与算法交易,其中单资产订单执行示例最完整,配套代码与配置位于 examples/rl_order_execution/。
数据准备
根据 examples/rl_order_execution/README.md,先下载 5 分钟级数据,再将其处理为 pickle 格式并生成训练订单:
python -m qlib.cli.data qlib_data --target_dir ./data/bin --region hs300 --interval 5min python scripts/gen_pickle_data.py -c scripts/pickle_data_config.yml python scripts/gen_training_orders.py python scripts/merge_orders.py完成后data/下应有bin、orders、pickle三个目录,分别对应训练配置中data_dir、order_dir、feature_root_dir引用的路径。
训练配置详解
下面是 quickstart 文档给出的训练配置文件(对应仓库中的 exp_configs/train_ppo.yml 等实际配置),每个键位直接映射到一个 MDP 组件:
simulator: # Each step contains 30mins time_per_step: 30 # Upper bound of volume, should be null or a float between 0 and 1, if it is a float, # represent upper bound is calculated by the percentage of the market volume vol_limit: null env: # Concurrent environment workers. concurrency: 1 # dummy or subproc or shmem. parallel_mode: dummy action_interpreter: class: CategoricalActionInterpreter kwargs: # Candidate actions: a list [a_1..a_L] or an integer n, in which case # [0, 1/n, 2/n, ..., n/n] is auto-generated. values: 14 # Total number of steps (an upper-bound estimation) max_step: 8 module_path: qlib.rl.order_execution.interpreter state_interpreter: class: FullHistoryStateInterpreter kwargs: data_dim: 6 # Number of dimensions in data. data_ticks: 240 # Equal to the total number of records (SAOE per minute: day length in minutes). max_step: 8 # 390min / 30min-per-step ≈ 13 steps(此处按订单窗口取 8 的上界估计) processed_data_provider: class: PickleProcessedDataProvider module_path: qlib.rl.data.pickle_styled kwargs: data_dir: ./data/pickle_dataframe/feature module_path: qlib.rl.order_execution.interpreter reward: class: PAPenaltyReward kwargs: penalty: 100.0 # The penalty for a large volume in a short time. module_path: qlib.rl.order_execution.reward data: source: order_dir: ./data/training_order_split data_dir: ./data/pickle_dataframe/backtest total_time: 240 # number of time indexes default_start_time: 0 # start time index default_end_time: 240 # end time index proc_data_dim: 6 num_workers: 0 queue_size: 20 network: class: Recurrent module_path: qlib.rl.order_execution.network policy: class: PPO kwargs: lr: 0.0001 module_path: qlib.rl.order_execution.policy runtime: seed: 42 use_cuda: false trainer: max_epoch: 2 repeat_per_collect: 5 # Number of episodes collected in each training iteration earlystop_patience: 2 episode_per_collect: 20 # Episodes per collect at training. batch_size: 16 val_every_n_epoch: 1 # Perform validation every n iterations checkpoint_path: ./checkpoints checkpoint_every_n_iters: 1配置中的几个关键取舍,可以从源码得到解释:
time_per_step: 30+data_ticks: 240:每步覆盖 30 分钟、一天共 240 个一分钟 tick,max_step是对总步数的上界估计(390 分钟交易时段 / 30 分钟每步);values: 14:动作离散化为 15 个候选比例[0, 1/14, ..., 1],由CategoricalActionInterpreter自动生成(见下节源码解析);class: PPO/class: DQN:QlibRL 当前基于 tianshou 支持 PPO 与 DQN 两类策略(指南原文如此),对应 qlib/rl/order_execution/policy.py 中的PPO与DQN封装类。
启动训练
python -m qlib.rl.contrib.train_onpolicy --config_path exp_configs/train_ppo.yml示例同时提供了两篇论文的复现任务:PPO(IJCAI 2020 "An End-to-End Optimal Trade Execution Framework based on Proximal Policy Optimization")与 OPDS(AAAI 2021 "Universal Trading for Order Execution with Oracle Policy Distillation"),二者的主要差别在于奖励函数,可分别查看 exp_configs/train_ppo.yml 与 exp_configs/train_opds.yml。训练指标、日志与 checkpoint 会输出到配置指定的outputs/目录。
回测配置与命令
训练完成后可用训练好的策略做回测,quickstart 给出的回测配置结构如下(真实配置见 exp_configs/backtest_ppo.yml):
order_file: ./data/backtest_orders.csv start_time: "9:45" end_time: "14:44" qlib: provider_uri_1min: ./data/bin feature_root_dir: ./data/pickle # feature generated by today's information feature_columns_today: ["$open", "$high", "$low", "$close", "$vwap", "$volume"] # feature generated by yesterday's information feature_columns_yesterday: ["$open_v1", "$high_v1", "$low_v1", "$close_v1", "$vwap_v1", "$volume_v1"] exchange: # the expression for buying and selling stock limitation limit_threshold: ['$close == 0', '$close == 0'] # deal price for buying and selling deal_price: ["If($close == 0, $vwap, $close)", "If($close == 0, $vwap, $close)"] volume_threshold: # volume limits are both buying and selling, "cum" means cumulative value over time all: ["cum", "0.2 * DayCumsum($volume, '9:45', '14:44')"] buy: ["current", "$close"] sell: ["current", "$close"] strategies: 30min: class: TWAPStrategy module_path: qlib.contrib.strategy.rule_strategy kwargs: {} 1day: class: SAOEIntStrategy module_path: qlib.rl.order_execution.strategy kwargs: state_interpreter: class: FullHistoryStateInterpreter module_path: qlib.rl.order_execution.interpreter kwargs: max_step: 8 data_ticks: 240 data_dim: 6 processed_data_provider: class: PickleProcessedDataProvider module_path: qlib.rl.data.pickle_styled kwargs: data_dir: ./data/pickle_dataframe/feature action_interpreter: class: CategoricalActionInterpreter module_path: qlib.rl.order_execution.interpreter kwargs: values: 14 max_step: 8 network: class: Recurrent module_path: qlib.rl.order_execution.network kwargs: {} policy: class: PPO module_path: qlib.rl.order_execution.policy kwargs: lr: 1.0e-4 # Local path to the latest model. The model is generated during training, # so please run training first if you want to run backtest with a trained # policy. You could also remove this parameter file to run backtest # with a randomly initialized policy. weight_file: ./checkpoints/latest.pth # Concurrent environment workers. concurrency: 5回测命令:
python -m qlib.rl.contrib.backtest --config_path exp_configs/backtest_ppo.yml一个值得注意的实现细节(来自 examples/rl_order_execution/README.md):训练与回测使用不同的模拟器。训练阶段为了效率使用简化版SingleAssetOrderExecutionSimple(不限制交易数量,订单总能完全成交),回测阶段则使用更贴近现实的SingleAssetOrderExecution(考虑成交量必须是最小交易单位整数倍等真实约束),因此回测结果与训练期测试阶段结果可能存在偏差。若想让回测与训练期测试完全一致,可用python -m qlib.rl.contrib.train_onpolicy --config_path PATH/TO/CONFIG --run_backtest --no_training仅运行回测段,并在配置的policy.kwargs中加上weight_file: PATH/TO/CHECKPOINT。
Part 4:理解 QlibRL 框架,并改写组件做定制
指南的最后一步(part4,docs/component/rl/framework.rst)面向想要做定制的用户:先理解框架,再按需重写具体组件。
框架总览:EnvWrapper 与四个可插拔组件
QlibRL 提供了覆盖 RL 全生命周期的组件集合:构建市场模拟器、构造状态与动作、训练策略、在模拟环境中回测。它在 Tianshou 与 Gym 之上实现,核心抽象是EnvWrapper——对模拟环境的完整封装:它接收外部(policy/strategy/agent)的动作、模拟市场变化、返回奖励与更新后的状态,形成交互闭环。EnvWrapper 是gym.Env的子类,实现其全部接口,因此任何接受gym.Env的类或流水线也能接受 EnvWrapper。
开发者不需要自己实现 EnvWrapper,只需实现它的4 个组成部分:
- Simulator(模拟器):环境模拟的核心组件,所有与环境模拟直接相关的逻辑都可放入其中。QlibRL 针对单资产交易提供了两个实现:
SingleAssetOrderExecution基于 Qlib 回测工具链,考虑了大量真实交易细节但较慢;SimpleSingleAssetOrderExecution基于简化交易模拟器,忽略细节(如交易限制、取整)但速度快。对应源码分别为 qlib/rl/order_execution/simulator_qlib.py 与 qlib/rl/order_execution/simulator_simple.py; - State interpreter(状态解释器):把模拟器原始格式的状态"翻译"成策略可理解的格式,例如把非结构化原始特征转换为数值张量;
- Action interpreter(动作解释器):方向相反,把策略输出的动作从策略格式转换为模拟器可接受的格式;
- Reward function(奖励函数):策略每执行一次动作后返回一个数值奖励。
EnvWrapper 会把这四部分"有机关联"起来。这种解耦带来的灵活性是:同一个环境(一个模拟器)可以搭配不同的状态解释器/动作解释器/奖励函数,训练多种类型的策略。所有组件都有定义良好的基类,定制方式就是继承基类并实现其要求的接口,基类 API 见 qlib/rl/interpreter.py(StateInterpreter、ActionInterpreter)与 qlib/rl/reward.py(Reward)。
指南点名的 MDP 模块逐一解析
指南针对"量化研究员设计 MDP"这一步,给出了订单执行示例中需要对照修改的 7 个模块及其源码位置。下面结合源码逐一说明它们在 MDP 建模中承担的角色:
1. State(状态)—— SAOEState
SAOEState是一个NamedTuple,是模拟器输出的原始状态结构,包含:当前订单order、当前时间cur_time、当前步数cur_step、剩余待执行量position、历史成交明细history_exec、历史各步统计history_steps、结算后才有的日度指标metrics、回测数据backtest_data,以及ticks_per_step、ticks_index、ticks_for_order等时间刻度信息。注意源码注释特别强调:解释器使用这些数据时要小心理解未来数据泄漏——FullHistoryStateInterpreter正是通过_mask_future_info把当前时刻之后的数据置零来保证这一点。
2. Metrics(指标)—— SAOEMetrics
SAOEMetrics定义了按"period"(一天、30 分钟窗口或逐分钟)累积的交易指标:市场侧的market_volume/market_price,策略侧的amount/inner_amount/deal_amount/trade_price/trade_value/position,以及累积指标ffr(订单完成度)与pa(相对于 TWAP 基线的价格优势,单位为 BP)。这里的pa就是训练日志中reward/pa的来源,也是示例中挑选 checkpoint 的评价指标。
3. ActionInterpreter(动作解释器)—— CategoricalActionInterpreter
把策略的离散动作转换为连续交易量:values若为整数n,则自动生成[0, 1/n, 2/n, ..., 1]共n+1个候选比例;解释时输出min(position, order.amount * action_values[action]),即"本步最多交易剩余仓位,且不超过订单量的候选比例"。若已到max_step的最后一步,则直接返回全部剩余仓位position,强制收尾。此外还有 TwapRelativeActionInterpreter,把连续动作解释为相对"剩余时段 TWAP 量"的倍数,适合想让策略学习"偏离 TWAP 多少"的场景。
4. StateInterpreter(状态解释器)—— FullHistoryStateInterpreter
把SAOEState翻译成策略可消费的观测字典,输出包含:截至当前的当日处理数据data_processed(未来信息被 mask)、昨日数据data_processed_prev、方向acquiring、当前 tick/step、总步数num_step、目标量target、剩余仓位position与仓位历史position_history。其observation_space属性声明了对应的 Gym 空间(如data_processed为(data_ticks, data_dim)的 Box),供 tianshou 策略自动构建网络。若策略只依赖最新状态,可改用更轻量的 CurrentStepStateInterpreter。
5. Reward(奖励)—— PAPenaltyReward
奖励公式为每步PA_t * vol_t / target - vol_t^2 * penalty:鼓励更高的价格优势,同时对"在极短时间内堆量"施加二次惩罚(penalty默认 100.0,还有scale系数整体缩放奖励)。同文件还提供 PPOReward——按 IJCAI 2020 PPO 论文设计,在订单完成或到达最后一步时,用实际 VWAP 与 TWAP 基线价格的比值给出 -1/0/+1 的离散奖励。这也解释了示例中 PPO 与 OPDS 两个训练任务"主要差别在奖励函数"的说法:OPDS 配置使用 OPDS 相关奖励,PPO 配置使用 PPOReward。
6. Observation(观测)—— FullHistoryObs
观测是状态解释器输出的最终数据契约(TypedDict),规定了策略输入必须包含的 8 个键。定制新状态解释器时,可以参照它定义自己的观测结构(键名、张量形状与observation_space保持一致即可),再配合 network.py 中的Recurrent(默认输出维度 32)或Attention等网络构建策略输入通路。
7. Simulator(模拟器)—— simulator_simple.py
前文已述,训练用SingleAssetOrderExecutionSimple(快、简化),回测用 simulator_qlib.py 的SingleAssetOrderExecution(慢、含真实交易细节)。定制新交易场景(如换市场、改撮合规则)时,模拟器是改动量最大、也最需要谨慎的组件。
策略(Policy)层的定制入口
指南对"RL 算法研究者"给出的建议是:跑通示例后,修改 policy 部分把自家 RL 算法接进来。从源码看,qlib/rl/order_execution/policy.py 中PPO是 tianshouPPOPolicy的封装(L102-L158):自动创建 actor/critic 网络(仅支持离散动作空间)、对 actor/critic 公共参数去重、支持weight_file加载 checkpoint,并暴露lr、discount_factor、eps_clip、gae_lambda、max_batch_size等常用超参默认值;DQN同样是DQNPolicy的封装(L164-L208),支持discount_factor、estimation_step、is_double等参数。此外还有不可学习的基线策略AllOne(输出恒定值,用于实现 TWAP 等规则基线,L46-L63)。要接入新算法(如 SAC、TD3 变体或自研算法),继承 tianshou 对应 policy 并按PPO/DQN的模式做封装、然后在配置里以class/module_path指向即可,无需触碰模拟器与解释器。
三类读者的推荐执行顺序(小结)
把指南原文的推荐序列落到可执行的清单上:
RL 算法新手:
- 在 overall 文档 学习 RL 基础(四要素、试错学习);
- 在 overall 文档 理解 RL 可应用的交易场景(订单执行、组合构建的 State/Action/Reward 一般设定);
- 按 quickstart 文档 与 examples/rl_order_execution/ 跑通示例;
- 想进一步定制时,先理解 framework 文档 的 EnvWrapper 四组件结构,再按需重写对应组件。
RL 算法研究者:
- 先理解交易场景(overall 文档 part2 章节);
- 选择一个场景(当前实现有订单执行与算法交易两个示例)跑通 quickstart 示例;
- 修改 policy.py 接入自己的 RL 算法。
量化研究员:
- 学习 RL 基础(part1)与交易场景(part2);
- 跑通 quickstart 示例;
- 理解 framework 文档的框架结构;
- 按问题特性选择算法(当前 QlibRL 基于 tianshou 支持PPO 与 DQN);
- 基于市场交易规则与待解问题设计 MDP,参照订单执行示例修改 7 个模块:
SAOEState(state.py#L70)、SAOEMetrics(state.py#L18)、CategoricalActionInterpreter(interpreter.py#L199)、FullHistoryStateInterpreter(interpreter.py#L68)、Reward(reward.py)、FullHistoryObs(interpreter.py#L44)、Simulator(simulator_simple.py)。
最后,文档还指出 QlibRL 模块以松耦合方式设计,核心 RL 部分比示例呈现的更简洁;如果不关心具体业务逻辑,可以配合 examples/rl/simple_example.ipynb 这个"无业务损失"的专用 notebook 来理解 RL 内核。文档同时预告未来会提供更多场景示例(如基于 RL 的组合构建)。适用前提提醒:以上示例与命令均以当前仓库中examples/rl_order_execution与qlib.rl模块的实际代码为准,且需要依赖 tianshou、gym 与 PyTorch 环境(可参考 examples/rl_order_execution/ 下的配置与 qlib/rl/contrib/ 的训练入口确认参数细节)。
【免费下载链接】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 R&D process.项目地址: https://gitcode.com/GitHub_Trending/qli/qlib
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考