In the article, I introduced DEMA and TEMA, but this time,
Comparison of exponential moving average (EMA) code written in Python
Similarly, let's compare several implementations, such as using scipy's lfilter, coding directly but speeding up with Numba.
Input data is a random walk of 100,000 samples.
import numpy as np
dn = np.random.randint(2, size=100000)*2-1
gwalk = np.cumprod(np.exp(dn*0.01))*100
Comparison of exponential moving average (EMA) code written in Python This is the fastest EMA code.
from numba import jit
@jit(nopython=True)
def EMA(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 y = EMA(gwalk, 0.15)
1000 loops, best of 3: 227 µs per loop
Use this to implement the DEMA formula as it is.
def DEMA1(x, period):
alpha = 2/(period+1)
ema = EMA(x, alpha)
ema2 = EMA(ema, alpha)
y = 2*ema-ema2
return y
%timeit y1 = DEMA1(gwalk, 14)
1000 loops, best of 3: 1.19 ms per loop
I've only used EMA twice, but it's about five times slower than EMA alone.
It is an implementation using scipy's lfilter function. The filter coefficient is
As requested in.
import scipy.signal as sp
def DEMA2(x, period):
alpha = 2/(period+1)
a = [1, 2*(alpha-1), (1-alpha)**2]
b = [alpha*(2-alpha), 2*alpha*(alpha-1)]
zi = sp.lfilter_zi(b, a)
y,zf = sp.lfilter(b, a, x, zi=zi*x[0])
return y
%timeit y2 = DEMA2(gwalk, 14)
1000 loops, best of 3: 717 µs per loop
It's a little faster.
@jit(nopython=True)
def DEMA3(x, period):
alpha = 2/(period+1)
a1 = 2*(alpha-1)
a2 = (1-alpha)**2
b0 = alpha*(2-alpha)
b1 = 2*alpha*(alpha-1)
y = np.empty_like(x)
y[0] = x[0]
y[1] = b0*x[1] + b1*x[0] - a1*y[0] - a2*y[0]
for i in range(2,len(x)):
y[i] = b0*x[i] + b1*x[i-1] - a1*y[i-1] - a2*y[i-2]
return y
%timeit y3 = DEMA3(gwalk, 14)
1000 loops, best of 3: 488 µs per loop
It's even faster, with direct implementation being the fastest. However, the difference is smaller than in EMA. What about the next TEMA?
First is the implementation using EMA.
def TEMA1(x, period):
alpha = 2/(period+1)
ema = EMA(x, alpha)
ema2 = EMA(ema, alpha)
ema3 = EMA(ema2, alpha)
y = 3*ema-3*ema2+ema3
return y
%timeit y1 = TEMA1(gwalk, 14)
100 loops, best of 3: 1.89 ms per loop
First of all, this is about.
def TEMA2(x, period):
alpha = 2/(period+1)
a = [1, 3*(alpha-1), 3*(1-alpha)**2, (alpha-1)**3]
b = [3*alpha*(1-alpha)+alpha**3, 3*alpha*(alpha-2)*(1-alpha), 3*alpha*(1-alpha)**2]
zi = sp.lfilter_zi(b, a)
y,zf = sp.lfilter(b, a, x, zi=zi*x[0])
return y
%timeit y2 = TEMA2(gwalk, 14)
1000 loops, best of 3: 718 µs per loop
The speed is almost the same as DEMA.
@jit(nopython=True)
def TEMA3(x, period):
alpha = 2/(period+1)
a1 = 3*(alpha-1)
a2 = 3*(1-alpha)**2
a3 = (alpha-1)**3
b0 = 3*alpha*(1-alpha)+alpha**3
b1 = 3*alpha*(alpha-2)*(1-alpha)
b2 = 3*alpha*(1-alpha)**2
y = np.empty_like(x)
y[0] = x[0]
y[1] = b0*x[1] + b1*x[0] + b2*x[0] - a1*y[0] - a2*y[0] - a3*y[0]
y[2] = b0*x[2] + b1*x[1] + b2*x[0] - a1*y[1] - a2*y[0] - a3*y[0]
for i in range(3,len(x)):
y[i] = b0*x[i] + b1*x[i-1] + b2*x[i-2] - a1*y[i-1] - a2*y[i-2] - a3*y[i-3]
return y
%timeit y3 = TEMA3(gwalk, 14)
1000 loops, best of 3: 604 µs per loop
In the case of TEMA as well, direct implementation kept the fastest. However, since the calculation time of lfilter does not change much even if the order increases, I think that it will be reversed when it becomes 4th or 5th order. Whether or not you need a higher order filter to analyze the market. .. ..
For the time being, DEMA and TEMA will implement directly using Numba. → GitHub
Recommended Posts