Ich habe versucht, Python-Code zu beschleunigen, einschließlich der if-Anweisung mit Numba und Cython

Einführung

Hinweise zur Beschleunigung des Python-Codes mit Numba Ich fand also heraus, dass Numba die technische Indexfunktion mithilfe der for-Anweisung effektiv beschleunigt, aber es gibt andere Indikatoren, die die if-Anweisung stark nutzen.

Eine davon ist Parabolic SAR. Dies ist kein besonders ungewöhnlicher Indikator, sondern sehr beliebt. Da jedoch der aufsteigende und der absteigende Modus umgeschaltet werden und sich die Schrittweite ändert, kann dies nicht allein durch die for-Anweisung beschrieben werden. Dies war das letzte Mal, dass wir die technischen Indikatoren von MetaTrader nach Python portiert haben.

Diese Zeit ist ein Memo, wenn Sie dies beschleunigen.

Parabolischer SAR-Python-Code

import numpy as np
import pandas as pd
dataM1 = pd.read_csv('DAT_ASCII_EURUSD_M1_2015.csv', sep=';',
                     names=('Time','Open','High','Low','Close', ''),
                     index_col='Time', parse_dates=True)

def iSAR(df, step, maximum):
    last_period = 0
    dir_long = True
    ACC = step
    SAR = df['Close'].copy()
    for i in range(1,len(df)):
        last_period += 1    
        if dir_long == True:
            Ep1 = df['High'][i-last_period:i].max()
            SAR[i] = SAR[i-1]+ACC*(Ep1-SAR[i-1])
            Ep0 = max([Ep1, df['High'][i]])
            if Ep0 > Ep1 and ACC+step <= maximum: ACC+=step
            if SAR[i] > df['Low'][i]:
                dir_long = False
                SAR[i] = Ep0
                last_period = 0
                ACC = step
        else:
            Ep1 = df['Low'][i-last_period:i].min()
            SAR[i] = SAR[i-1]+ACC*(Ep1-SAR[i-1])
            Ep0 = min([Ep1, df['Low'][i]])
            if Ep0 < Ep1 and ACC+step <= maximum: ACC+=step
            if SAR[i] < df['High'][i]:
                dir_long = True
                SAR[i] = Ep0
                last_period = 0
                ACC = step
    return SAR

%timeit y = iSAR(dataM1, 0.02, 0.2)

Die for-Anweisung ist einfach, dauert aber einige Zeit.

1 loop, best of 3: 1min 19s per loop

Beschleunigen Sie mit Numba

Lassen Sie uns zuerst mit Numba beschleunigen. Ändern Sie einfach das Pandas-Array in ein Numpy-Array und fügen Sie "@ jit" hinzu.

from numba import jit
@jit
def iSARjit(df, step, maximum):
    last_period = 0
    dir_long = True
    ACC = step
    SAR = df['Close'].values.copy()
    High = df['High'].values
    Low = df['Low'].values
    for i in range(1,len(SAR)):
        last_period += 1    
        if dir_long == True:
            Ep1 = High[i-last_period:i].max()
            SAR[i] = SAR[i-1]+ACC*(Ep1-SAR[i-1])
            Ep0 = max([Ep1, High[i]])
            if Ep0 > Ep1 and ACC+step <= maximum: ACC+=step
            if SAR[i] > Low[i]:
                dir_long = False
                SAR[i] = Ep0
                last_period = 0
                ACC = step
        else:
            Ep1 = Low[i-last_period:i].min()
            SAR[i] = SAR[i-1]+ACC*(Ep1-SAR[i-1])
            Ep0 = min([Ep1, Low[i]])
            if Ep0 < Ep1 and ACC+step <= maximum: ACC+=step
            if SAR[i] < High[i]:
                dir_long = True
                SAR[i] = Ep0
                last_period = 0
                ACC = step
    return SAR

%timeit y = iSARjit(dataM1, 0.02, 0.2)
1 loop, best of 3: 1.43 s per loop

Es ist ungefähr 55 mal schneller. Es gibt nur wenige Codekorrekturen, daher ist das Ergebnis ziemlich gut.

Beschleunigen Sie mit Cython

