在Python中,通过重用以前的计算来计算EMA的更快方法是什么?

问题描述 投票:2回答:2

我一直在使用TA-Lib计算EMA,但是每次我向阵列添加新数字时,TA-Lib都会从头开始执行计算。

我正在对相当大的一组数据(> 1M行)进行分析,这很慢。

添加新值后计算新EMA的最快方法是什么?

python moving-average ta-lib
2个回答
1
投票

x为包含样本的长度为n的向量,即x[0],...,x[n-1]。令y为包含EMA的向量。然后,y由等式给出:

y[k] = y[k-1] * a + x[k] * (1-a)

a是EMA参数,在0到1之间。越接近1,曲线越平滑。

因此,您只需要计算EMA:

a = 0.9
y[0] = x[0]
for k in range(1, n):
    y[k] = y[k-1]*a + x[k]*(1-a)

然后,如果您获得另一个样本,即x[n],则可以使用以下方法进行EMA y[n]的计算,而无需进行完整的计算:

y[n] = y[n-1]*a + x[n]*(1-a)

这是伪代码,因此,如果使用列表,它应该是这样的:

y.append(y[-1]*a + x[-1]*(1-a))

编辑:

[如果您真的想提高EMA(一次整个EMA)的计算速度,则可以使用numba和numpy:

import numpy as np
from numba import njit
from timeit import timeit

n=1000000
x_np = np.random.randn(n) # your data
x_list = list(x_np)
a = 0.9

def ema_list(x, a):
     y = [x[0]]
     for k in range(1, n):
          y.append(y[-1]*a + x[k]*(1-a))
     return y


@njit("float64[:](float64[:], float64)")
def ema_np(x, a):
     y = np.empty_like(x)
     y[0] = x[0]
     for k in range(1, n):
          y[k] = y[k-1]*a + x[k]*(1-a)
     return y


print(timeit(lambda: ema_list(x_list, a), number=1)) # 0.7080 seconds
print(timeit(lambda: ema_np(x_np, a), number=1)) # 0.008015 seconds

列表实现大约需要708毫秒,而numba和numpy则需要8毫秒,这大约快了88倍。没有numba的numpy实现与列表实现花费的时间相似。


0
投票

TA-Lib有一个名为TA-Lib RT的分支,可用于实时出现的数据,而无需重新计算整个数据集。

https://github.com/trufanov-nok/ta-lib-rt

它包含TA函数的其他变体,这些变体旨在循环工作,并在每次调用时处理单个数据值而不是数组。这些函数接受state参数以保持调用之间的内部状态。

不幸的是,它还没有python绑定。我目前正在尝试通过分叉原始TA-Lib python绑定进行这种绑定。

© www.soinside.com 2019 - 2024. All rights reserved.