Backtesting FX System avec Python Comme je l'ai mentionné dans l'article, seule la fonction SAR parabolique (iSAR) a pris du temps parmi les indicateurs techniques publiés sur GitHub. Je me demandais si cela pouvait être aidé car l'algorithme est compliqué, mais il s'est avéré qu'il y avait en fait un problème pour trouver les valeurs maximales et minimales.
Dans cet article, j'utiliserai un exemple de code pour résumer les problèmes.
Considérez le problème de l'extraction de 3 échantillons à la fois à partir de données chronologiques appropriées et de la recherche séquentielle de la valeur maximale. Cela ressemble à ceci lorsqu'il est écrit dans une formule.
Créez les données de série chronologique sous forme de séquence de nombres aléatoires comme suit.
import numpy as np
x = np.random.randint(1000, size=100000)
Essayons 4 types de codes qui calculent la valeur maximale de 3 échantillons sous forme de série chronologique.
func1
Faites le code tel qu'il est. Passez x [i], x [i-1], x [i-2]
comme arguments à la fonction intégrée de Python 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
Un peu comme Python, utilisez des tranches et passez-les à l'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
Puisque numpy a également une fonction max
, essayez d'utiliser np.max
au lieu de max
.
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
Listons les trois éléments x [i], x [i-1], x [i-2]
et passons-les à l'argument de 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
%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
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
func1 est le plus rapide, func2, func3, func4 et ainsi de suite. func4 prend 14 fois plus de temps que func1. Accélération par numba Comparons l'accélération par numba avec le même code. Si vous faites attention à l'unité de temps et comparez, func1 est µs, donc il est extrêmement plus rapide. Le prochain plus rapide est func3. Vous pouvez clairement voir l'effet de l'accélération par numba. En comparaison, func2 et func4 sont plus lents que l'effet de numba. En conséquence, la différence entre func4 et func1 est 3700 fois plus grande. Après tout, lors de la recherche de la valeur maximale avec un petit nombre d'éléments, il s'est avéré que passer chaque élément individuellement à la fonction intégrée «max» est le plus rapide. En fait, dans le amax du document numpy, "maximum (a [0], a [1]) est plus rapide qu'un max (a, axis = 0). ", Un commentaire comme celui-là a été écrit.
Pour en revenir à l'histoire, la raison pour laquelle iSAR était lent était qu'il était écrit comme func4. Quand je l'ai écrit comme func1, il est devenu considérablement plus rapide. En raison de l'effet de numba, l'indice technique le plus lent à ce jour est devenu l'un des indicateurs techniques les plus rapides.
Je ne sais pas vraiment où Python a un goulot d'étranglement.
Recommended Posts