4. Qlib数据表达式引擎入门

任务目标

用 Qlib 的表达式引擎(Expression Engine)在已有行情数据上计算两类技术指标:移动平均(MA)与收益率(Return),并验证表达式结果与手工计算一致。

环境与依赖

  • Python 3.8+,已安装 pyqlib(pip install pyqlib)。
  • 已通过 python -m qlib.run.get_data 或 qlib.init 准备好一份本地数据(本案例使用 qlib_data/cn_data 作为示例路径,请按实际路径替换)。

核心思路

Qlib 表达式引擎把字符串表达式(如 Mean($close, 5)、$close/Ref($close,1)-1)解析为算子并作用在行情字段上。字段以 $ 前缀引用,算子通过 qlib.data.ops 注册。我们只需初始化数据、构造表达式、调用 D.features 即可得到指标序列。

完整代码

import qlib
from qlib.data import D

# 1. 初始化 Qlib,指向本地数据目录
qlib.init(provider_uri="qlib_data/cn_data", region="cn")

# 2. 定义标的与时间区间
instruments = ["SH600000"]
fields = ["$close"]

# 3. 构造表达式:5日均线、10日均线、日收益率
exprs = {
    "ma5":  "Mean($close, 5)",
    "ma10": "Mean($close, 10)",
    "ret1": "$close / Ref($close, 1) - 1",
}

# 4. 通过表达式引擎计算指标
df = D.features(
    instruments=instruments,
    fields=list(exprs.values()),
    start_time="2020-01-01",
    end_time="2020-03-31",
    freq="day",
)
df.columns = list(exprs.keys())
print(df.tail())

# 5. 验证:与 pandas 手工计算对比
import pandas as pd
close = D.features(instruments, fields, "2020-01-01", "2020-03-31", freq="day")
close.columns = ["close"]
manual = pd.DataFrame({
    "ma5":  close["close"].rolling(5).mean(),
    "ma10": close["close"].rolling(10).mean(),
    "ret1": close["close"].pct_change(),
})
diff = (df - manual).abs().max()
print("最大偏差:\n", diff)
assert (diff.fillna(0) < 1e-8).all(), "表达式结果与手工计算不一致"
print("验证通过:表达式引擎结果与手工计算一致")

运行方式

python expr_demo.py

验证方法与通过条件

  • 脚本末尾的 assert 通过,说明 Mean、Ref 等算子结果与 pandas 手工计算在数值上一致(阈值 1e-8)。
  • 若断言失败,检查 provider_uri 是否指向真实数据目录,以及标的代码是否存在于该数据集中。
  • 常见问题:Mean 前 4 个交易日为 NaN(窗口不足),属正常现象,对比时用 fillna(0) 处理。