[PYTHON] Ich habe den gleitenden Durchschnitt des IIR-Filtertyps mit Pandas und Scipy verglichen

Vorausgesetzte Artikel

Vergleich der Berechnungszeit des in Python geschriebenen gleitenden Durchschnitts

Es kommt nicht in Frage, die for-Anweisung in Python zu verwenden, um den gleitenden Durchschnitt zu berechnen, und das Ergebnis ist, dass es besser ist, die Pandas- und Scipy-Funktionen zu verwenden. Im obigen Artikel war es jedoch ein gleitender Durchschnitt des FIR-Filtertyps wie SMA und LWMA, daher habe ich diesmal den gleitenden Durchschnitt des IIR-Filtertyps wie EMA und SMMA untersucht.

EMA EMA ist eine Abkürzung für Exponential Moving Average und wird durch die folgende Formel ausgedrückt.

y(n)=\alpha x(n)+(1-\alpha)y(n-1)

Wobei $ \ alpha $ ein realer Parameter von 0 bis 1 ist. Diese Formel enthält keinen Parameter, der die Periode darstellt. Da SMA und LWMA jedoch Parameter verwenden, die die Periode darstellen, verwendet EMA den Periodenparameter häufig entsprechend. Unter der Annahme, dass der Zeitraum $ p $ beträgt, beträgt EMA $ \ alpha = 2 / (p + 1) $ und SMMA $ \ alpha = 1 / p $. Persönlich halte ich es nicht für notwendig, zwischen EMA und SMMA zu unterscheiden, da sie dieselbe Formel haben, aber ich werde sie erwähnen, weil sie in MetaTrader separat verwendet werden.

Implementiert mit Pandas

Lassen Sie es uns zuerst mit Pandas implementieren. Die zu verarbeitenden Daten sind die gleichen wie im vorherigen Artikel. Es ist eine vierwertige Zeitreihe von etwa 370.000 Stück. Da Pandas für Zeitreihendaten bestimmt ist, kann EMA auch einfach mit den Funktionen "ewm ()" und "mean ()" geschrieben werden.

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 EMA(s, ma_period):
    return s.ewm(span=ma_period).mean()

%timeit MA = EMA(dataM1['Close'], 10)

Da auch diesmal die Ausführungszeit verglichen wird, werden die Messergebnisse angezeigt.

10 loops, best of 3: 32.2 ms per loop

Im Fall von SMA waren es ungefähr 16 Millisekunden, also ungefähr doppelt so langsam.

Eine kleine Konvertierung vor der Implementierung mit scipy

Wenn Sie "lfilter ()" von scipy verwenden, reicht es nicht aus, nur $ \ alpha $ einzugeben. Sie müssen zum IIR-Filterformat wechseln und den Koeffizienten eingeben. Also werde ich es ein wenig konvertieren. (Eine detaillierte Theorie wird weggelassen. Sie ist die Grundlage der digitalen Signalverarbeitung.)

Konvertieren Sie beide Seiten des EMA-Ausdrucks in $ z $.

Y(z)=\alpha X(z)+(1-\alpha)z^{-1}Y(z)

Wenn Sie $ Y (z) $ auf die linke Seite setzen

\\{1-(1-\alpha)z^{-1}\\}Y(z)=\alpha X(z)

Und wenn $ Y (z) / X (z) $ $ H (z) $ ist,

H(z)=\frac{\alpha}{1-(1-\alpha)z^{-1}}

Kann geschrieben werden. Dies ist die Systemfunktion des IIR-Filters. Das Argument von "lfilter ()" zu übergeben, ist der Koeffizient des molekularen Polynoms und der Koeffizient des Nennerpolynoms dieser Systemfunktion.

Im Fall von EMA ist das Molekül der Systemfunktion eine Konstante und der Nenner ein Polynom erster Ordnung, so dass die allgemeine Formel der Systemfunktion wie folgt geschrieben werden kann.

H(z)=\frac{b_0}{a_0+a_1z^{-1}}

Wenn Sie die Koeffizienten vergleichen, sehen Sie, dass die Koeffizienten von $ b $ und $ a $ wie folgt sind.

b_0=\alpha, \ a_0=1, \ a_1=\alpha-1

Implementiert mit scipy

Wenn Sie also EMA mit scipys lflter () implementieren, können Sie wie folgt schreiben. Setzen Sie die obigen $ b $ und $ a $ in Form einer Liste.

