警惕算法交易中的“平滑”陷阱
最近在对之前写的量化交易系统进行重构,测试时发现有一些与“平滑”有关的事还是值得记录一下,分享的同时也方便后续不再踩坑。
实盘测试时遇见的问题
很久以前曾经写过一个基于考夫曼均线与ATR的通道策略,躺在代码库中吃灰许久,未认真回测,没有用于过实盘交易,测试的时候翻出来简单重构了一下以适应新的回测引擎,然后实盘模拟跑跑看。
这是一个通道型的均值回归交易策略,基于考夫曼均线及ATR构建通道,不同于布林带使用标准差,这个通道一般不会大幅度敞口。正常情况下K线通常运行在通道内部,当出现极端超卖或超买,K线会突破通道形成买点卖点。当K线自通道外上穿下轨为买入信号,自通道外下穿上轨为卖出信号。策略核心参数如下:
| 参数 | 说明 |
|---|---|
| Kama_Period | KAMA均线计算周期 |
| Atr_Period | ATR波动率计算周期 |
| Up_Band | 通道上轨ATR倍数 |
| Down_Band | 通道下轨ATR倍数 |
| Stop_Loss | 固定止损 |
用实时数据对该策略进行测试时,发现从图表上看应当触发交易信号,但实际系统运行并没有任何动作,从代码上我确信没有逻辑Bug,问题出在哪里?通过从控制台打印的指标计算结果与实盘图表上的指标值进行对比,我发现两者并不相同,这让人费解,因为从实现上,图表渲染的指标数据与实盘引擎计算,调用的是同一个类方法(self.make_indicator),是什么导致计算结果出现大幅偏差呢?
问题的根源 - 平滑
既然图表与交易判断在指标计算上调用的是同一个接口,那么问题只能出在两者不同的参数处理上。
为了最小化实盘阶段策略实例的计算量,提高响应速度,我在该策略的交易信号判断接口中只使用了 最低需求K线数量 进行指标计算。比如Kama的周期设置为20,ATR的周期设置30,那么我只取最新的35根K线进行指标计算。而在图表绘制模块中,为了观察到图表整体的指标全貌,传入绘图方法的K线数据是数据库中的K线全量数据,同时用 全量数据 使用内置的回测引擎进行回测得到买卖信号,然后叠加在图表上。
问题就在这里,使用 最低需求K线数量 与使用 全量数据,在最新的指标计算结果上是不同的!这让我忽然想起以前学习ATR指标计算方法时,接触过的Wilder平滑算法,于是我去千问查了查两个指标算法上的一些细节,结论如我的猜测:Kama与ATR在计算时均具有 “所有历史数据对当前值有非零影响” 的特征。具体而言:
Kama计算公式:
$$ \text{KAMA}_t = \text{KAMA}_{t-1} + \text{SC} \times (P_t - \text{KAMA}_{t-1}) $$
$$ \text{SC} = \left[ \text{ER} \times (\text{fast_SC} - \text{slow_SC}) + \text{slow_SC} \right]^2 $$
$$ \text{ER} = \frac{\text{Direction}}{\text{Volatility}} \in [0, 1] $$
$$ \text{Direction} = |P_t - P_{t-N}| $$
$$ \text{Volatility} = \sum_{i=1}^{N} |P_{t-i+1} - P_{t-i}| $$
ER是考夫曼均线的自适应平滑系数,也是考夫曼均线过滤震荡并且能及时响应的根源。算法上,Kama现值的计算对t-1期值有递归,ER的算法又直接决定了现值对远期递归及近期递归样本的敏感程度,因此这是一个使用全量样本滚动计算现值的指标,而不仅仅局限于你所设定指标周期样本。
采用Wilder平滑算法的ATR计算公式:
$$ \text{ATR}_t = \text{ATR}_{t-1} + \frac{ \text{TR}_t - \text{ATR}_{t-1} }{N} $$
采用Wilder平滑的ATR指标,t期现值的计算会受到t-1期值递归传递的影响,然后由1/N再进行平滑。
还有哪些常见技术指标有其他类似情况
理论上,所有基于 “递推式平滑”(而非滑动窗口截断)的技术指标,都会受周期外远期数据影响,我让AI梳理了一下,以下是按受指标周期外历史数据影响程度(即历史信息衰减速度)从慢到快(即“记忆最长” → “记忆最短”)进行排序的表格:
📊 技术指标历史数据影响程度排序(记忆长度从长到短)
| 排名 | 指标 | 平滑机制 | 等效平滑系数 α(近似) | 历史数据衰减速度 | 说明 |
|---|---|---|---|---|---|
| 1 | KAMA | 自适应 EMA(动态 α) | α ∈ [α_min, α_max] (例如 N=30 时 α_min ≈ 0.004) |
⭐⭐⭐⭐⭐ 最慢(震荡市) | 在低效率市场(ER≈0)时,α 极小,衰减极慢,记忆超长;趋势市中变快。平均而言记忆最长。 |
| 2 | ATR | Wilder 平滑 | α = 1/N | ⭐⭐⭐⭐ 慢 | Wilder 平滑等价于 α = 1/N 的 EMA(比标准 EMA 更慢)。例如 N=14 → α≈0.071。 |
| 3 | RSI | Wilder 平滑(Avg Gain/Loss) | α = 1/N | ⭐⭐⭐⭐ 慢 | 与 ATR 相同平滑机制,记忆长度相当。 |
| 4 | ADX / DMI | 双重 Wilder 平滑 | α ≈ 1/N(两层) | ⭐⭐⭐ 中等偏慢 | 先对 DM 和 TR 做 Wilder 平滑,再对 DX 做第二次 Wilder 平滑,整体衰减略快于单层,但仍慢于 EMA。 |
| 5 | EMA | 标准指数平滑 | α = 2/(N+1) | ⭐⭐ 中等 | 经典 EMA。例如 N=14 → α≈0.133,衰减快于 Wilder(因 α 更大)。 |
| 6 | MACD | 双 EMA 差值 + 信号线 EMA | α₁=2/13, α₂=2/27, α₃=2/10 | ⭐⭐ 中等 | 虽含多层 EMA,但核心仍是标准 EMA,整体衰减速度与 EMA 同阶。 |
| 7 | TRIX | 三重 EMA | α = 2/(N+1)(三层嵌套) | ⭐ 较快 | 三次 EMA 导致高频成分被强力压制,但远期数据衰减更快(因 (1−α)³ 累积衰减)。短期更敏感,长期记忆弱于单 EMA。 |
📌 说明:
- 所有这些指标均采用递归平滑结构,理论上所有历史数据都有影响(权重 > 0)。
- “影响程度”由等效衰减因子(effective decay factor) 决定:衰减越慢,远期数据权重越高,记忆越长。
- 比较基于相同输入周期 N(如都用 N=14)下的典型实现。
- 若比较不同周期(如 RSI(2) vs EMA(100)),则周期长度主导记忆长短。本表假设相同名义周期 N(如都用 14)。
- DMI 本身是 +DI/-DI,其计算依赖于对 +DM/-DM 和 TR 的 Wilder 平滑,因此与 ADX 底层一致,排位相同。
- Wilder 平滑(α = 1/N)比标准 EMA(α = 2/(N+1))衰减更慢。
例:N=14 → Wilder α≈0.071,EMA α≈0.133 → Wilder 记忆更长。- KAMA 在震荡市中 α 可远小于 1/N(如 α≈0.004),此时记忆长度可达数百日,显著长于其他指标。
- TRIX 虽平滑,但因多次应用 EMA,长期记忆反而被削弱——它更关注“近期变化率”,而非长期水平。
- “影响程度” ≠ “滞后性”:KAMA 趋势市中滞后小,但震荡市中因强平滑而滞后大,但其“记忆长度”在震荡市极长。
评论 (0)
发表评论
正在加载评论...