Die grundlegendsten gleitenden Durchschnitte technischer Indikatoren, von denen der einfache gleitende Durchschnitt (SMA) nur ein Durchschnitt ist, der jedoch zur Berechnung vieler anderer technischer Indikatoren als SMA verwendet wird. Tatsächlich verwenden 40% der rund 30 auf GitHub veröffentlichten technischen Indikatoren SMA.
Dieses Mal möchte ich mich auf diese SMA spezialisieren und Python-Code vergleichen.
Da wir den Satz von Python-Paketen aktualisiert haben, lauten die Versionen von Python und die verwendeten Pakete wie folgt.
Als allererstes Zufälliger Spaziergang in Python Machen Sie einen zufälligen Spaziergang von 100.000 Proben, indem Sie sich auf beziehen. Dies sind die Eingabedaten für 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
Die einfachste Implementierung von SMA ist mit Pandas. Es kann einfach mit den Serienmethoden Rolling und Mean geschrieben werden.
def SMA1(x, period):
return pd.Series(x).rolling(period).mean()
Geben Sie als allgemeine Spezifikation die Eingabezeitreihen und die SMA-Periode in das Argument ein. Da Vergleiche nach der Differenz der Periode durchgeführt werden, messen Sie bei Periode = 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
Bei Pandas scheint es je nach Zeitraum keinen Unterschied in der Ausführungsgeschwindigkeit zu geben.
Vergleich der Berechnungszeit des in Python geschriebenen gleitenden Durchschnitts Lassen Sie es uns mit der Filterfunktion lfilter von scipy implementieren.
from scipy.signal import lfilter
def SMA2(x, period):
return lfilter(np.ones(period), 1, x)/period
Lassen Sie uns die Ausführungszeit auf die gleiche Weise messen.
%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
Da lfilter eine universelle Filterfunktion ist, die nicht für SMA vorgesehen ist, scheint sich die Ausführungszeit je nach Zeitraum zu ändern. Kürzere Perioden sind schneller als Pandas, aber längere Perioden sind langsamer.
Schreiben wir die SMA-Berechnungsformel direkt mit der for-Anweisung. Natürlich ist es offensichtlich, dass es langsam sein wird, wenn es so bleibt, wie es ist. Verwenden Sie, wie der Titel sagt, numba, um es zu beschleunigen.
@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
Ich verwende die for-Anweisung, aber wenn der Zeitraum aufgrund der Beschleunigung von numba 20 beträgt, ist er der bisher schnellste. Da es jedoch proportional zur Periode ist, ist es bei 200 zehnmal langsamer und am langsamsten.
Die endgültige Implementierung ist eine Methode, die die Eigenschaften von SMA nutzt. Da SMA einfach Stichproben hinzufügt, wird nur berechnet, indem der alte Stichprobenwert subtrahiert und der neue Stichprobenwert unter Verwendung des Berechnungsergebnisses einer Stichprobe zuvor addiert wird.
@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
Wir werden die Proben hinzufügen, bis die Proben für den Zeitraum bereit sind, aber danach müssen wir nur noch drei Daten hinzufügen. Die Ausführungsgeschwindigkeit ist wie folgt.
%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
Es hat das schnellste Ergebnis aller bisherigen Implementierungen. Das Ergebnis war fast das gleiche, auch wenn der Zeitraum verlängert wurde.
Wie oben erwähnt, wurde unter der Annahme der Beschleunigung durch numba festgestellt, dass die Geschwindigkeit von SMA ziemlich hoch ist, selbst wenn die for-Anweisung verwendet wird.
Recommended Posts