☰
指数移动平均 EMA(Exponential Moving Average)算法详解
2026/10/7 9:57:56 网站建设 项目流程

指数移动平均 EMA(Exponential Moving Average)算法详解

  • 一、算法详解
    • 1、引言
    • 2、 什么是移动平均
      • 2.1 、简单移动平均(SMA)
      • 2.2、 指数移动平均(EMA)
    • 3、 EMA 的数学定义
      • 3.1、 平滑因子 α 与窗口 N 的关系
    • 4、 递推公式的展开推导
    • 5、 EMA 与 SMA 的对比
      • 5.1 适用场景建议
    • 6、典型应用场景
      • 6.1 、量化交易中的技术指标
      • 6.2 、深度学习优化器中的参数平滑
      • 6.3、 系统监控与异常检测
    • 7. 总结
  • 二、代码示例

一、算法详解

1、引言

在时间序列分析、技术指标计算和深度学习优化器中,指数移动平均(Exponential Moving Average,简称 EMA)是一种极其常用的统计方法。与简单移动平均(SMA)不同,EMA 对近期数据赋予更高的权重,因此能更快地反映数据的最新变化趋势。

本文将从数学原理出发,逐步推导 EMA 的递推公式,并通过代码示例展示其实现方式,最后介绍 EMA 在量化交易和深度学习中的典型应用场景。

2、 什么是移动平均

移动平均(Moving Average,MA)是一种用于平滑时间序列数据的技术,其核心思想是取一段时间窗口内数据的平均值,以消除短期波动、凸显长期趋势。

2.1 、简单移动平均(SMA)

简单移动平均对窗口内的所有数据点赋予相同权重,其计算公式为:

SMA_t = (x_t + x_{t-1} + ... + x_{t-N+1}) / N

其中N为窗口大小。SMA 的缺点是:窗口外的数据被完全丢弃,窗口内的数据权重相同,导致对最新变化的响应不够灵敏。

2.2、 指数移动平均(EMA)

EMA 则采用指数衰减的权重分配方式,越近的数据权重越大,越远的数据权重越小,且权重永远不会归零。这使得 EMA 既能平滑噪声,又能更快地跟踪趋势变化。

3、 EMA 的数学定义

EMA 在时刻t的取值EMA_t定义如下:

EMA_t = α * x_t + (1 - α) * EMA_{t-1}

其中:

  • x_t为当前时刻的观测值;
  • EMA_{t-1}为上一时刻的 EMA 值;
  • α为平滑因子(smoothing factor),取值范围为0 < α ≤ 1。

3.1、 平滑因子 α 与窗口 N 的关系

在实际应用中,α通常由窗口长度N换算而来:

α = 2 / (N + 1)

例如:

  • 当N = 5时,α = 2 / 6 ≈ 0.333;
  • 当N = 10时,α = 2 / 11 ≈ 0.182;
  • 当N = 20时,α = 2 / 21 ≈ 0.095。

窗口N越大,α越小,平滑效果越强,但对新数据的响应越慢;反之,N越小,α越大,对最新数据越敏感。

4、 递推公式的展开推导

将 EMA 的递推公式逐层展开,可以更直观地理解其权重分配机制。

假设从时刻0开始,初始值EMA_0 = x_0,则:

EMA_1 = α * x_1 + (1 - α) * EMA_0 = α * x_1 + (1 - α) * x_0 EMA_2 = α * x_2 + (1 - α) * EMA_1 = α * x_2 + (1 - α) * [α * x_1 + (1 - α) * x_0] = α * x_2 + α(1 - α) * x_1 + (1 - α)² * x_0

以此类推,可以得到通项公式:

EMA_t = α * x_t + α(1 - α) * x_{t-1} + α(1 - α)² * x_{t-2} + ... + (1 - α)^t * x_0

可以看出:

  • 当前时刻数据x_t的权重为α;
  • 前一个时刻数据x_{t-1}的权重为α(1 - α);
  • 前两个时刻数据x_{t-2}的权重为α(1 - α)²;
  • 权重按(1 - α)的幂次指数衰减,这正是「指数移动平均」名称的由来。

所有权重之和收敛于 1:

α + α(1 - α) + α(1 - α)² + ... = 1

5、 EMA 与 SMA 的对比

特性SMAEMA
权重分配窗口内等权近期权重高,指数衰减
响应速度较慢较快
对异常值敏感度较低较高
计算复杂度O(N)O(1) 递推
数据存储需保留窗口内全部数据只需保留上一时刻 EMA 值

5.1 适用场景建议

  • SMA:适合数据噪声较大、希望获得更平滑曲线的场景;
  • EMA:适合需要快速捕捉趋势变化、对实时性要求较高的场景。

6、典型应用场景

6.1 、量化交易中的技术指标

EMA 是技术分析中最常用的指标之一,常被用于:

  • 趋势判断:当短期 EMA(如 EMA12)上穿长期 EMA(如 EMA26)时,形成「金叉」,视为买入信号;反之形成「死叉」,视为卖出信号。
  • 动态支撑与压力位:价格在 EMA 上方运行时,EMA 常被视为支撑位;价格在 EMA 下方运行时,EMA 常被视为压力位。

6.2 、深度学习优化器中的参数平滑

在深度学习训练中,EMA 被广泛用于模型参数的滑动平均。具体做法是:在训练过程中,维护一份模型参数的 EMA 副本,训练结束后用 EMA 副本替代原始参数进行推理。

