工具实战
本讲建立 Qlib 的第一张分层地图,系统解释数据层、模型层、策略层各自负责什么,以及研究、训练、回测和实验记录在框架中的连接关系。重点拆清 Qlib 不是单一模型库、也不是直接实盘系统,而是一套把量化研究流程配置化、可复现化的研究操作系统,为后续数据规范、Alpha 建模与回测组合构建打基础。
Qlib 的真正价值,不是“又一个量化平台”,而是把研究、训练、回测、组合构建和执行衔接这五段原本散落在不同脚本里的流程,压成一条可复现、可配置、可审计的研究流水线。本讲作为第 1 讲,不急着写模型,也不急着跑回测,先解决一个更基础的问题:Qlib 到底把量化研究拆成了哪些层,每一层负责什么,又该在哪里接入自己的代码。
如果这个问题没有讲清楚,后面很容易出现三类常见失误:
因此,本讲的交付目标只有一个:建立一张清楚的 Qlib 分层地图,让你知道后面每一讲新增的内容,分别应该放在数据层、模型层还是策略层。
Qlib 可以理解为一套围绕 research -> train -> backtest -> analysis 设计的研究操作系统。它最核心的抽象只有三层。
数据层负责回答四个问题:
在 Qlib 里,数据层并不是一张 DataFrame,而是一组可被统一读取的表达式和数据处理器。最常见的入口是 DatasetH 和 DataHandlerLP。前者更像“研究视角的数据集包装器”,后者负责把原始市场数据映射成因子列、标签列和过滤规则。
这意味着你在 Qlib 中不应该先手工导出一份 CSV,再临时写 df['label'] = ...。更稳的做法是把特征和标签规则写成可配置表达式,例如:
handler_config = {
"start_time": "2018-01-01",
"end_time": "2024-12-31",
"fit_start_time": "2018-01-01",
"fit_end_time": "2021-12-31",
"instruments": "csi300",
"infer_processors": [
{"class": "RobustZScoreNorm", "kwargs": {"fields_group": "feature"}},
{"class": "Fillna", "kwargs": {"fields_group": "feature"}},
],
"learn_processors": [
{"class": "DropnaLabel"},
{"class": "CSRankNorm", "kwargs": {"fields_group": "label"}},
],
"data_loader": {
"class": "QlibDataLoader",
"kwargs": {
"config": {
"feature": ["Ref($close, -1) / $close - 1", "Mean($volume, 5)"],
"label": ["Ref($close, -5) / Ref($close, -1) - 1"],
}
},
},
}
这段配置的价值,不是语法本身,而是它把“字段定义”和“实验时间边界”从脚本里抽离了出来,后续替换市场、替换因子、替换标签都可以只动配置,不动主流程。
模型层负责读取数据层产出的样本,并输出一个与研究目标对应的预测结果。Qlib 自带 LightGBM、线性模型等研究模板,也允许你接入自定义模型。关键不在于“能不能训”,而在于模型层只负责拟合与预测,不应该顺手改标签口径或临时清洗数据。
一个健康的分层边界应该是这样的:
feature 与 label。train/valid/test 切分后的样本。如果你在模型训练时还在手动 fillna、手动对齐交易日、手动筛停牌股票,那说明分层已经塌了。后果通常是:研究脚本里能跑通,迁移到定时任务时全线报错。
策略层负责回答“预测结果如何变成交易动作”。这一层至少包括三步:
Qlib 在这一层的设计很务实。它不强迫你一定使用复杂组合优化,也不假设你已经有成熟执行系统。你完全可以从最简单的 TopK Dropout 组合开始:
strategy_config = {
"class": "TopkDropoutStrategy",
"kwargs": {
"signal": "<PRED.pkl>",
"topk": 30,
"n_drop": 5,
},
}
这类配置的意义在于,模型输出和交易规则被明确分开。你可以在保持模型不动的前提下,单独替换调仓频率、持仓上限和成本模型,观察研究结果到底是“模型有效”还是“策略映射有效”。
把三层连起来看,一条标准 Qlib 链路大致是:
最小可运行骨架如下:
import qlib
from qlib.config import REG_CN
from qlib.utils import init_instance_by_config
qlib.init(provider_uri="~/.qlib/qlib_data/cn_data", region=REG_CN)
dataset = init_instance_by_config(dataset_config)
model = init_instance_by_config(model_config)
model.fit(dataset)
pred = model.predict(dataset)
真正值得记住的不是这 4 行,而是它背后的分工:provider_uri 属于数据环境初始化;dataset_config 属于数据层;model_config 属于模型层;后续的 strategy/backtest 再进入策略层。如果后续你要重构研究脚本,这个分层顺序就是最小稳定骨架。
Qlib 的安装难点不在 Python 语法,而在环境一致性。第一次上手时,建议只检查下面四项:
Qlib 对 pandas / numpy / lightgbm / pyarrow 的组合较敏感。建议至少确认:
python --version
pip show pyqlib
pip show pandas
pip show numpy
如果你后面计划训练树模型或做高频特征扩展,尽量把研究环境固定在单独虚拟环境中,不要和日常开发环境混用。
Qlib 本地研究离不开 provider 目录。即使暂时不下载完整市场数据,也要先确定 provider_uri 指向的路径真实存在,且程序对该目录有读权限。
REG_CN、REG_US 这类参数不仅是一个标签,它决定了交易日历、市场假设和字段语义。如果你的研究对象是 A 股,却在配置里混入了美股口径,后面很多问题不会立刻报错,而是静默产生错位结果。
第 1 讲不要追求下载数据、训练模型、回测一条龙。先保证这段代码能稳定通过:
import qlib
from qlib.config import REG_CN
qlib.init(provider_uri="~/.qlib/qlib_data/cn_data", region=REG_CN)
print("Qlib initialized")
只要这一步不稳定,后面所有问题都会被环境噪声淹没。
很多人第一次接触 Qlib,会把它误认为“带因子功能的 LightGBM 封装”。这会导致后续用法非常别扭。Qlib 的核心不是某个具体模型,而是研究流程的组织能力。
它可以帮助你把研究结果结构化、配置化、可追溯化,但它并不直接替代实盘 OMS、风控总线或订单路由。你应该把它理解为“投研中台式框架”,而不是券商级执行平台。
真正让项目失控的,通常不是不会调用接口,而是标签定义、复权口径、停牌处理、行业映射这些基础口径没有统一。Qlib 恰好就是通过数据层抽象来解决这件事。
如果你今天用一个配置训出好结果,明天却无法复现,不是模型不稳定,而是研究流程失控。Qlib 的实验记录能力,本质上是在强制你把“输入、配置、结果”绑定起来。
先排查当前终端是否激活到正确环境,再确认安装包名是 pyqlib 而不是 qlib。很多人装错包名后,会误以为框架本身不可用。
这是最常见的初始化错误。不要急着改代码,先确认目录是否真实存在、路径分隔符是否正确、运行进程是否有权限读取。
这通常不是模型问题,而是数据层表达式引用了当前 provider 中不存在的字段。应先回头检查 Handler 的 feature/label 配置,而不是直接调模型参数。
优先检查三件事:
Qlib 可以帮你组织流程,但不会自动替你发现所有研究口径错误。
如果你准备把 Qlib 纳入日常研究栈,建议按下面顺序推进,而不是一口气全学:
DataHandlerLP、DatasetH 和时间切分配置。fit -> predict。这样推进的好处是,每一层都能单独验收。只要某一层出错,问题不会扩散到整条链路。
Qlib 的学习门槛,不在于 API 多,而在于它要求你把量化研究拆成真正可管理的层次。数据层决定口径,模型层决定预测,策略层决定把预测怎样变成组合。只要这三层边界清楚,后续你接任何模型、任何市场、任何回测规则,都能在同一张框架图上落位。
本讲是《Qlib研究到交易完整学习计划》的第 1/11 讲,当前主题是《Qlib架构入门:数据层、模型层与策略层协同机制》。
这是本系列的开篇,重点是把后续实操会反复使用的核心概念、输入输出和判断标准先立住。
下一讲:第 2 讲《Qlib数据规范与特征管线:从原始行情到可训练样本》。
后续安排:第 3 讲《Qlib Alpha建模实践:标签构造、样本切分与模型训练》;第 4 讲《Qlib回测模块与组合构建:信号排序、调仓与成本建模》。
风险揭示与免责声明
本页面内容仅用于量化研究与技术交流,旨在展示研究方法与流程,不构成对任何金融产品、证券或衍生品的要约、招揽、推荐或保证。
本文所涉历史数据、回测结果与示例参数不代表未来表现,也不应作为投资决策依据。
市场存在波动、流动性与执行偏差等不确定性,任何策略均可能出现收益波动或阶段性失效。
读者应结合自身风险承受能力进行独立判断,并在必要时咨询持牌专业机构意见。