2. Qlib基础回顾

在进入滚动训练与模型更新的实战之前,有必要把 Qlib 的整体骨架重新梳理一遍。滚动训练并不是一个孤立功能,它建立在 Qlib 的数据组织方式、工作流抽象和配置驱动机制之上。只有理解了这些基础,后续才能准确判断“哪些环节需要滚动、哪些状态需要继承、哪些参数需要随窗口变化”。本节从架构、数据层、工作流、配置文件和常用模块五个角度回顾,并给出一个可直接运行的快速上手示例。

一、核心原理:Qlib 的分层架构

Qlib 的设计哲学是“数据与流程解耦、配置驱动执行”。从下到上大致可分为四层:

  • 数据层(Data Layer):负责原始行情数据的采集、清洗、存储与表达式计算,核心是 DataHandler 与表达式引擎。
  • 工作流层(Workflow Layer):以 qrun 和 Workflow 为核心,把数据、模型、训练、回测串成可复现的流水线。
  • 模型层(Model Layer):提供 Model 基类及 LightGBM、LSTM、Transformer 等实现,统一 fit/predict 接口。
  • 策略与回测层(Strategy & Backtest):包含 Strategy、Executor、Backtest,负责信号到持仓的转换与绩效评估。

这种分层带来的直接好处是:滚动训练时,我们只需替换数据切分逻辑和模型更新策略,而无需重写回测与评估代码。

二、数据层:Qlib 的“数据即表达式”

Qlib 数据层最鲜明的特点是表达式驱动。用户不需要预先计算所有因子,而是用类似 Ref($close, 1)/$close - 1 的表达式描述特征,由引擎在读取时计算。核心组件包括:

  • Calendar:交易日历,决定时间轴。
  • Instrument:股票池,如 csi300、csi500。
  • Feature:原始字段与表达式特征。
  • DataHandler:把上述内容组装成模型可用的 DataFrame,并处理缺失值、标准化。
表达式引擎是 Qlib 高效的关键:它支持缓存与增量计算,滚动训练时若窗口重叠,可显著减少重复计算开销。

三、工作流与配置文件:qrun 的驱动方式

Qlib 推荐用 YAML 配置文件描述整个实验,再用 qrun 执行。一个典型配置包含 qlib_init、market、benchmark、data_handler_config、task 等段落。下面是一个最小可运行示例:

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: 2018-01-01
    end_time: 2020-08-01
    fit_start_time: 2018-01-01
    fit_end_time: 2019-12-31
    instruments: *market
task:
    model:
        class: LGBModel
        module_path: qlib.contrib.model.gbdt
        kwargs:
            loss: mse
            learning_rate: 0.05
    dataset:
        class: DatasetH
        module_path: qlib.data.dataset
        kwargs:
            handler:
                class: Alpha158
                module_path: qlib.contrib.data.handler
                kwargs: *data_handler_config
            segments:
                train: [2018-01-01, 2019-12-31]
                valid: [2020-01-01, 2020-06-30]
                test: [2020-07-01, 2020-08-01]
    record:
        - class: SignalRecord
          module_path: qlib.workflow.record_temp

执行命令非常简洁:

qrun workflow_config_lightgbm.yaml

运行后 Qlib 会在 mlruns 目录下生成实验记录,包含模型、预测信号和回测结果。理解这份配置的结构,是后续改造为滚动训练配置的前提。

四、常用模块速查

模块典型类/函数作用
数据Alpha158 / Alpha360内置因子集,快速构建特征
数据集DatasetH按时间段切分 train/valid/test
模型LGBModel / LSTM统一 fit/predict 接口
工作流qrun / Workflow配置驱动执行与记录
回测TopkDropoutStrategy按预测分数选股并调仓
记录SignalRecord / PortAnaRecord保存信号与绩效分析

五、快速上手示例与常见误区

若不想用 YAML,也可以用 Python API 快速跑通:

import qlib
from qlib.contrib.data.handler import Alpha158
from qlib.contrib.model.gbdt import LGBModel
from qlib.data.dataset import DatasetH

qlib.init(provider_uri="~/.qlib/qlib_data/cn_data", region="cn")
handler = Alpha158(instruments="csi300",
                   start_time="2018-01-01", end_time="2020-08-01",
                   fit_start_time="2018-01-01", fit_end_time="2019-12-31")
dataset = DatasetH(handler, segments={
    "train": ("2018-01-01", "2019-12-31"),
    "valid": ("2020-01-01", "2020-06-30"),
    "test":  ("2020-07-01", "2020-08-01"),
})
model = LGBModel(loss="mse", learning_rate=0.05)
model.fit(dataset)
pred = model.predict(dataset)
print(pred.head())
常见误区一:把 fit_start_time 与 train 段混为一谈。前者用于特征标准化统计,后者用于模型训练,二者时间范围可以不同,滚动训练时必须分别管理。误区二:忽略 qlib.init 的 provider_uri,导致数据路径错误却报出难以定位的异常。误区三:直接修改 test 段做“滚动”,实际上破坏了样本外评估的严谨性。

复盘来看,Qlib 的基础可以浓缩为一句话:用表达式描述数据,用配置描述流程,用记录保证可复现。滚动训练要做的,正是在这套稳定骨架上,把“一次性切分”替换为“按时间窗口反复切分与更新”。理解了本节内容,后续改造配置、继承模型状态、管理多窗口实验时,就能做到心中有数、改动有据。