# 伪代码示例:训练过程中维护参数 EMAema_decay=0.999ema_params={}forstep,batchinenumerate(train_loader):# 常规梯度更新optimizer.zero_grad()loss=compute_loss(batch)loss.backward()optimizer.step()# 更新 EMA 参数forname,paraminmodel.named_parameters():ifnamenotinema_params:ema_params[name]=param.data.clone()else:ema_params[name]=ema_decay*ema_params[name]+(1-ema_decay)*param.data

这样做的好处是:

  • 对参数更新过程中的噪声进行平滑,使模型更加稳定;
  • 在训练后期,EMA 参数往往能取得比原始参数更好的泛化性能。

6.3、 系统监控与异常检测

在服务器监控场景中,EMA 常用于平滑 CPU 使用率、内存占用等指标,帮助运维人员识别长期趋势,同时过滤瞬时抖动造成的误报。

7. 总结

本文详细介绍了指数移动平均(EMA)的数学原理、递推公式推导、代码实现及典型应用场景。核心要点总结如下:

  • EMA 通过指数衰减的权重分配,对近期数据赋予更高权重;
  • 平滑因子α = 2 / (N + 1)建立了与窗口大小的换算关系;
  • EMA 只需保存上一时刻的值即可递推计算,空间复杂度为 O(1);
  • 相比 SMA,EMA 响应更快,更适合实时趋势跟踪场景;
  • EMA 在量化交易、深度学习参数平滑、系统监控等领域有广泛应用。

理解 EMA 的数学本质,有助于在实际问题中灵活选择平滑策略,从而更准确地把握数据的变化规律。

二、代码示例

#include<iostream>#include<Windows.h>#include<iostream>#include<cassert>classEMA{public:/// @brief 构造:标准EMA,alpha = 2/(N+1),K线算法,前N点SMA初始化explicitEMA(intperiod):alpha_(0.0f),period_(period),count_(0),sum_(0.0f),ema_prev_(0.0f),init_done_(false){assert(period>0);alpha_=2.0f/(period+1.0f);}/// @brief 构造:一阶指数平滑,自定义alpha,传感器滤波explicitEMA(floatcustom_alpha):alpha_(custom_alpha),period_(0),count_(0),sum_(0.0f),ema_prev_(0.0f),init_done_(true){assert(custom_alpha>0.0f&&custom_alpha<=1.0f);}// 送入新采样值,返回当前EMA结果floatupdate(floatval){if(!init_done_){sum_+=val;count_++;if(count_>=period_){ema_prev_=sum_/period_;init_done_=true;}returnema_prev_;}// 一阶平滑:首次进来直接赋值if(count_==0){ema_prev_=val;count_++;returnema_prev_;}ema_prev_=val*alpha_+ema_prev_*(1.0f-alpha_);count_++;returnema_prev_;}// 重置滤波器状态voidreset(){count_=0;sum_=0.0f;ema_prev_=0.0f;init_done_=false;}// 获取当前EMA值floatget()const{returnema_prev_;}private:floatalpha_;intperiod_;intcount_;floatsum_;floatema_prev_;boolinit_done_;};intmain(){SetConsoleOutputCP(CP_UTF8);// 方式1:标准EMA5,alpha=2/(5+1)EMAema5(5);floatprices[]={10,12,11,13,14,16,15,17,10,2,2,3,5,4,8,63,45,1000,1,2,2000};intlen=sizeof(prices)/sizeof(prices[0]);std::cout<<"===== EMA5 (周期构造) =====\n";for(inti=0;i<len;i++){floatv=ema5.update(prices[i]);std::cout<<"price="<<prices[i]<<", ema="<<v<<"\n";}// 方式2:传感器一阶平滑,直接指定alpha=0.2EMAfilter(0.2f);std::cout<<"\n===== 一阶平滑 alpha=0.2 =====\n";for(inti=0;i<len;i++){floatv=filter.update(prices[i]);std::cout<<"price="<<prices[i]<<", filter="<<v<<"\n";}return0;}

运行结果:

=====EMA5(周期构造)=====price=10,ema=0price=12,ema=0price=11,ema=0price=13,ema=0price=14,ema=12price=16,ema=13.3333price=15,ema=13.8889price=17,ema=14.9259price=10,ema=13.2839price=2,ema=9.52263price=2,ema=7.01509price=3,ema=5.67672price=5,ema=5.45115price=4,ema=4.96743price=8,ema=5.97829price=63,ema=24.9855price=45,ema=31.657price=1000,ema=354.438price=1,ema=236.625price=2,ema=158.417price=2000,ema=772.278=====一阶平滑 alpha=0.2=====price=10,filter=10price=12,filter=10.4price=11,filter=10.52price=13,filter=11.016price=14,filter=11.6128price=16,filter=12.4902price=15,filter=12.9922price=17,filter=13.7938price=10,filter=13.035price=2,filter=10.828price=2,filter=9.0624price=3,filter=7.84992price=5,filter=7.27994price=4,filter=6.62395price=8,filter=6.89916price=63,filter=18.1193price=45,filter=23.4955price=1000,filter=218.796price=1,filter=175.237price=2,filter=140.59price=2000,filter=512.472d:\user\01417804\桌面\CppProject\cppTest\x64\Debug\cppTest.exe(进程3732)已退出,代码为0(0x0)。 要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。 按任意键关闭此窗口...


需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询