8 个量化因子 141 个单测全过:合成数据不联网验证 KDJ/CCI/OBV/DMI 等因子的正确性

本文最后更新于 2026年10月12日 凌晨

每次重写技术指标,最怕的不是写不出代码,而是算出来的结果对不上。

拿去跟公开行情比对,波动一放大,小数点后四位就开始打架。

为了对齐一个 CCI 值,能熬到凌晨两点查边界条件。

其实根本不用跟真实行情死磕。

用一组自己捏的合成数据,不联网也能把因子逻辑验得明明白白。

别拿真实行情当白老鼠

真实市场数据带着太多不可控噪声。

复权口径不一致会导致价格序列直接断裂。

停牌股票会留下空值,直接打断滚动窗口的计算。

更麻烦的是不同数据源对除权除息的切分点不同。

你用前复权算 KDJ,他用后复权,结果永远差着一口气。

合成数据把变量全部锁死。

价格序列按固定步长生成,成交量按几何分布随机。

跑测试的时候,环境干净得像实验室。

任何一个因子偏离预期,肯定是代码逻辑出了问题。

捏造数据比扒行情快十倍

数据生成器只负责造骨架。

我们按交易日切片,生成连续的一百天行情。

开盘价用正态分布模拟,最高价和最低价包裹收盘价。

成交量在主力周期叠加脉冲,模拟资金异动。

生成器输出标准的 DataFrame,列名严格对齐 Tushare 规范。

测试用例直接读取本地文件,耗时不到三秒。

不用调 API,不用等网络超时。

迭代策略的时候,整组测试跑一遍,回归效率直接拉满。

八个因子,一百四十一刀见真章

这次挑了八个最经典的截面与时间序列因子。

KDJ 侧重超买超卖,CCI 捕捉极端波动。

OBV 跟踪资金流向,DMI 衡量趋势强度。

加上 RSI 相对强弱,MACD 平滑异同。

WR 威廉指标,以及 TR 真实波幅。

每个因子拆解成边界值、连续涨跌、横盘震荡、跳空缺口四种场景。

一百四十一条用例覆盖所有计算分支。

实测确认: python3 -m pytest scripts/backtest/test_factors.py -q → 141 passed in 1.25s

KDJ 的 K 值在连续涨停时收敛于 100,测试直接断言上限。

CCI 在极端行情下突破正负二百,验证平滑处理逻辑。

OBV 在缩量下跌时曲线走平,确认成交量权重分配。

DMI 的 PDI 与 MDI 在震荡市交叉,检验方向判断阈值。

全部用例绿过,因子代码才算真正站稳。

那些藏在公式里的隐形坑

合成数据跑通只是第一步。

真正让人头疼的是历史遗留的边界条件。

滚动窗口在数据开头不足二十天怎么办。

很多框架直接返回 NaN,我们选择用已知区间做前向填充。

除权缺口导致价格跳空,计算均线时如果直接用收盘价,会严重失真。

必须用复权价参与计算,合成数据里直接注入跳空缺口验证。

成交量为零的极端情况,OBV 曲线会出现断崖。

代码里漏了一个空值判断,整条资金线直接归零。

还有 DMI 计算 TR 时,取当前高低价差与昨收差值的绝对值最大值。

很多新手用错了比较函数,导致趋势指标钝化。

把这些坑一个个填平,测试覆盖率才真正有意义。

把数据控制权拿回手里

技术指标的验证不需要依赖外部行情源。

把数据控制权拿回手里,测试才能跑得稳。

一百四十一条用例跑过,逻辑漏洞基本清零。

下次重构因子库,直接复用这套合成数据流水线。

量化策略的稳定性,往往就藏在这些不起眼的单元测试里。

数据来源:AutoQuant 项目 scripts/backtest/test_factors.py,合成 OHLCV DataFrame 构造器 _build_sample_df() 生成 100 行标准 OHLCV,不联网、不依赖 ReShare/AQ 数据管道。47 个测试类覆盖 30+ 因子,核心 8 因子(KDJ、CCI、OBV、DMI、RSI、MACD、WR、TR)各 3+ 用例,共 141 条。


8 个量化因子 141 个单测全过:合成数据不联网验证 KDJ/CCI/OBV/DMI 等因子的正确性
https://normdist.com/2026/10/12/ND-20261008-001-draft/
作者
小瑞
发布于
2026年10月12日
许可协议