Versuchen Sie als nächstes, mit Cython zu beschleunigen. Ich dachte, Cython sei mühsam einzurichten, aber mit dem Jupyter-Notebook war die Installation ziemlich einfach. Da jedoch ein externer Compiler verwendet wird, müssen Sie Visual C ++ installieren. Ich musste mit der von mir erstellten Version von Anaconda übereinstimmen, also habe ich diesmal den folgenden Compiler installiert.

Visual Studio Community 2015

Das erste ist, wenn Sie Cython nur einstellen, ohne den Code zu ändern.

%load_ext Cython
%%cython
cimport numpy
cimport cython
def iSAR_c0(df, step, maximum):
    last_period = 0
    dir_long = True
    ACC = step
    SAR = df['Close'].values.copy()
    High = df['High'].values
    Low = df['Low'].values
    for i in range(1,len(SAR)):
        last_period += 1    
        if dir_long == True:
            Ep1 = High[i-last_period:i].max()
            SAR[i] = SAR[i-1]+ACC*(Ep1-SAR[i-1])
            Ep0 = max([Ep1, High[i]])
            if Ep0 > Ep1 and ACC+step <= maximum: ACC+=step
            if SAR[i] > Low[i]:
                dir_long = False
                SAR[i] = Ep0
                last_period = 0
                ACC = step
        else:
            Ep1 = Low[i-last_period:i].min()
            SAR[i] = SAR[i-1]+ACC*(Ep1-SAR[i-1])
            Ep0 = min([Ep1, Low[i]])
            if Ep0 < Ep1 and ACC+step <= maximum: ACC+=step
            if SAR[i] < High[i]:
                dir_long = True
                SAR[i] = Ep0
                last_period = 0
                ACC = step
    return SAR
%timeit y = iSAR_c0(dataM1, 0.02, 0.2)

Ergebnis

1 loop, best of 3: 1.07 s per loop

Cython ist mit dem gleichen Code etwas schneller.

Als nächstes beim Hinzufügen der Variablentypdeklaration mit cdef.

%%cython
cimport numpy
cimport cython
def iSARnew(df, double step, double maximum):
    cdef int last_period = 0
    dir_long = True
    cdef double ACC = step
    cdef numpy.ndarray[numpy.float64_t, ndim=1] SAR = df['Close'].values.copy()
    cdef numpy.ndarray[numpy.float64_t, ndim=1] High = df['High'].values
    cdef numpy.ndarray[numpy.float64_t, ndim=1] Low = df['Low'].values
    cdef double Ep0, Ep1
    cdef int i, N=len(SAR)
    for i in range(1,N):
        last_period += 1    
        if dir_long == True:
            Ep1 = max(High[i-last_period:i])
            SAR[i] = SAR[i-1]+ACC*(Ep1-SAR[i-1])
            Ep0 = max([Ep1, High[i]])
            if Ep0 > Ep1 and ACC+step <= maximum: ACC+=step
            if SAR[i] > Low[i]:
                dir_long = False
                SAR[i] = Ep0
                last_period = 0
                ACC = step
        else:
            Ep1 = min(Low[i-last_period:i])
            SAR[i] = SAR[i-1]+ACC*(Ep1-SAR[i-1])
            Ep0 = min([Ep1, Low[i]])
            if Ep0 < Ep1 and ACC+step <= maximum: ACC+=step
            if SAR[i] < High[i]:
                dir_long = True
                SAR[i] = Ep0
                last_period = 0
                ACC = step
    return SAR
%timeit y = iSARnew(dataM1, 0.02, 0.2)

Ergebnis ist

1 loop, best of 3: 533 ms per loop

war. Es ist ungefähr doppelt so schnell. Es kann schneller sein, wenn Sie es optimieren, aber es kann Ihren Code weniger lesbar machen, also ist es das.

Zusammenfassung

Nur bei der for-Anweisung beschleunigt Numba ebenfalls erheblich, aber wenn die if-Anweisung ebenfalls enthalten ist, nimmt der Effekt ab. Wenn Sie es etwas schneller machen möchten, können Sie Cython mit einigen Codeänderungen verwenden.

Recommended Posts

