Les moyennes mobiles les plus élémentaires des indicateurs techniques, dont la moyenne mobile simple (SMA) n'est qu'une moyenne, mais elle est utilisée pour calculer de nombreux indicateurs techniques autres que la SMA. En effet, sur la trentaine d'indicateurs techniques affichés sur GitHub, 40% utilisent SMA.
Cette fois, j'aimerais me spécialiser dans ce SMA et comparer du code Python.
Depuis que nous avons mis à jour l'ensemble des packages Python, les versions de Python et les packages utilisés sont les suivants.
Tout d'abord Random walk in Python Faites une promenade aléatoire de 100 000 échantillons en vous référant à. Ce seront les données d'entrée pour SMA.
import numpy as np
import pandas as pd
from numba import jit
dn = np.random.randint(2, size=100000)*2-1
gwalk = np.cumprod(np.exp(dn*0.01))*100
L'implémentation la plus simple de SMA est avec les pandas. Il peut être facilement écrit en utilisant les méthodes de série Rolling and Mean.
def SMA1(x, period):
return pd.Series(x).rolling(period).mean()
Comme spécification courante, entrez la série chronologique d'entrée et la période SMA dans l'argument. Puisque les comparaisons seront faites en fonction de la différence de période, mesurez à période = 20 200.
%timeit y1_20 = SMA1(gwalk, 20)
%timeit y1_200 = SMA1(gwalk, 200)
100 loops, best of 3: 6.02 ms per loop
100 loops, best of 3: 6.01 ms per loop
Dans le cas des pandas, il semble n'y avoir aucune différence de vitesse d'exécution selon la période.
Comparé le temps de calcul de la moyenne mobile écrite en Python Implémentons-le en utilisant la fonction de filtre de scipy lfilter, en référence à.
from scipy.signal import lfilter
def SMA2(x, period):
return lfilter(np.ones(period), 1, x)/period
Mesurons le temps d'exécution de la même manière.
%timeit y2_20 = SMA2(gwalk, 20)
%timeit y2_200 = SMA2(gwalk, 200)
100 loops, best of 3: 5.53 ms per loop
100 loops, best of 3: 10.4 ms per loop
Puisque lfilter est une fonction de filtre à usage général, non dédiée à SMA, le temps d'exécution semble changer en fonction de la période. Les périodes plus courtes sont plus rapides que les pandas, mais les périodes plus longues sont plus lentes.
Écrivons la formule de calcul SMA directement en utilisant l'instruction for. Bien sûr, il est évident qu'il sera lent s'il est laissé tel quel, alors comme le titre l'indique, utilisez numba pour l'accélérer.
@jit
def SMA3(x, period):
y = np.zeros(len(x))
for i in range(len(y)):
for j in range(period):
y[i] += x[i-j]
return y/period
%timeit y3_20 = SMA3(gwalk, 20)
%timeit y3_200 = SMA3(gwalk, 200)
100 loops, best of 3: 3.07 ms per loop
10 loops, best of 3: 32.3 ms per loop
J'utilise l'instruction for, mais si la période est de 20 en raison de l'effet d'accélération de numba, c'est la plus rapide à ce jour. Cependant, comme elle est proportionnelle à la période, si elle est de 200, elle sera 10 fois plus lente, et ce sera la plus lente.
La mise en œuvre finale est une méthode qui tire parti des caractéristiques du SMA. Puisque SMA ajoute simplement des échantillons, il ne calcule qu'en soustrayant l'ancienne valeur d'échantillon et en ajoutant la nouvelle valeur d'échantillon en utilisant le résultat du calcul d'un échantillon antérieur.
@jit
def SMA4(x, period):
y = np.empty(len(x))
y[:period-1] = np.nan
y[period-1] = np.sum(x[:period])
for i in range(period, len(x)):
y[i] = y[i-1]+x[i]-x[i-period]
return y/period
Nous ajouterons les échantillons jusqu'à ce que les échantillons soient prêts pour la période, mais après cela, nous ne devons ajouter que trois données. La vitesse d'exécution est la suivante.
%timeit y4_20 = SMA4(gwalk, 20)
%timeit y4_200 = SMA4(gwalk, 200)
1 loop, best of 3: 727 µs per loop
1000 loops, best of 3: 780 µs per loop
Il a le résultat le plus rapide de toute implémentation à ce jour. Le résultat était presque le même même si la période était prolongée.
Comme mentionné ci-dessus, en supposant l'accélération par numba, il a été constaté que la vitesse de SMA est assez élevée même si l'instruction for est utilisée.
Recommended Posts