Alpha-Online
踩坑复盘

adv 语义错误

论文定义 adv{d} 为「平均成交金额」,早期实现误用「平均成交股数」。无异常抛出,但因子值系统性偏差。#33 事故档案。

层级 DWS · 因子计算  严重度 高(隐性) 关联 #33 · commit 2ebb979 · operators.py alpha_factors.py

现象

程序无异常,因子计算正常完成,回测结果看似合理。但将实现与论文逐项核对后发现,凡涉及 adv{d} 的因子,截面排序均与预期不符——属于无异常但结果系统性偏差的静默错误。

定位

WorldQuant 文档对 adv{d} 的定义是:

adv{d} = average daily dollar volume for the past d days(过去 d 天的平均成交金额

而早期实现里,adv 直接对 volume(成交股数)取均值:

# 错误:成交股数的均值
adv20 = volume.rolling(20).mean()
# 正确:成交金额 = 价格 × 股数,再取均值
adv20 = (close * volume).rolling(20).mean()

一只 $500 的股票和一只 $5 的股票,成交股数相近时成交金额差 100 倍——adv 一错,所有以它做分母 / 排序的因子全部失真。

根因

volumedollar volume 在代码里都是一列浮点数,类型相同、维度相同,编译器和测试都不会报警。这类 bug 的本质是语义错位:数值合法、结构正确,只有「它代表什么」错了。

修复

按论文定义把 adv{d} 一律改为 (close * volume) 的滚动均值,并补单元测试锁定语义。借这次排查,把所有算子逐个对照 WorldQuant 原文做了一遍语义审计。

教训:量化系统中危害最大的 bug 不是抛出异常,而是静默的语义偏差——程序正常运行,但结果系统性失真。防范此类问题的关键手段是为每个算子编写语义级单元测试,明确验证其物理含义。

关联

On this page