Ich habe versucht, Python-Code zu beschleunigen, einschließlich der if-Anweisung mit Numba und Cython
Hinweise zur Beschleunigung des Python-Codes mit Numba
Ich habe Numba mit Python3.5 installiert und verwendet
Ich habe Jacobian und teilweise Differenzierung mit Python versucht
Ich habe Funktionssynthese und Curry mit Python versucht
Laden / Anzeigen und Beschleunigen von GIF mit Python [OpenCV]
Ich habe fp-Wachstum mit Python versucht
Ich habe versucht, mit Python zu kratzen
Ich habe gRPC mit Python ausprobiert
Ich habe versucht, mit Python zu kratzen
Ich habe versucht, Follow Management mit Twitter API und Python (einfach)
Ich habe versucht, die Benutzeroberfläche neben Python und Tkinter dreiäugig zu gestalten
Beschleunigen Sie Python mit numba grob
Ich habe mit PyQt5 und Python3 gespielt
Ich habe versucht, Prolog mit Python 3.8.2 auszuführen.
Ich habe die SMTP-Kommunikation mit Python versucht
Ich habe versucht, mit Selenium und Python einen regelmäßigen Ausführungsprozess durchzuführen
Ich habe versucht herauszufinden, ob ReDoS mit Python möglich ist
Ich habe versucht, Gesichtsmarkierungen mit Python und Dlib leicht zu erkennen
Mayungos Python Learning Episode 7: Ich habe versucht, mit if, elif, else zu drucken
Was tun, wenn ipython und python mit unterschiedlichen Versionen starten?
Ich habe versucht, mit Python + opencv nicht realistisch zu rendern
Ich habe versucht, den Authentifizierungscode der Qiita-API mit Python abzurufen.
Ich habe eine funktionale Sprache mit Python ausprobiert
Ich habe versucht, mit Python ② (Fibonacci-Zahlenfolge) aufzuklären.
Ich habe versucht, die Beschleunigung von Python durch Cython zu verifizieren und zu analysieren
Ich habe versucht, den Google-Kalender mit CSV-Terminen mithilfe von Python und Google API zu aktualisieren
# Ich habe so etwas wie Vlookup mit Python # 2 ausprobiert
Ich habe versucht, das Bild mit Python + OpenCV zu "glätten"
Ich habe Hunderte Millionen SQLite mit Python ausprobiert
Ich habe versucht, Web-Scraping mit Python und Selen
Ich habe versucht, das Bild mit Python + OpenCV zu "differenzieren"
Ich habe versucht, Objekte mit Python und OpenCV zu erkennen
Ich habe Flask mit Remote-Containern von VS Code ausprobiert
Ich habe L-Chika mit Razpai 4 (Python Edition) ausprobiert.
Ich habe versucht, mit PartiQL und MongoDB verbunden zu spielen
Ich habe versucht, CloudWatch-Daten mit Python abzurufen
Ich habe versucht, Mecab mit Python2.7, Ruby2.3, PHP7 zu verwenden
Ich habe versucht, LLVM IR mit Python auszugeben
Ich habe versucht, das Bild mit Python + OpenCV zu "binarisieren"
Ich habe versucht, mit Python Faiss zu laufen, Go, Rust
Ich habe versucht, die Herstellung von Sushi mit Python zu automatisieren
Ich habe versucht, Deep Floor Plan mit Python 3.6.10 auszuführen.
Ich habe versucht, eine E-Mail mit SendGrid + Python zu senden
Ich habe versucht, das Artikel-Update des Livedoor-Blogs mit Python und Selen zu automatisieren.
Ich habe mit Python verschiedene Dinge ausprobiert: Schaben (Beautiful Soup + Selenium + PhantomJS) und morphologische Analyse
Bildverarbeitung mit Python (ich habe versucht, es in 0 und 1 Mosaikkunst zu binarisieren)
Ich habe versucht, die Verarbeitungsgeschwindigkeit mit dplyr von R und pandas von Python zu vergleichen
Ich habe versucht, mit VOICEROID2 2 automatisch zu lesen und zu speichern
Ich habe pipenv und asdf für die Python-Versionskontrolle ausprobiert
Ich möchte die Optimierung mit Python und CPlex behandeln
Ich habe versucht, Mine Sweeper auf dem Terminal mit Python zu implementieren
Ich habe versucht, mit Blenders Python script_Part 01 zu beginnen
Ich habe versucht, eine CSV-Datei mit Python zu berühren