我一直在使用TA-Lib计算EMA,但是每次我向阵列添加新数字时,TA-Lib都会从头开始执行计算。
我正在对相当大的一组数据(> 1M行)进行分析,这很慢。
添加新值后计算新EMA的最快方法是什么?
让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实现与列表实现花费的时间相似。
TA-Lib
有一个名为TA-Lib RT
的分支,可用于实时出现的数据,而无需重新计算整个数据集。
https://github.com/trufanov-nok/ta-lib-rt
它包含TA函数的其他变体,这些变体旨在循环工作,并在每次调用时处理单个数据值而不是数组。这些函数接受state
参数以保持调用之间的内部状态。
不幸的是,它还没有python绑定。我目前正在尝试通过分叉原始TA-Lib python绑定进行这种绑定。