因子表达式引擎指南¶
本页定位为“查表 + 排障”,用于快速回答三个问题:
- 表达式怎么写才符合语义?
- 算子有哪些、参数怎么填?
- 报错或结果异常时先查什么?
如果你想系统学习从想法到落地的完整路径,可以再看 第 14 章:高性能因子挖掘与表达式引擎。
1. 为什么需要因子表达式¶
在因子研究中,核心瓶颈通常不是“不会写代码”,而是“想法验证速度太慢”。使用表达式引擎的主要价值有三点:
- 把研究目标从工程细节中解耦,只关注因子数学结构。
- 把重复的分组、窗口、对齐逻辑交给引擎,减少手写错误。
- 统一因子定义格式,便于复现、对比和批量迭代。
典型对比:
- 传统方式:每个因子都手写 DataFrame 逻辑,代码冗长且难统一。
- 表达式方式:例如
Rank(Ts_Mean(Close, 10)),可直接进入验证和迭代。
2. AKQuant 的因子表达式特色¶
- 高性能执行:底层基于 Rust + Polars,利用 Lazy 执行与并行计算。
- 分区语义清晰:明确区分 TS/CS/EL,跨分区嵌套自动拆步执行。
- 工程化可调试:复杂表达式可先内层后外层验证,定位问题更直接。
- 批量计算友好:
run_batch适合统一样本池下的多因子并行评估。 - 时区与数据规范明确:默认
Asia/Shanghai,非 A 股场景可显式设置。
3. 最小使用模板¶
from akquant.factor import FactorEngine
engine = FactorEngine(catalog)
df = engine.run("Rank(Ts_Mean(Close, 10))")
df_batch = engine.run_batch(
[
"Ts_Mean(Close, 5)",
"Rank(Volume)",
"If(Close > Open, 1, 0)",
]
)
最小执行顺序建议:
- 准备
catalog并保证数据可读。 - 先
run一个单表达式验证数据链路。 - 再
run_batch做多因子并行计算。
输入数据建议至少包含:
symboldateopen,high,low,close,volume(按策略实际需求)
返回结果约定:
run(expr):返回date,symbol,factor_value三列核心结果。run_batch(exprs):返回date,symbol加多列因子值宽表。
时区约定:
- 默认
Asia/Shanghai。 - 非 A 股场景请显式设置
timezone,并对时间列显式tz_localize。
4. 语法规则速览¶
4.1 变量与常量¶
- 列名不区分大小写:
Close与close等价。 - 数值常量可直接写:
1、0.5。 - 变量名必须能映射到真实列;如数据是
ClosePrice,写Close会失败。
4.2 运算符¶
- 算术运算:
+,-,*,/ - 比较运算:
>,<,>=,<=,==,!= - 逻辑组合:可在条件中使用
&,|
示例:
4.3 三类分区语义¶
- TS(时序):按
symbol分组滚动。 - CS(截面):按
date分组横截面。 - EL(元素级):逐元素变换,不引入窗口。
跨分区嵌套(如 Rank(Ts_Mean(...)))会被拆步执行并物化中间结果。
5. 算子速查¶
5.1 时序算子 (TS)¶
| 算子 | 别名 | 说明 | 示例 |
|---|---|---|---|
Ts_Mean(X, d) |
Mean |
过去 d 期移动平均 |
Ts_Mean(Close, 5) |
Ts_Std(X, d) |
Std |
过去 d 期移动标准差 |
Ts_Std(Close, 20) |
Ts_Max(X, d) |
Max |
过去 d 期最大值 |
Ts_Max(High, 10) |
Ts_Min(X, d) |
Min |
过去 d 期最小值 |
Ts_Min(Low, 10) |
Ts_Sum(X, d) |
Sum |
过去 d 期求和 |
Ts_Sum(Volume, 5) |
Ts_ArgMax(X, d) |
ArgMax |
过去 d 期最大值距今天数 |
Ts_ArgMax(Close, 5) |
Ts_ArgMin(X, d) |
ArgMin |
过去 d 期最小值距今天数 |
Ts_ArgMin(Close, 5) |
Ts_Rank(X, d) |
- | 当前值在过去 d 期分位排名 |
Ts_Rank(Close, 5) |
Delta(X, d) |
- | X(t) - X(t-d) |
Delta(Close, 1) |
Delay(X, d) |
Ref |
滞后 d 期数值 |
Delay(Close, 1) |
Ts_Corr(X, Y, d) |
Corr |
过去 d 期相关系数 |
Ts_Corr(Close, Volume, 20) |
Ts_Cov(X, Y, d) |
Cov |
过去 d 期协方差 |
Ts_Cov(Close, Open, 20) |
5.2 截面算子 (CS)¶
| 算子 | 说明 | 示例 |
|---|---|---|
Rank(X) |
同日横截面百分比排名(0~1) | Rank(Close) |
Scale(X) |
同日归一化,sum(abs(X)) = 1 |
Scale(Close) |
5.3 逻辑与数学算子 (EL)¶
| 算子 | 说明 | 示例 |
|---|---|---|
If(Cond, A, B) |
条件判断 | If(Close > Open, 1, -1) |
Sign(X) |
符号函数(1, 0, -1) | Sign(Close - Open) |
Abs(X) |
绝对值 | Abs(Close - Open) |
Log(X) |
自然对数 | Log(Volume) |
SignedPower(X, e) |
保持符号的幂运算 | SignedPower(Close, 2) |
6. 排障手册(按优先级)¶
6.1 结果全是 NaN¶
优先检查:
d是否大于可用历史长度(Warmup 不足)。- 原始列是否有大量 NaN。
- 列名是否真实可映射。
6.2 嵌套表达式明显变慢¶
常见原因是跨分区嵌套触发拆步物化。处理方式:
- 先单独运行内层表达式。
- 确认内层结果合理后再加外层。
- 批量场景再考虑
run_batch。
6.3 窗口语义与预期不一致¶
若数据有停牌/缺失日期,滚动窗口按行推进,可能偏离“自然日”理解。建议先做交易日对齐。
6.4 列名看着对却报错¶
引擎会做大小写归一,但不会猜测别名。ClosePrice 与 Close 不是同一列。
6.5 同策略跨市场结果漂移¶
先检查时区与本地化:
- 默认时区为
Asia/Shanghai。 - 非 A 股必须显式设置
timezone。 - 时间列需要显式
tz_localize。
更多时区细节见 时区处理指南。
7. 性能建议¶
- 先
run调通,再run_batch扩展。 - 减少不必要的深层嵌套,优先可解释的组合结构。
- 使用最小必要列,降低 IO 与内存占用。
- 对停牌和缺失日期提前清洗,减少窗口偏差导致的反复调试。
8. 教程迁移说明¶
当前你可能在教程页和指南页都能看到因子表达式内容。为了避免依赖单一入口,本指南保持独立可读:
- 教程侧重学习路径与案例。
- 本页侧重速查、规范与排障。
- 即使教程后续迁移位置,本页仍可直接作为日常开发参考。
9. FAQ¶
Q: 支持分钟线吗?
A: 支持。date 包含时间戳即可;d=60 表示过去 60 根 bar。
Q: 为什么同一表达式在不同数据源结果不同? A: 通常不是算子问题,而是数据对齐、复权、缺失值处理与时区设置差异。
Q: 什么时候优先用 run_batch?
A: 同样本池、同时间段、多因子并行评估时优先;单表达式调试时优先 run。