J'ai comparé la moyenne mobile du type de filtre IIR avec les pandas et scipy

Articles prérequis

Comparé le temps de calcul de la moyenne mobile écrite en Python

Il est hors de question d'utiliser l'instruction for en Python pour calculer la moyenne mobile, et le résultat est qu'il est préférable d'utiliser les fonctions pandas et scipy. Cependant, dans l'article ci-dessus, il s'agissait d'une moyenne mobile du type de filtre FIR tel que SMA et LWMA, donc cette fois j'ai étudié la moyenne mobile du type de filtre IIR tel que EMA et SMMA.

EMA EMA est une abréviation de moyenne mobile exponentielle et s'exprime par la formule suivante.

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

Où $ \ alpha $ est un paramètre réel de 0 à 1. Cette formule n'inclut pas de paramètre qui représente la période, mais comme SMA et LWMA utilisent des paramètres qui représentent la période, EMA utilise souvent le paramètre de période en conséquence. En supposant que la période est $ p $, EMA est $ \ alpha = 2 / (p + 1) $ et SMMA est $ \ alpha = 1 / p $. Personnellement, je ne pense pas qu'il soit nécessaire de faire la distinction entre EMA et SMMA car ils ont la même formule, mais je les mentionnerai car ils sont utilisés séparément dans MetaTrader.

Mis en œuvre avec des pandas

Commençons par l'implémenter avec les pandas. Les données à traiter sont les mêmes que dans l'article précédent. Il s'agit d'une série chronologique à quatre valeurs d'environ 370 000 pièces. Puisque les pandas sont pour les données de séries chronologiques, EMA peut aussi être facilement écrit avec les fonctions ʻewm () ʻetmean ().

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)

Étant donné que le temps d'exécution sera également comparé cette fois, les résultats de la mesure seront affichés.

10 loops, best of 3: 32.2 ms per loop

Dans le cas du SMA, c'était environ 16 millisecondes, donc c'est environ deux fois plus lent.

Un peu de conversion avant de mettre en œuvre avec scipy

Lorsque vous utilisez lfilter () de scipy, il ne suffit pas de saisir simplement $ \ alpha $, vous devez passer au format de filtre IIR et entrer le coefficient. Donc, je vais le convertir un peu. (La théorie détaillée est omise. C'est la base du traitement numérique du signal.)

Convertit les deux côtés de l'expression EMA en $ z $.

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

Si vous mettez $ Y (z) $ sur le côté gauche

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

Et si $ Y (z) / X (z) $ est $ H (z) $,

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

Peut être écrit. C'est la fonction système du filtre IIR. Passer l'argument de lfilter () est le coefficient du polynôme moléculaire et le coefficient du polynôme dénominateur de cette fonction système.

Dans le cas de l'EMA, la molécule de la fonction système est une constante et le dénominateur est un polynôme du premier ordre, de sorte que la formule générale de la fonction système peut s'écrire comme suit.

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

En comparant les coefficients, vous pouvez voir que les coefficients de $ b $ et $ a $ sont les suivants.

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

Implémenté avec scipy

Donc, si vous implémentez EMA en utilisant lflter () de scipy, vous pouvez écrire comme suit. Mettez les $ b $ et $ a $ ci-dessus sous la forme d'une 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)

Le résultat est

100 loops, best of 3: 3.08 ms per loop

Il est devenu presque la même vitesse que le cas de SMA. Après tout, lfilter () est rapide.

Ajuster les conditions initiales de lfilter ()

Le résultat est que lfilter () est également rapide cette fois, mais il y a un léger problème avec le résultat du traitement.

En EMA, lors du calcul de la première sortie $ y (0) $, $ y (-1) $ sans données est utilisé, mais dans le cas des pandas, il convient aux données de séries chronologiques, donc $ y Il est traité de sorte que $ y (-1) $ ne soit pas utilisé comme (0) = x (0) $.

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

Dans ce cas, le résultat de EMA n'est pas si différent de la série temporelle d'entrée, mais dans le cas de lfilter (), il est calculé comme $ y (-1) = 0 $, donc le premier EMA La valeur de s'écartera considérablement de l'entrée.

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

Il semble que ce problème puisse être résolu avec l'argument optionnel de lfilter (). En écrivant ce qui suit, j'ai presque le même résultat que les pandas.

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)

Ici, zi est la valeur initiale de la variable d'état, donc ce n'est pas seulement la valeur initiale de l'entrée et de la sortie, mais ici, $ y (0) = \ alpha x (0) + zi = x (0) Si vous mettez un zi qui devient $, il semble que le résultat sera comme ça.

