QlibRL 实践指南:量化交易中的强化学习范式、订单执行场景与训练回测全流程
本文基于 Qlib 官方文档中的强化学习章节(RL 总体介绍),系统讲解强化学习(Reinforcement Learning, RL)在量化投资中的应用场景——订单执行(Order Execution)与组合构建(Portfolio Construction),并结合 Qlib 仓库中 qlib/rl 子系统的真实源码与示例工程,说明如何把 State/Action/Reward 抽象落到可运行的训练与回测配置上。读完后,你将能够理解 RL 在量化交易中的 MDP 建模方式,并掌握使用 QlibRL 训练订单执行策略、用学到的策略回测对比基准(如 TWAP)的完整方法。
一、强化学习范式:MDP 假设下的四个核心要素
与分类、回归等监督学习任务不同,强化学习是机器学习中另一个重要范式:智能体(agent)在马尔可夫决策过程(MDP)等少量假设下,通过与环境直接交互来优化累积数值奖励信号。一个 RL 系统由四个要素构成:
- Agent(智能体):感知并解释环境、采取行动、通过奖励学习,追求长期、最大化的总体奖励,从而得到最优解;
- Environment(环境):agent 交互的对象;
- Policy(策略):agent 依据其对环境采取行动;
- Reward(奖励信号):环境反馈给 agent 的标量信号。
RL 通过“试错”(trial and error)学习产生动作:采样动作、观察哪个动作导向期望结果,从而得到一个能产生最优动作的策略。与监督学习的关键区别在于,RL 学习的目标信号不是标签(label),而是延迟的、标量化的奖励(reward)——它告诉当前结果是好是坏。一句话概括:RL 的目标就是采取行动以最大化奖励。
Qlib 为此内置了强化学习工具包 QlibRL(qlib/rl 包),为在 Qlib 平台上实现各类 RL 算法提供支撑,其组件构成与 API 详见 QlibRL 框架文档 与 快速上手文档。
二、订单执行(Order Execution):RL 建模四要素
RL 方法已在游戏、资源分配、推荐系统、营销与广告等众多领域展现出显著成效。投资是一个典型的连续决策过程:投资者通过管理仓位与持仓、执行各类买卖行为来优化投资收益,并且每次买卖决策前都会仔细评估市场状况与个股信息。从投资者视角看,这可以看作一个由与市场交互驱动的连续决策过程——RL 正是应对此类挑战的有前景方法。
2.1 通用建模:Environment / State / Action / Reward
官方文档将订单执行任务定义为:在兼顾最优价格、最小化交易成本、降低市场冲击、最大化订单成交率、并在指定时间窗口内完成执行等多个目标的前提下高效执行订单。RL 的做法是把上述目标编码进奖励函数与动作选择过程:RL agent 与市场环境交互,从市场信息中观察状态,决策下一步执行量,并通过试错学习最优执行策略,最大化期望累积奖励。具体建模如下:
- Environment(环境):订单执行所发生的金融市场,涵盖订单簿动态、流动性、价格波动与市场状况等变量;
- State(状态):某一时间步上 RL agent 可获得的信息,通常包括当前订单簿状态(买卖价差、订单深度)、历史价格、历史成交量、市场波动率及其他辅助决策的信息;
- Action(动作):agent 基于观察状态做出的决策。在订单执行中,动作可以包括选择订单量(order size)、价格与执行时机;
- Reward(奖励):标量信号,用于评价 agent 动作在环境中的表现。奖励函数被设计为鼓励高效、低成本执行的动作,通常综合考虑最大化价格优势、最小化交易成本(含手续费与滑点)、降低市场冲击(订单对市场价格的影响)以及最大化成交率等多目标。
2.2 Qlib 源码中的落地:SAOE 任务的组件实现
Qlib 仓库将上述四要素抽象为可组合的基类,开发者继承基类实现接口即可。以单资产订单执行(Single-Asset Order Execution, SAOE)任务为例,各要素对应的真实实现:
- Simulator(环境模拟核心):提供两套实现——SingleAssetOrderExecution 基于 Qlib 的回测工具包构建,考虑了较多真实交易细节但速度较慢;SingleAssetOrderExecutionSimple 基于简化交易模拟器,忽略交易限制、取整等细节但速度很快。简单模拟器的机制在源码注释中写得很清楚:每一步的交易量被“均分”到每个 tick,再受最大可成交量阈值(
vol_threshold,相对市场成交量的比例)约束,若为最后一步则尽量确保全部成交; - State Interpreter(状态解释器):把模拟器输出的原始状态转换为策略可理解的数值张量。FullHistoryStateInterpreter 会输出包含当日(截至当前)与昨日数据的观测字典,字段包括
data_processed、data_processed_prev、acquiring、cur_tick、cur_step、num_step、target、position、position_history等,并对未来信息做掩码以避免前视偏差; - Action Interpreter(动作解释器):把策略输出的动作格式转换为模拟器可接受的格式。
CategoricalActionInterpreter的动作空间由values参数决定:传入values: 14时自动生成离散动作列表[0, 1/14, 2/14, ..., 14/14],即“本步执行剩余订单量的比例”; - Reward(奖励函数):基类定义在 Reward,子类只需实现
reward(simulator_state) -> float;RewardCombination还支持多个奖励函数按权重组合。
其中最典型的奖励实现是 PAPenaltyReward(PA = Price Advantage,价格优势)。其每步奖励形式为:
reward = PA_t * vol_t / target − vol_t^2 * penalty
即鼓励更高的价格优势,同时惩罚在极短时间内堆叠大量成交量——这正是文档中“最大化价格优势、降低市场冲击、最大化成交率”多目标权衡的代码化表达。源码中 penalty 默认值为 100.0,另有 scale 参数用于整体缩放奖励幅度;函数内部还会通过 self.log 把 reward/pa 与 reward/penalty 分项记入日志,便于训练中观察两个目标的分解表现。此外源码中还提供 PPOReward,对应文献“基于 PPO 的端到端最优交易执行框架”的奖励设计,用于与 TWAP 基准做三档(-1/0/1)评价。
2.3 场景划分:单资产与多资产订单执行
文档进一步把订单执行划分为两类场景:
- 单资产订单执行:针对某一特定资产(股票或加密货币)执行单笔订单,目标是在最大化价格优势、最小化交易成本、降低市场冲击与高成交率之间取得平衡。RL agent 与该资产的市场环境交互,对订单量、价格、执行时机做决策,学习针对该资产特定动态的最优执行策略;
- 多资产订单执行:把任务扩展到同时或顺序执行多个资产的一组订单。与单资产场景不同,关注点不仅在于单笔订单的执行效率,还在于组合内不同资产之间的交互与依赖关系——RL agent 需为每个资产决定订单量、价格与时机,同时考虑资产间依赖、现金约束、市场状况与交易成本,目标是学习一个在单资产执行效率与组合整体目标之间取得平衡的策略。
当前仓库中,examples/rl_order_execution 示例工程(含 README 与训练/回测配置 exp_configs)即为单资产订单执行场景的完整实现;多资产场景可作为在此组件体系上的扩展方向。文档同时指出:具体设定与 RL 算法的选择取决于任务要求、可用数据与期望的性能目标。
三、组合构建(Portfolio Construction):State / Action / Reward
组合构建是从投资组合中选择并配置资产的过程。RL 为此提供了一个优化组合管理决策的框架:通过与市场环境交互学习,在考虑风险管理的前提下最大化长期收益。文档给出的通用建模为:
- State(状态):表示市场与组合的当前信息,通常包括历史价格与成交量、技术指标及其他相关数据;
- Action(动作):对应向组合中不同资产分配资本的决策,决定各资产的投资权重或比例;
- Reward(奖励):评价组合表现的度量指标,可定义为总收益、风险调整后收益,或最大化夏普比率、最小化回撤等其他目标。
文档列举了三个可直接套用该框架的场景:
- 股票市场:agent 学习在不同股票间分配资本;
- 加密货币市场:agent 学习做出配置决策;
- 外汇(Forex)市场:agent 基于汇率数据、经济指标及其他因素在不同货币对间分配资本。
需要说明适用前提:就当前仓库而言,RL 组合构建尚属于文档中声明的未来方向(快速上手文档明确写道“未来将提供更多示例,例如基于 RL 的组合构建”),qlib/rl 与示例工程目前围绕订单执行任务落地;而 Qlib 的组合层面优化能力(如 portfolio 示例 与增强指数策略 optimizer) 主要走监督学习 + 组合优化路线。因此组合构建的 RL 化应理解为该范式提供的建模框架与演进方向,而非当前版本已内置的示例。与订单执行场景一样,基础设定与算法的选择取决于问题的具体需求与市场的特征。
四、QlibRL 组件体系:把范式变成可运行管线
官方框架文档(framework.rst)说明:QlibRL 覆盖 RL 管线的完整生命周期——构建市场模拟器、塑造状态与动作、训练策略、以及在模拟环境中回测策略。其实现基本依托 Tianshou 与 Gym 框架。对开发者而言,关键在于 EnvWrapper:它是模拟环境的完整封装,接收外部(policy/strategy/agent)的动作、模拟市场变化、并返回奖励与更新后的状态,形成交互闭环。
从 EnvWrapper 源码 可以看到,它是 gym.Env 的子类,实现 gym.Env 的全部接口,因此任何接受 gym.Env 的类或管线都可以直接接受它。开发者无需自己实现 EnvWrapper,只需实现其内部 4 个组件:Simulator、State Interpreter、Action Interpreter、Reward Function,EnvWrapper 会将它们有机地组装起来。这种解耦带来明显的开发灵活性:例如想在同一环境中训练多种策略,只需设计一个模拟器,再为不同策略分别设计状态解释器/动作解释器/奖励函数即可。
策略层直接复用 Tianshou 的 policy:可以开箱使用 Tianshou 内置策略,也可以通过继承实现自定义策略。qlib/rl/order_execution/policy.py 提供了三类现成实现:PPO(示例默认策略,Actor-Critic 结构)、DQN,以及用于基线对照的 AllOne 策略——它总是输出固定值,专门用来实现 TWAP 这类无需学习的执行基线。
训练层由 Training Vessel 与 Trainer 两个辅助类构成:Training Vessel 是“承载”模拟器/解释器/奖励函数/策略的容器,控制训练中与算法相关的部分;Trainer 则负责训练的运行时控制,通过 Scikit-learn 风格的 trainer.fit() 接口启动训练管线。值得注意的是,Training Vessel 持有的是构建 EnvWrapper 所需的全部组件而非 EnvWrapper 实例本身——这使得它可以在需要时(例如并行训练)动态创建 EnvWrapper 的副本。
五、实战:从配置到训练与回测
快速上手文档给出了单资产订单执行任务的完整可运行示例。下面以仓库 examples/rl_order_execution/exp_configs 中的配置为蓝本,拆解训练与回测两个阶段的关键参数。
5.1 训练配置(train_ppo.yml)
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. Corresponding to parallelism in tianshou
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:
# Number of dimensions in data.
data_dim: 6
# Equal to the total number of records. For example, in SAOE per minute,
# data_ticks is the length of the day in minutes.
data_ticks: 240
# The total number of steps (an upper-bound estimation). e.g. 390min / 30min-per-step = 13 steps
max_step: 8
# Provider of the processed data.
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:
# The penalty for a large volume in a short time.
penalty: 100.0
module_path: qlib.rl.order_execution.reward
data:
source:
order_dir: ./data/training_order_split
data_dir: ./data/pickle_dataframe/backtest
# number of time indexes
total_time: 240
default_start_time: 0
default_end_time: 240
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
# Number of episodes collected in each training iteration
repeat_per_collect: 5
earlystop_patience: 2
# Episodes per collect at training.
episode_per_collect: 20
batch_size: 16
# Perform validation every n iterations
val_every_n_epoch: 1
checkpoint_path: ./checkpoints
checkpoint_every_n_iters: 1
参数解读(结合源码语义):
time_per_step: 30:每个决策步对应 30 分钟,一天约 8 步(390min 交易时段 / 30min);max_step是步数的上界估计,需与之一致;data_ticks: 240:分钟级数据下等于一天的分钟数,与data段的total_time: 240对应;data_dim: 6为特征维度(开高低收、VWAP、成交量);CategoricalActionInterpreter.values: 14:动作空间为 15 个离散档位(0 到 14/14),即“本步执行剩余量的 0/14 ~ 14/14”;PAPenaltyReward.penalty: 100.0:短时大量成交的惩罚系数,与 源码实现 中的默认值一致;env.concurrency/env.parallel_mode:控制并行环境 worker 数量与并行方式(dummy/subproc/shmem,对应 Tianshou 的向量化环境);trainer段控制训练运行时:max_epoch、episode_per_collect(每次收集 20 条 episode)、batch_size: 16、验证与检查点频率等;checkpoint_path指向训练产出的策略权重目录,供回测阶段加载。
5.2 回测配置(backtest_ppo.yml)要点
回测配置(对应 examples/rl_order_execution/exp_configs/backtest_ppo.yml)定义订单文件、交易时段、Qlib 数据源与交易所规则,并在 strategies 中同时挂载两条策略做对比:
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:
# "cum" means a 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
policy:
class: PPO
module_path: qlib.rl.order_execution.policy
kwargs:
lr: 1.0e-4
# Local path to the latest model. Run training first;
# or remove this file to backtest with a randomly initialized policy.
weight_file: ./checkpoints/latest.pth
# Concurrent environment workers.
concurrency: 5
回测侧的关键点:
- 两条策略分别对应不同的执行周期:
TWAPStrategy(30min 时段的规则基线,来自 qlib/contrib/strategy/rule_strategy.py)与SAOEIntStrategy(1day 时段、由神经网络决策,来自 qlib/rl/order_execution/strategy.py)——前者正是文档所述“将多目标纳入奖励函数”后的对照基线; SAOEIntStrategy必须复用与训练完全一致的状态/动作解释器参数(max_step: 8、data_ticks: 240、values: 14等)与网络结构,weight_file指向训练产出的./checkpoints/latest.pth;若删除该参数,则退化为随机初始策略的回测;volume_threshold中的cum/current分别表示按时间累积的成交量约束与实时值约束,0.2 * DayCumsum(...)即“单笔累计成交量不超过当日均量累计的 20%”这类真实市场约束——对应simulator.vol_limit在训练侧的约束语义;exchange.deal_price用表达式If($close == 0, $vwap, $close)处理收盘后无成交价的分钟条,回测成交价的取值规则由此显式化。
5.3 数据准备与运行命令
训练/回测前需要先准备两份数据:分钟级回测数据的 pickle 缓存(由 gen_pickle_data.py 配合 pickle_data_config.yml 生成)与训练订单文件(由 gen_training_orders.py 生成,可进一步用 merge_orders.py 合并多日订单)。准备好后,两条命令即可启动全流程:
$ python -m qlib.rl.contrib.train_onpolicy.py --config_path train_ppo.yml
训练完成后,加载权重进行回测:
$ python -m qlib.rl.contrib.backtest.py --config_path backtest_ppo.yml
对单资产订单执行任务,如果开发者已自定义了 simulator / interpreters / reward function / policy,只需修改配置文件中的相应设置即可启动训练与回测管线——这正是 QlibRL“低耦合、组件化”设计的直接收益。更完整的示例说明见 examples/rl_order_execution/README.md。
六、小结
- 本文主体源自 docs/component/rl/overall.rst:RL 以 MDP 为假设、以最大化累积奖励为目标,其四要素(agent、environment、policy、reward)天然契合量化投资中“与市场交互驱动的连续决策”特性;
- 订单执行与组合构建是文档给出的两大潜在应用场景。前者按 Environment/State/Action/Reward 四要素建模,区分单资产与多资产场景;后者以 State/Action/Reward 三要素建模,覆盖股票、加密货币与外汇市场,其中组合构建在仓库中尚属规划方向;
- 仓库中
qlib/rl子系统的 EnvWrapper(gym.Env 子类)、两套 SAOE 模拟器、FullHistoryStateInterpreter/CategoricalActionInterpreter、PAPenaltyReward奖励、PPO/AllOne策略与Trainer.fit()训练接口,构成了从文档范式到可复制配置与命令的完整证据链; - 设定与算法的选择始终取决于任务要求、可用数据与性能目标——建议读者从单资产订单执行的示例配置出发,先跑通训练—回测闭环,再按需替换组件扩展到自己的场景。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00