from scipy.signal import lfilter
def EMAnew(s, ma_period):
    alpha = 2/(ma_period+1)
    y = lfilter([alpha], [1,alpha-1], s)
    return pd.Series(y, index=s.index)

%timeit MA = EMAnew(dataM1['Close'], 10)

Ergebnis ist

100 loops, best of 3: 3.08 ms per loop

Es wurde fast die gleiche Geschwindigkeit wie im Fall von SMA. Immerhin ist lfilter () schnell.

Anpassen der Anfangsbedingungen von lfilter ()

Das Ergebnis ist, dass lfilter () auch diesmal schnell ist, aber es gibt ein kleines Problem mit dem Verarbeitungsergebnis.

In EMA wird bei der Berechnung der ersten Ausgabe $ y (0) $ $ y (-1) $ ohne Daten verwendet, bei Pandas jedoch für Zeitreihendaten, also $ y Es wird so verarbeitet, dass $ y (-1) $ nicht als (0) = x (0) $ verwendet wird.

pd.DataFrame({'Close':dataM1['Close'],'EMA':MA}).head(10)
Close EMA
Time
2015-01-01 13:00:00 1.20962 1.209620
2015-01-01 13:01:00 1.20962 1.209620
2015-01-01 13:02:00 1.20961 1.209616
2015-01-01 13:04:00 1.20983 1.209686
2015-01-01 13:05:00 1.20988 1.209742
2015-01-01 13:06:00 1.20982 1.209762
2015-01-01 13:07:00 1.20987 1.209788
2015-01-01 13:08:00 1.21008 1.209855
2015-01-01 13:09:00 1.20996 1.209878
2015-01-01 13:10:00 1.20977 1.209855

In diesem Fall unterscheidet sich das Ergebnis von EMA nicht so sehr von der Eingabezeitreihe, aber im Fall von "lfilter ()" wird es als $ y (-1) = 0 $ berechnet, also die erste EMA Der Wert von wird erheblich von der Eingabe abweichen.

Close EMA
Time
2015-01-01 13:00:00 1.20962 0.219931
2015-01-01 13:01:00 1.20962 0.399874
2015-01-01 13:02:00 1.20961 0.547099
2015-01-01 13:04:00 1.20983 0.667596
2015-01-01 13:05:00 1.20988 0.766193
2015-01-01 13:06:00 1.20982 0.846852
2015-01-01 13:07:00 1.20987 0.912855
2015-01-01 13:08:00 1.21008 0.966896
2015-01-01 13:09:00 1.20996 1.011090
2015-01-01 13:10:00 1.20977 1.047213

Es scheint, dass dieses Problem mit dem optionalen Argument "lfilter ()" gelöst werden kann. Durch das Schreiben des Folgenden habe ich fast das gleiche Ergebnis wie Pandas erzielt.

def EMAnew(s, ma_period):
    alpha = 2/(ma_period+1)
    y,zf = lfilter([alpha], [1,alpha-1], s, zi=[s[0]*(1-alpha)])
    return pd.Series(y, index=s.index)

Hier ist zi der Anfangswert der Zustandsvariablen, also nicht nur der Anfangswert von Eingabe und Ausgabe, sondern hier $ y (0) = \ alpha x (0) + zi = x (0) Wenn Sie ein "zi" setzen, das zu "$" wird, scheint das Ergebnis so zu sein.

Recommended Posts