Recommended Posts

J'ai comparé la moyenne mobile du type de filtre IIR avec les pandas et scipy
J'ai comparé la vitesse de Hash avec Topaz, Ruby et Python
J'ai comparé le temps de calcul de la moyenne mobile écrite en Python
J'ai essayé de comparer la vitesse de traitement avec dplyr de R et pandas de Python
J'ai essayé de trouver la moyenne de plusieurs colonnes avec TensorFlow
Découvrez la puissance de l'accélération avec NumPy / SciPy
[Introduction à Python] J'ai comparé les conventions de nommage de C # et Python.
J'ai écrit le fonctionnement de base de Pandas dans Jupyter Lab (partie 1)
J'ai écrit le fonctionnement de base de Pandas dans Jupyter Lab (partie 2)
Tracez l'indice boursier moyen Nikkei avec des pandas
J'ai vectorisé l'accord de la chanson avec word2vec et je l'ai visualisé avec t-SNE
J'ai fait une erreur en récupérant la hiérarchie avec MultiIndex of pandas
J'ai mesuré la vitesse de la notation d'inclusion de liste, pendant et pendant avec python2.7.
Essayez de séparer l'arrière-plan et l'objet en mouvement de la vidéo avec OpenCV
J'ai comparé la vitesse de l'écho du framework web en langage go et du flask du framework web python
Parlez des fonctionnalités dont les pandas et moi étions en charge dans le projet
J'ai comparé la vitesse des expressions régulières en Ruby, Python et Perl (version 2013)
J'ai tweeté l'éclairement de la pièce avec Raspberry Pi, Arduino et un capteur optique
Conversion de type de plusieurs colonnes de pandas DataFrame avec un type en même temps
Apprenez en implémentant avec Scipy Les bases de la régression logistique et du perceptron multicouche
Notez que le calcul de la corrélation moyenne par paire était très facile avec les pandas
J'ai essayé la fonction de tableau croisé dynamique des pandas
J'ai comparé "type de dictionnaire python" et "fonction excel"
[Systre] Achetez et vendez avec le MACD moyen mobile ♬
J'ai lu et implémenté les variantes de UKR
J'ai essayé d'utiliser le filtre d'image d'OpenCV
[Python] Déterminez le type d'iris avec SVM
J'ai essayé d'automatiser la mise à jour de l'article du blog Livedoor avec Python et sélénium.
J'ai comparé la vitesse de la référence du python dans la liste et la référence de l'inclusion du dictionnaire faite à partir de la liste dans.
Je voulais juste extraire les données de la date et de l'heure souhaitées avec Django
J'ai comparé l'identité des images par moment Hu
Visualisez la gamme d'insertions internes et externes avec python
J'ai vérifié les versions de Blender et Python
J'ai mesuré les performances d'un million de documents avec mongoDB
J'ai vérifié le système d'exploitation et le shell par défaut de docker-machine
Extraire la valeur maximale avec les pandas et modifier cette valeur
Traitement FFT avec filtre numpy et scipy vers passe-bas
Vérifiez le type et la version de la distribution Linux
Animez les valeurs alpha et bêta des principales valeurs boursières mondiales avec pandas + matplotlib
J'ai appris les bases de l'apprentissage intensif et joué avec Cart Pole (implémentation simple de Q Learning)
Moyenne mobile avec numpy
Créer un filtre avec scipy
J'ai essayé d'implémenter une ligne moyenne mobile de volume avec Quantx
J'ai essayé la "correction gamma" de l'image avec Python + OpenCV
J'ai écrit la grammaire de base de Python dans Jupyter Lab
Opération sur les bits comprenant le type de retour et le cast de numpy.random.choice
J'ai piraté le bouton Amazon Dash et je me suis inscrit à Salesforce
J'ai évalué la stratégie de négociation du système boursier avec Python.
Reformatez l'axe des temps du graphique de la série chronologique des pandas avec matplotlib
J'ai essayé d'implémenter l'algorithme FloodFill avec TRON BATTLE de CodinGame
Je veux connaître la nature de Python et pip
J'ai écrit le fonctionnement de base de matplotlib dans Jupyter Lab
J'ai affiché le chat de YouTube Live et essayé de jouer
Jouez avec le mécanisme de mot de passe de GitHub Webhook et Python
J'ai créé un bot LINE qui me dit le type et la force de Pokémon dans la région de Garal avec Heroku + Flask + PostgreSQL (Heroku Postgres)