Backtesting von FX Systre mit Python Wie ich in dem Artikel erwähnt habe, hat nur die parabolische SAR (iSAR) -Funktion unter den auf GitHub veröffentlichten technischen Indikatoren lange gedauert. Ich habe mich gefragt, ob es helfen könnte, weil der Algorithmus kompliziert ist, aber es stellte sich heraus, dass es tatsächlich ein Problem gab, wie man die Maximal- und Minimalwerte findet.
In diesem Artikel werde ich Beispielcode verwenden, um die Probleme zusammenzufassen.
Betrachten Sie das Problem, 3 Proben gleichzeitig aus geeigneten Zeitreihendaten zu extrahieren und den Maximalwert nacheinander zu ermitteln. Es sieht so aus, wenn es in einer Formel geschrieben ist.
Erstellen Sie die Zeitreihendaten wie folgt als Zufallszahlenfolge.
import numpy as np
x = np.random.randint(1000, size=100000)
Ich werde 4 Arten von Codes ausprobieren, die den Maximalwert von 3 Stichproben als Zeitreihe berechnen. func1 Machen Sie den Code so wie er ist. Übergeben Sie "x [i], x [i-1], x [i-2]" als Argumente an die in Python integrierte Funktion "max".
def func1(x):
y = np.empty(len(x), dtype=int)
for i in range(2,len(x)):
y[i] = max(x[i], x[i-1], x[i-2])
return y
func2 Verwenden Sie ein wenig wie Python Slices und übergeben Sie sie an das Argument "max".
def func2(x):
y = np.zeros(len(x), dtype=int)
for i in range(2,len(x)):
y[i] = max(x[i-2:i+1])
return y
func3 Da numpy auch eine "max" -Funktion hat, versuchen Sie, "np.max" anstelle von "max" zu verwenden.
def func3(x):
y = np.zeros(len(x), dtype=int)
for i in range(2,len(x)):
y[i] = np.max(x[i-2:i+1])
return y
func4 Listen wir die drei Elemente "x [i], x [i-1], x [i-2]" auf und übergeben sie an das Argument "np.max".
def func4(x):
y = np.zeros(len(x), dtype=int)
for i in range(2,len(x)):
y[i] = np.max([x[i], x[i-1], x[i-2]])
return y
Vergleichen wir die Ausführungszeiten der oben genannten vier Funktionen.
%timeit y1 = func1(x)
%timeit y2 = func2(x)
%timeit y3 = func3(x)
%timeit y4 = func4(x)
10 loops, best of 3: 91.6 ms per loop
1 loop, best of 3: 304 ms per loop
1 loop, best of 3: 581 ms per loop
1 loop, best of 3: 1.29 s per loop
func1 ist am schnellsten, func2, func3, func4 und so weiter. func4 dauert 14 mal länger als func1.
Vergleichen wir mit demselben Code die Beschleunigung nach numba.
from numba import jit
@jit
def func1(x):
y = np.zeros(len(x), dtype=int)
for i in range(2,len(x)):
y[i] = max(x[i], x[i-1], x[i-2])
return y
@jit
def func2(x):
y = np.zeros(len(x), dtype=int)
for i in range(2,len(x)):
y[i] = max(x[i-2:i+1])
return y
@jit
def func3(x):
y = np.zeros(len(x), dtype=int)
for i in range(2,len(x)):
y[i] = np.max(x[i-2:i+1])
return y
@jit
def func4(x):
y = np.zeros(len(x), dtype=int)
for i in range(2,len(x)):
y[i] = np.max([x[i], x[i-1], x[i-2]])
return y
%timeit y1 = func1(x)
%timeit y2 = func2(x)
%timeit y3 = func3(x)
%timeit y4 = func4(x)
1000 loops, best of 3: 365 µs per loop
1 loop, best of 3: 377 ms per loop
100 loops, best of 3: 4.33 ms per loop
1 loop, best of 3: 1.36 s per loop
Wenn Sie auf die Zeiteinheit achten und vergleichen, ist func1 µs, also überwältigend schneller. Der nächstschnellste ist func3. Sie können den Effekt der Beschleunigung durch numba deutlich sehen. Im Vergleich dazu sind func2 und func4 langsamer als der Effekt von numba.
Infolgedessen ist der Unterschied zwischen func4 und func1 3700-mal größer. Schließlich stellte sich beim Ermitteln des Maximalwerts mit einer kleinen Anzahl von Elementen heraus, dass es am schnellsten ist, jedes Element einzeln an die integrierte Funktion "max" zu übergeben.
Tatsächlich ist im amax des numpy-Dokuments "Maximum (a [0], a") [1]) ist schneller als ein Maximum (a, Achse = 0). ", Ein solcher Kommentar wurde geschrieben.
Zurück zur Geschichte: Der Grund, warum iSAR langsam war, war, dass es wie func4 geschrieben wurde. Als ich es wie func1 schrieb, wurde es dramatisch schneller. Aufgrund der Wirkung von Numba ist der bisher langsamste technische Index zu einem der schnelleren technischen Indikatoren geworden.
Ich weiß nicht genau, wo Python einen Engpass hat.
Recommended Posts