Ich habe den gleitenden Durchschnitt des IIR-Filtertyps mit Pandas und Scipy verglichen
Ich habe die Geschwindigkeit von Hash mit Topaz, Ruby und Python verglichen
Ich habe die Berechnungszeit des in Python geschriebenen gleitenden Durchschnitts verglichen
Ich habe versucht, die Verarbeitungsgeschwindigkeit mit dplyr von R und pandas von Python zu vergleichen
Ich habe versucht, mit TensorFlow den Durchschnitt mehrerer Spalten zu ermitteln
Sehen Sie, wie schnell Sie mit NumPy / SciPy beschleunigen können
[Einführung in Python] Ich habe die Namenskonventionen von C # und Python verglichen.
Ich habe die Grundoperation von Pandas im Jupyter Lab geschrieben (Teil 1)
Ich habe die grundlegende Operation von Pandas im Jupyter Lab geschrieben (Teil 2).
Zeichnen Sie den Nikkei Average Stock Index mit Pandas
Ich habe den Akkord des Songs mit word2vec vektorisiert und mit t-SNE visualisiert
Ich habe einen Fehler beim Abrufen der Hierarchie mit MultiIndex von Pandas gemacht
Ich habe die Geschwindigkeit der Listeneinschlussnotation für und während mit Python2.7 gemessen.
Versuchen Sie, den Hintergrund und das sich bewegende Objekt des Videos mit OpenCV zu trennen
Ich verglich die Geschwindigkeit von Go Language Web Framework Echo und Python Web Framework Flask
Sprechen Sie über die Funktionen, für die Pandas und ich im Projekt verantwortlich waren
Ich habe die Geschwindigkeit regulärer Ausdrücke in Ruby, Python und Perl (Version 2013) verglichen.
Ich habe die Beleuchtungsstärke des Raumes mit Raspberry Pi, Arduino und einem optischen Sensor getwittert
Typkonvertierung mehrerer Spalten von Pandas DataFrame mit Astype gleichzeitig
Lernen Sie während der Implementierung mit Scipy die Grundlagen der logistischen Regression und des mehrschichtigen Perzeptrons
Beachten Sie, dass die Berechnung der durchschnittlichen paarweisen Korrelation mit Pandas sehr einfach war
Ich habe die Pivot-Table-Funktion von Pandas ausprobiert
Ich habe "Python Dictionary Type" und "Excel Function" verglichen.
[Systre] Kaufen und verkaufen mit mobilem Durchschnitts-MACD ♬
Ich habe die Varianten von UKR gelesen und implementiert
Ich habe versucht, den Bildfilter von OpenCV zu verwenden
[Python] Bestimmen Sie den Typ der Iris mit SVM
Ich habe versucht, das Artikel-Update des Livedoor-Blogs mit Python und Selen zu automatisieren.
Ich habe die Geschwindigkeit der Referenz des Pythons in der Liste und die Referenz der Wörterbucheinbeziehung aus der In-Liste verglichen.
Ich wollte nur die Daten des gewünschten Datums und der gewünschten Uhrzeit mit Django extrahieren
Ich verglich die Identität der Bilder nach Hu Moment
Visualisieren Sie den Bereich der internen und externen Einfügungen mit Python
Ich habe mir die Versionen von Blender und Python angesehen
Ich habe die Leistung von 1 Million Dokumenten mit mongoDB gemessen
Ich habe das Standardbetriebssystem und die Shell der Docker-Maschine überprüft
Extrahieren Sie den Maximalwert mit Pandas und ändern Sie diesen Wert
FFT-Verarbeitung mit numpy und scipy bis Tiefpassfilter
Überprüfen Sie den Linux-Verteilungstyp und die Version
Animieren Sie die Alpha- und Beta-Werte der weltweit besten Marktwertaktien mit Pandas + Matplotlib
Ich lernte die Grundlagen des intensiven Lernens und spielte mit Cart Pole (Implementierung von einfachem Q-Lernen).
Gleitender Durchschnitt mit Numpy
Erstellen Sie einen Filter mit scipy
Ich habe versucht, mit Quantx eine Linie mit gleitendem Durchschnitt des Volumens zu implementieren
Ich habe versucht, das Bild mit Python + OpenCV "gammakorrektur" zu machen
Ich habe die grundlegende Grammatik von Python in Jupyter Lab geschrieben
Bitoperation einschließlich des Rückgabetyps und der Umwandlung von numpy.random.choice
Ich habe den Amazon Dash Button gehackt und mich bei Salesforce registriert
Ich habe die Strategie des Aktiensystemhandels mit Python evaluiert.
Formatieren Sie die Zeitachse des Pandas-Zeitreihendiagramms mit matplotlib neu
Ich habe versucht, den FloodFill-Algorithmus mit TRON BATTLE von CodinGame zu implementieren
Ich möchte die Natur von Python und Pip kennenlernen
Ich habe die Grundoperation von matplotlib in Jupyter Lab geschrieben
Ich habe den Chat von YouTube Live angezeigt und versucht zu spielen
Spielen Sie mit dem Passwortmechanismus von GitHub Webhook und Python
Ich habe mit Heroku + Flask + PostgreSQL (Heroku Postgres) einen LINE-Bot erstellt, der mir den Typ und die Stärke von Pokemon in der Garal-Region angibt.