简介:这份PDF文档是华泰证券金工研究团队出品的深度研究报告《微软AI量化投资平台Qlib体验》,面向量化投资研究者、金融工程从业者及希望入门AI选股的学生群体。报告系统梳理了Qlib的基础与进阶功能,对比传统量化策略开发流程,提炼其数据存储方案、表达式引擎、缓存系统等工程创新,并探讨实际使用体会。资源包内仅含1个PDF文件,大小约4.71MB,内容涵盖Qlib安装、数据准备、港股日频量价因子生成、LightGBM选股策略构建与结果展示,以及自定义因子、标签、预处理方式和AI模型等进阶组件讲解。目前已有1172人学习下载。读者可借此快速理解Qlib覆盖量化投资全过程的架构设计,掌握从环境搭建到策略回测的完整操作路径,并了解其相对MySQL、MongoDB、InfluxDB等方案在因子计算性能上的优势,为后续AI选股模型开发提供可复用的参考框架。
1. 从一份港股数据说起:Qlib 到底能帮你省掉哪些重复劳动
如果你写过因子选股的回测脚本,大概率经历过这样的循环:用 pandas 读一堆 csv,手动对齐交易日历,算完因子再拼标签,换一个模型就得重写一遍数据加载逻辑。这套流程跑通一次不难,难的是每次换因子、换模型、换股票池都要动一遍底层代码。Qlib 想解决的正是这个问题——它把量化投资从数据存储、因子计算、模型训练到回测评估串成一条标准流水线,你只需要在关键节点上换参数或继承类,不用每次从零搭架子。
这份资源是一份实操型研究报告,以港股日频量价因子搭配 LightGBM 选股为例,把 Qlib 的安装、数据准备、因子生成、策略构建、结果展示完整走了一遍,还深入讲了自定义因子、标签、预处理方式和 AI 模型的进阶用法。适合两类人:一是想快速上手 Qlib 但被官方文档绕晕的开发者,二是已经在用量化框架、想看看 Qlib 的工程实现值不值得迁移的熟手。下面按实际落地顺序拆开讲。
2. 环境搭建与数据准备:从安装到 dump_all 的完整链路
2.1 安装环节的两个硬性依赖
Qlib 的安装本身不复杂,但有两个前置条件容易翻车。第一,Python 版本建议 3.7 及以上;第二,Windows 环境下必须装 Microsoft Visual C++ 14.0 以上的生成工具。注意这里说的是完整版生成工具,不是那个小体积的 Redistributable 运行组件——只装运行组件,安装 Qlib 时照样报Microsoft Visual C++ 14.0 is required。
官方给了 pip 和 setup.py 两种安装方式。pip 一行pip install pyqlib确实省事,但装的是稳定版;setup.py 方式会拉取开发版,版本更新。我一般推荐后者,因为 Qlib 迭代快,开发版里往往已经修了一些稳定版的坑。具体操作:
# 先确保 numpy 和 cython 就位 pip install numpy pip install --upgrade cython # 方式一:有 git 环境 git clone https://github.com/microsoft/qlib.git && cd qlib python setup.py install # 方式二:没 git,下载 zip 源码包解压后,在 setup.py 所在目录执行 python setup.py install参数说明:setup.py install会自动处理依赖并编译 Cython 扩展,这也是为什么需要 C++ 生成工具。安装完成后可以用pip show pyqlib确认版本,开发版通常带.dev后缀。
2.2 数据下载与格式转换
Qlib 自带 A 股和美股数据下载脚本,但这份资源用的是港股数据,所以走的是用户自定义数据导入路线。核心工具是dump_bin.py里的dump_all指令,它把 csv 转成 Qlib 内部的 bin 格式。
先看 csv 的组织方式:每只股票一个 csv 文件,文件名就是股票代码,全部放在同一个文件夹下。字段方面,除了开高低收量额,有两个字段必须带上——factor(复权因子)和change(涨跌幅)。缺了它们,跑官方策略范例时净值曲线会出异常,这是实测踩过的坑。价格字段建议用复权价,因为后续标签计算和回测撮合都依赖 close 或 vwap。
转换命令长这样:
python scripts/dump_bin.py dump_all \ --csv_path ~/.qlib/csv_data/hk_data \ --qlib_dir ~/.qlib/qlib_data/hk_data \ --symbol_field_name stock_code \ --date_field_name date \ --include_fields open,high,low,close,volume,money,factor,vwap,change参数逐个说:csv_path是原始 csv 所在目录;qlib_dir是转换后 bin 文件的输出目录;symbol_field_name指定 csv 里哪一列是股票代码;date_field_name指定日期列;include_fields列出要保留的字段,注意逗号后面不能有空格,否则解析会出错。转换完成后,目标目录下会出现calendar、features、instruments三个子目录,分别存交易日历、因子数据和股票池信息。
提示:如果 pip 安装后运行
get_data报ModuleNotFoundError: No module named 'qlib.tests',把源码包里的 tests 文件夹拷到安装路径下即可。
3. 因子生成与模型训练:Alpha158 因子库和 LightGBM 的对接方式
3.1 初始化环境与自定义股票池
数据就位后,第一步是初始化 Qlib 运行环境,指定数据路径和区域:
import qlib from qlib.constant import REG_HK qlib.init(provider_uri="~/.qlib/qlib_data/hk_data", region=REG_HK)provider_uri指向 bin 数据目录,region告诉 Qlib 用哪套交易日历和交易规则。初始化之后,可以用D.calendar()拿交易日列表,用D.instruments()拿股票列表。自定义股票池的做法是写一个文本文件,每行一个股票代码,然后在配置里引用这个文件路径。这一步决定了后续因子计算和回测的范围,股票池设得太宽会拖慢速度,设得太窄又影响模型泛化。
3.2 Alpha158 因子库的调用与标签生成
Qlib 内置了 Alpha158 和 Alpha360 两个因子库。Alpha158 包含 158 个量价因子,覆盖 K 线形态、滚动统计、量价相关性等维度。调用方式是通过DataHandler配置:
from qlib.contrib.data.handler import Alpha158 data_handler_config = { "start_time": "2008-01-01", "end_time": "2020-11-30", "fit_start_time": "2008-01-01", "fit_end_time": "2017-12-31", "instruments": "hk_stock_pool", } handler = Alpha158(**data_handler_config)这里fit_start_time和fit_end_time是给数据预处理用的,比如标准化时的均值和方差只在这段区间内拟合,避免用到未来信息。标签默认是下期收益率,基于 close 计算。如果你想换标签,比如用 vwap 算收益,或者改成多期收益,可以继承Alpha158重写get_label_config方法。
因子生成完之后,可以用handler.fetch按日期和股票代码取数据,检查因子值是否正常。常见问题是某些因子全为 NaN,通常是因为股票池里有些股票历史数据太短,滚动窗口算不出来。
3.3 LightGBM 模型训练与 workflow 串联
Qlib 把模型训练封装成 task,用 workflow 把数据 handler、模型、数据集串起来。核心配置分三块:
from qlib.contrib.model.gbdt import LGBModel from qlib.workflow import R model = LGBModel( loss="mse", colsample_bytree=0.8, learning_rate=0.05, subsample=0.8, n_estimators=500, ) task = { "model": model, "dataset": { "class": "DatasetH", "module_path": "qlib.data.dataset", "kwargs": { "handler": handler, "segments": { "train": ("2008-01-01", "2017-12-31"), "valid": ("2018-01-01", "2018-12-31"), "test": ("2019-01-01", "2020-11-30"), }, }, }, } with R.start(experiment_name="hk_lgb"): R.save_objects(**{"params.pkl": model}) model.fit(task["dataset"]) R.save_objects(**{"model.pkl": model})segments把数据切成训练、验证、测试三段,时间上必须严格递增,否则就是未来函数。R.start是 Qlib 的实验管理入口,每次训练会生成一个记录,方便后续对比不同参数的效果。训练完成后模型和参数都会存下来,回测时直接加载。
4. 回测与绩效分析:从信号到净值的落地细节
4.1 回测配置与执行
模型训练完只是有了预测分数,要变成可评估的策略还得过回测。Qlib 的回测配置主要控制持仓规则、交易成本和基准:
from qlib.contrib.evaluate import backtest_daily from qlib.contrib.strategy import TopkDropoutStrategy strategy = TopkDropoutStrategy( signal=pred_score, topk=50, n_drop=5, ) port_analysis_config = { "strategy": strategy, "backtest": { "start_time": "2019-01-01", "end_time": "2020-11-30", "account": 100000000, "benchmark": "hkhsi", "exchange_kwargs": { "freq": "day", "limit_threshold": 0.095, "deal_price": "close", "open_cost": 0.0005, "close_cost": 0.0015, "min_cost": 5, }, }, }TopkDropoutStrategy是最简单的选股策略:每天持有预测分数最高的 50 只,卖出其中 5 只并买入新的 5 只。limit_threshold是涨跌停限制,港股没有 A 股那种硬性涨跌停,但设一个阈值可以过滤掉极端价格。deal_price指定用收盘价撮合,open_cost和close_cost是买卖手续费率。这些参数直接决定回测结果的可信度,设得太乐观净值会虚高。
4.2 结果读取与绩效指标
回测跑完后,Qlib 会生成一份分析报告,包含 IC、Rank IC、净值曲线、最大回撤、换手率等指标。读取方式:
from qlib.contrib.report import analysis_position report_normal, positions_normal = backtest_daily( start_time="2019-01-01", end_time="2020-11-30", strategy=strategy, account=100000000, benchmark="hkhsi", exchange_kwargs=exchange_kwargs, ) analysis_position.report_graph(report_normal)IC 衡量预测分数和实际收益的相关性,Rank IC 看的是排序相关性。这两个指标比净值曲线更早暴露模型问题——如果 IC 长期在零附近晃,净值再好也可能是运气。最大回撤和换手率则直接关系到策略的实盘可行性,换手率太高的话,手续费会吃掉大部分超额收益。
注意:这份资源里的港股策略仅作教学演示,没有剔除低价股和低流动性股票,训练和测试区间也偏短,不具备实际投资参考价值。
5. 避坑与排查:安装、数据、回测中最容易翻车的几个点
5.1 安装报错 C++ 14.0 required
现象:Windows 下执行python setup.py install时报错,提示缺少 Microsoft Visual C++ 14.0。原因:Qlib 的部分模块用 Cython 编译,需要 C++ 编译工具链。解决:下载 Microsoft C++ 生成工具完整版安装,安装时勾选“使用 C++ 的桌面开发”工作负载。只装 Redistributable 运行组件没用。
5.2 dump_all 转换后数据为空
现象:csv 转 bin 之后,features 目录下没有文件或文件数量对不上。原因:include_fields参数里逗号后面带了空格,或者 csv 字段名和参数不匹配。解决:检查--include_fields的值,确保逗号后无空格;确认--symbol_field_name和--date_field_name跟 csv 表头完全一致。
5.3 回测净值曲线异常
现象:策略净值要么一条直线,要么暴涨暴跌。原因:csv 数据缺少factor或change字段,导致复权计算和涨跌幅判断出错。解决:在原始 csv 里补上这两个字段,重新跑 dump_all。复权因子可以从数据源直接导出,涨跌幅用 close 算一下就行。
5.4 因子值大面积 NaN
现象:handler.fetch取出来的因子矩阵里大量缺失值。原因:股票池里包含上市时间短的股票,滚动窗口因子算不出来;或者交易日历和股票数据的时间范围没对齐。解决:在股票池里过滤掉历史数据不足的标的,或者在 handler 配置里设置start_time时留出足够的预热期。
5.5 训练集和测试集时间重叠
现象:模型在测试集上表现异常好,IC 高得不正常。原因:segments里 train、valid、test 的时间区间有重叠,或者fit_start_time、fit_end_time设到了测试区间内。解决:严格按时间顺序切分,预处理参数的拟合区间只能落在训练集内。
6. 二次开发:自定义组件与性能优化的实操思路
6.1 自定义因子、标签和预处理
Qlib 的组件化设计让自定义变得直接。最简单的改法是调参数,比如换标签的计算方式:
from qlib.contrib.data.handler import Alpha158 class MyHandler(Alpha158): def get_label_config(self): return ["Ref($vwap, -2) / Ref($vwap, -1) - 1"], ["LABEL0"]这段代码把标签从默认的 close 收益改成 vwap 的两期收益。Ref($vwap, -2)表示两天后的 vwap,表达式引擎会自动处理时间对齐。如果要加自定义因子,在get_feature_config里追加表达式即可,比如"($close - Ref($close, 5)) / Ref($close, 5)"就是五日动量。
预处理方式的替换更简单,Qlib 内置了DropnaLabel、CSZScoreNorm、RobustZScoreNorm等处理器,在 handler 配置的processors列表里换一个就行。比如把截面标准化换成截面排序标准化,改一行配置的事。
6.2 替换 AI 模型
Qlib 内置了 LightGBM、XGBoost、CatBoost、MLP、LSTM 等模型。换模型有两种方式:一是改task里的model配置,指定不同的模型类;二是继承Model基类写新模型。以 SVR 为例:
from qlib.model.base import Model from sklearn.svm import SVR class SVRModel(Model): def __init__(self, **kwargs): self.model = SVR(**kwargs) def fit(self, dataset): X_train, y_train = dataset.prepare("train", col_set=["feature", "label"]) self.model.fit(X_train.values, y_train.values.ravel()) def predict(self, dataset): X_test, _ = dataset.prepare("test", col_set=["feature", "label"]) return pd.Series(self.model.predict(X_test.values), index=X_test.index)关键点是fit和predict两个方法的输入输出格式:dataset.prepare返回的 DataFrame 是多层索引,feature 和 label 分开取;predict返回的 Series 索引必须和测试集一致,否则回测时信号对不上。
6.3 性能调优的切入点
Qlib 的性能优势主要来自三个设计:bin 格式的列式存储、表达式引擎的惰性计算、以及缓存系统。二次开发时如果想进一步提速,可以从这几个方向入手。数据层面,把不常用的字段从include_fields里去掉,减少 IO;因子层面,避免在表达式里写太复杂的嵌套,拆成多个简单因子再组合;缓存层面,Qlib 会自动缓存计算过的因子,但如果股票池或时间范围频繁变动,缓存命中率会下降,建议固定实验配置再跑批量测试。
我自己的习惯是,每次改完因子或模型配置,先跑一个小股票池、短时间段的快速验证,确认流程通了再放大到全量数据。Qlib 的 workflow 支持这种分阶段实验,用不同的experiment_name隔离就行。从那以后我每次调参都强制走一遍小样本验证,省了不少等全量跑完才发现配置写错的时间。希望帮到你。
本文还有配套的精品资源,点击获取