3. Qlib核心架构解析

Qlib核心架构解析 学习卡片

Qlib 的工程价值不在于某个单点模型,而在于它把量化研究从“数据清洗—特征工程—模型训练—信号生成—组合构建—回测评估”串成了一条可复现、可扩展、可并行的流水线。理解这条流水线的分层结构,是后续做深度学习预测与策略迭代的前提。Qlib 的核心架构可以概括为五层:数据层、模型层、策略层、回测层与工作流引擎。它们之间通过统一的接口与配置驱动协作,而不是靠硬编码耦合。

一、核心原理:五层职责与协作关系

数据层负责把原始行情、财务、文本等异构数据整理成统一的时间序列格式,并提供表达式引擎与数据集划分能力。模型层只关心“给定特征,输出预测分数”,不关心数据从哪来、策略怎么用。策略层把预测分数转化为可执行的投资组合或交易信号,例如 TopK 选股、权重分配、风险约束。回测层模拟真实交易环境,计算收益、回撤、换手率等指标,并处理涨跌停、停牌、手续费等细节。工作流引擎则负责编排整个流程,支持记录实验、并行执行与结果复现。

五层之间的数据流是单向且清晰的:数据层输出 Dataset,模型层消费后输出 prediction score,策略层消费分数后输出 order/position,回测层消费订单后输出 portfolio metrics,工作流引擎贯穿始终并记录每一步的配置与产物。这种设计让研究者可以只替换其中一层,而不影响其他层。

关键设计思想:Qlib 用“配置即实验”的方式管理流程。一个 workflow 配置文件中同时声明数据、模型、策略与回测参数,执行后自动生成带时间戳的实验目录,保证结果可追溯。

二、方法流程:从配置到回测的完整链路

下面以一个典型的深度学习预测任务为例,展示五层如何协作。假设我们要用 LSTM 预测未来 5 日收益率,并做 TopK 选股回测。

# workflow_config.yaml 核心片段
qlib_init:
    provider_uri: "~/.qlib/qlib_data/cn_data"
    region: cn

market: &market csi300
benchmark: &benchmark SH000300

data_handler_config: &data_handler_config
    start_time: 2015-01-01
    end_time: 2021-12-31
    fit_start_time: 2015-01-01
    fit_end_time: 2019-12-31
    instruments: *market
    infer_processors:
        - class: RobustZScoreNorm
          kwargs: {fields_group: feature}
        - class: Fillna
          kwargs: {fields_group: feature}
    learn_processors:
        - class: DropnaLabel
        - class: CSRankNorm
          kwargs: {fields_group: label}
    label: ["Ref($close, -5) / Ref($close, -1) - 1"]

model:
    class: LSTM
    module_path: qlib.contrib.model.pytorch_lstm
    kwargs:
        d_feat: 20
        hidden_size: 64
        num_layers: 2
        dropout: 0.1
        n_epochs: 50
        lr: 0.001
        batch_size: 1024

strategy:
    class: TopkDropoutStrategy
    kwargs:
        topk: 50
        n_drop: 5
        signal: &signal "&model"

backtest:
    start_time: 2020-01-01
    end_time: 2021-12-31
    account: 10000000
    benchmark: *benchmark
    exchange_kwargs:
        limit_threshold: 0.095
        deal_price: close
        open_cost: 0.0005
        close_cost: 0.0015
        min_cost: 5

执行时,工作流引擎按顺序完成:数据层加载并预处理数据,模型层训练 LSTM 并输出预测分数,策略层根据分数生成每日持仓,回测层模拟交易并计算指标。整个过程可以通过一条命令启动:

qrun workflow_config.yaml

运行结束后,实验目录下会生成 prediction.pkl、portfolio_analysis、mlflow 等产物,便于复盘与对比。

三、案例/场景:各层扩展方式与典型用法

Qlib 的扩展性体现在每一层都可以被替换或增强。下表总结了常见扩展点与对应做法。

层级扩展目标典型做法关键接口/类
数据层接入新数据源或自定义特征编写表达式或自定义 ProcessorDataHandler、Processor
模型层替换为自定义深度学习模型继承 Model 并实现 fit/predictqlib.model.base.Model
策略层实现新的组合构建逻辑继承 BaseStrategy 并重写 generate_trade_decisionqlib.strategy.base.BaseStrategy
回测层调整交易成本或撮合规则配置 exchange_kwargs 或自定义 ExchangeExchange、Executor
工作流引擎批量实验或超参搜索使用 qrun 配合多配置文件或 MLflowqrun、MLflow

例如,若想用自定义的 Transformer 模型替换 LSTM,只需在模型层实现 fit 与 predict 方法,并在配置中修改 module_path 与 class,数据层、策略层与回测层完全无需改动。这正是分层架构带来的解耦收益。

实践建议:初次接触 Qlib 时,建议先用内置模型与策略跑通完整流程,再逐层替换。每次只改一层,便于定位问题。实验配置建议纳入 Git 管理,配合 MLflow 记录参数与指标。

四、误区/复盘:常见问题与排查思路

在实际使用中,初学者容易陷入几个典型误区。第一,混淆数据层与模型层的职责,把特征工程写进模型代码,导致数据泄漏或复现困难。正确做法是把所有与特征相关的处理放在 DataHandler 与 Processor 中,模型只接收标准化后的特征矩阵。第二,忽略回测层的交易约束,直接用预测分数计算收益,导致回测结果虚高。Qlib 的 Exchange 已经内置涨跌停、停牌、手续费等处理,务必在配置中显式声明。

第三,策略层与回测层的信号对齐问题。策略层输出的交易决策必须与回测层的时间索引严格对齐,否则会出现“未来函数”或信号滞后。建议在策略层使用 signal 字段时,明确指定预测分数的日期偏移。第四,工作流引擎的并行与复现问题。Qlib 支持多进程与 MLflow 记录,但若配置文件中的路径使用相对路径,在不同机器上可能无法复现。建议使用绝对路径或环境变量。

常见报错:若出现 ValueError: The data of the instrument is not enough,通常是数据层的时间范围与模型训练范围不匹配,或 instruments 配置的股票池在指定区间内数据缺失。检查 start_time、end_time 与 fit_start_time、fit_end_time 是否合理。

复盘时,建议按“数据—模型—策略—回测”的顺序逐层检查:先确认数据层输出的特征与标签无缺失、无泄漏;再确认模型层训练损失收敛且预测分数分布合理;然后确认策略层持仓数量与换手率符合预期;最后确认回测层的成本参数与基准一致。只有每一层都正确,整体流程才能产出可信的量化预测结果。