用Python编写的指数移动平均(EMA)代码的比较


在移动平均线中,除简单移动平均线(SMA)之后最常用的一种是指数移动平均线(EMA)。除了作为使用EMA的技术指标而闻名的MACD之外,还有多次多次使用EMA的DEMA,TEMA和TriX,而自适应移动平均线(例如AMA,FrAMA和VIDyA)使用EMA作为计算方法。我会。

这次,
我将IIR滤波器类型的移动平均值与pandas和Scipy进行了比较
作为后续,让我们比较一些EMA代码。

EMA公式

实际使用EMA时,将句点作为参数输入,但是在这里,该公式直接用于检查EMA本身的性能。

$$ y(n)= \\ alpha x(n)(1- \\ alpha)y(n-1)$$

即,上式中EMA的参数为$ \\ alpha $。

pandas实施

首先,输入数据要乘以EMA
关于假定使用Numba的简单移动平均值的Python代码
也将其作为随机行走。

1
2
3
4
5
import numpy as np
import pandas as pd

dn = np.random.randint(2, size=100000)*2-1
gwalk = np.cumprod(np.exp(dn*0.01))*100

使用

pandas,您可以轻松地转换为Series类并使用ewmmean方法运行EMA。您也可以直接将alpha分配为ewm的参数。 alpha的范围是0到1,并且没有特别的差异,因此请在此输入0.15。

1
2
3
4
def EMA1(x, alpha):
    return pd.Series(x).ewm(alpha=alpha).mean()

%timeit y1 = EMA1(gwalk, 0.15)

执行时间如下。

1
100 loops, best of 3: 8.62 ms per loop

用lflter实现scipy

我将IIR滤波器类型的移动平均值与pandas和scipy进行了比较
它是使用scipy的filter函数lfilter的一种实现方式。

1
2
3
4
5
6
from scipy.signal import lfilter
def EMA2(x, alpha):
    y,zf = lfilter([alpha], [1,alpha-1], x, zi=[x[0]*(1-alpha)])
    return y

%timeit y2 = EMA2(gwalk, 0.15)

执行时间如下。

1
1000 loops, best of 3: 631 μs per loop

这是上一篇文章的结尾,据说scipy很快,但是这次是续篇。

使用Numba直接执行公式

直接编写EMA公式。但是,如果按原样放置,它将非常慢,因此请使用Numba加快速度。

1
2
3
4
5
6
7
8
9
10
from numba import jit
@jit(nopython=True)
def EMA3(x, alpha):
    y = np.empty_like(x)
    y[0] = x[0]
    for i in range(1,len(x)):
        y[i] = alpha*x[i] + (1-alpha)*y[i-1]
    return y

%timeit y3 = EMA3(gwalk, 0.15)

如果将nopython=True添加到

@jit的参数,并且没有错误发生,则可以预期会加速。实际上,执行时间是

1
1000 loops, best of 3: 227 μs per loop

它变为

,比scipy更快。

对于

EMA,结果是使用Numba进行直接编码最快。