PC & Mobile

Trading Toolbox – Vers la science des données

Trading Toolbox - Vers la science des données


Boîte à outils de trading

Photo par M. B. M. sur Unsplash

Dans le premier article de la série Financial Trading Toolbox (Création d'une boîte à outils Financial Trading en Python: Moyenne mobile simple), nous avons expliqué comment calculer une moyenne mobile simple, l'ajouter à un graphique de série de prix et l'utiliser pour les décisions d'investissement et de négociation. . La moyenne mobile simple n'est qu'une des nombreuses moyennes mobiles disponibles qui peuvent être appliquées aux séries de prix pour créer des systèmes de négociation ou des cadres de décision d'investissement. Parmi ceux-ci, deux autres moyennes mobiles sont couramment utilisées parmi les marchés financiers:

  • Moyenne mobile pondérée (WMA)
  • Moyenne mobile exponentielle (EMA)

Dans cet article, nous verrons comment calculer ces deux moyennes et comment nous assurer que les résultats correspondent aux définitions que nous devons implémenter.

Moyenne mobile pondérée

Dans certaines applications, l’une des limites de la moyenne mobile simple est qu’elle attribue un poids égal à chacun des prix quotidiens inclus dans la fenêtre. Par exemple, dans une moyenne mobile sur 10 jours, le jour le plus récent reçoit le même poids que le premier jour de la fenêtre: chaque prix reçoit une pondération de 10%.

Par rapport à la moyenne mobile simple, le Moyenne mobile pondérée linéairement (ou simplement Moyenne mobile pondérée, WMA), donne plus de poids au prix le plus récent et de moins en moins au fur et à mesure Sur une moyenne pondérée sur 10 jours, le prix du dixième jour serait multiplié par 10, celui du neuvième jour par 9, le huitième jour par 8, et ainsi de suite. Le total sera ensuite divisé par la somme des poids (dans ce cas: 55). Dans cet exemple spécifique, le prix le plus récent reçoit environ 18,2% du poids total, le second 16,4% le plus récent, et ainsi de suite jusqu'au prix le plus ancien de la fenêtre qui reçoit 0,02% du poids.

Mettons cela en pratique avec un exemple en Python. En plus de pandas et Matplotlib, nous allons utiliser NumPy:

importer des pandas en tant que pd
importer numpy en tant que np
importer matplotlib.pyplot en tant que plt
importer matplotlib en mpl

Nous appliquons un style pour nos graphiques. Si vous utilisez Jupyter c’est une bonne idée d’ajouter le % matplotlib inline instruction (et sauter plt.show () lors de la création de graphiques):

plt.style.use ('cinq sur trente')

Pour les exemples suivants, nous allons utiliser les données de prix d'un article de StockCharts.com. C’est un excellent article éducatif sur les moyennes mobiles et je vous recommande de le lire. Les séries de prix utilisées dans cet article peuvent appartenir à n’importe quel instrument ou instrument financier et serviront à nos fins d’illustration.

J'ai modifié la feuille de calcul Excel d'origine en incluant des calculs pour la WMA à 10 jours car le calcul pour la EMA est déjà inclus. Vous pouvez accéder à mon fichier Google Sheets et télécharger les données au format CSV ici.

Lors de la modélisation des données, il est toujours judicieux de commencer par une simple implémentation de notre modèle que nous pouvons utiliser pour nous assurer que les résultats de notre implémentation finale sont corrects.

Nous commençons par charger les données dans un cadre de données:

datafile = 'cs-movavg.csv'data = pd.read_csv (fichier de données, index_col = 'Date')
data.index = pd.to_datetime (data.index)
# Nous pouvons supprimer l'ancienne colonne d'index:
data = data.drop (columns = 'Sans nom: 0')
Les données

Pour le moment, nous ne prendrons en compte que les colonnes WMA Price et WMA 10 jours et passerons ultérieurement à l'EMA.

En ce qui concerne les moyennes mobiles linéairement pondérées, la pandas bibliothèque n'a pas de méthode prête à l'emploi pour les calculer. Il offre cependant une méthode très puissante et flexible: .appliquer() Cette méthode nous permet de créer et de transmettre toute fonction personnalisée à une fenêtre défilante: c’est ainsi que nous allons calculer notre moyenne mobile pondérée. Pour calculer un WMA 10 jours, nous commençons par créer un tableau de poids - nombres entiers de 1 à 10:

poids = np.arange (1,11) #this crée un tableau avec des entiers compris entre 1 et 10poids

Qui ressemble à:

tableau ([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])

Ensuite, en utilisant le .appliquer() méthode nous passons notre propre fonction (un lambda fonction) pour calculer le produit scalaire des poids et des prix dans notre fenêtre déroulante (les prix dans la fenêtre seront multipliés par le poids correspondant, puis additionnés), puis divisés par la somme des poids:

wma10 = données['Price'].rolling (10) .apply (prix lambda: np.dot (prix, pondération) /weights.sum (), raw = True)wma10.head (20)

Qui donne:

Nous souhaitons maintenant comparer notre WMA à celle obtenue avec le tableur. Pour ce faire, nous pouvons ajouter un «Notre WMA de 10 jours» colonne vers le dataframe. Pour faciliter la comparaison visuelle, nous pouvons arrondir la série WMA à trois décimales en utilisant le.rond() méthode de NumPy. Ensuite, nous sélectionnons les colonnes de prix et WMA à afficher:

Les données['Our 10-day WMA'] = np.round (wma10, décimales = 3)Les données[['Price', '10-day WMA', 'Our 10-day WMA']]tête de lit (20)

Montrant:

Les deux colonnes WMA se ressemblent. Il y a quelques différences dans la troisième décimale, mais nous pouvons attribuer cela à une erreur d'arrondi et conclure que notre mise en œuvre de la WMA est correcte. Dans une application réelle, si nous voulons être plus rigoureux, nous devons calculer les différences entre les deux colonnes et vérifier qu'elles ne sont pas trop grandes. Pour l'instant, nous gardons les choses simples et nous pouvons être satisfaits de l'inspection visuelle.

Il serait intéressant de comparer dans un complot notre nouvellement créé WMA avec le familier SMA:

sma10 = data['Price'].rouler (10) .moyen ()plt.figure (figsize = (12,6))plt.plot (data['Price'], label = "Prix")
plt.plot (wma10, label = "WMA 10 jours")
plt.plot (sma10, label = "SMA 10 jours")
plt.xlabel ("Date")
plt.ylabel ("Prix")
plt.legend ()
plt.show ()

Ceci montre:

Comme on peut le constater, les deux moyennes lissent le mouvement des prix. La WMA est plus réactive et suit le prix plus près que la SMA: nous l’attendons puisque la WMA donne plus de poids aux dernières observations de prix. En outre, les deux séries de moyennes mobiles commencent le jour 10: le premier jour avec suffisamment de données disponibles pour calculer les moyennes.

La moyenne mobile pondérée peut être moins connue que son frère exponentiel. Cependant, cela peut être un élément supplémentaire dans notre boîte à outils lorsque nous essayons de construire des solutions originales. L'implémentation de la WMA en Python nous a obligés à rechercher un moyen de créer des moyennes mobiles personnalisées à l'aide de .appliquer(): cette technique peut également être utilisée pour implémenter des moyennes mobiles nouvelles et originales.

Moyenne mobile exponentielle

Comme pour la moyenne mobile pondérée, la moyenne mobile exponentielle (EMA) attribue un poids plus important aux dernières observations de prix. Bien qu'il attribue un poids moindre aux données passées, il repose sur une formule récursive qui inclut dans son calcul toutes les données passées de nos séries de prix.

L'EMA à l'heure t est calculé comme le prix actuel multiplié par un facteur de lissage alpha (un nombre positif inférieur à 1) plus l'EMA au temps − 1 multiplié par 1 moins alpha. Il s’agit essentiellement d’une valeur comprise entre l’EMA précédent et le prix actuel:

Le facteur de lissage 𝛼 ( alpha ) est défini comme:

où 𝑛 est le nombre de jours dans notre étendue. Par conséquent, un EMA 10 jours aura un facteur de lissage:

Pandas inclut une méthode permettant de calculer la moyenne mobile EMA de n’importe quelle série chronologique: .ewm (). Cette méthode répondra-t-elle à nos besoins et calculera-t-elle une moyenne qui correspond à notre définition? Testons le:

ema10 = données['Price'].ewm (span = 10) .mean ()ema10.head (10)

Qui donne:

Nous voulons comparer cette série EMA avec celle obtenue dans le tableur:

Les données['Our 10-day EMA'] = np.round (ema10, décimales = 3)Les données[['Price', '10-day EMA', 'Our 10-day EMA']]tête de lit (20)

Quels résultats:

Comme vous l'avez déjà remarqué, nous avons un problème ici: l'EMA à 10 jours que nous venons de calculer ne correspond pas à celui calculé dans le tableur téléchargé. L'un commence le jour 10, l'autre le jour 1. En outre, les valeurs ne correspondent pas exactement.

Notre calcul est-il faux? Ou bien le calcul dans le tableur fourni est-il faux? Ni l'une ni l'autre: ces deux séries correspondent à deux définitions différentes de l'EMA. Pour être plus précis, la formule utilisée pour calculer l'EMA est la même. Ce qui change, ce n’est que l’utilisation des valeurs initiales.

Si nous examinons attentivement la définition de la moyenne mobile exponentielle sur la page Web StockCharts.com, nous remarquons un détail important: ils commencent à calculer une moyenne mobile sur 10 jours le jour 10, en ignorant les jours précédents et en remplaçant le prix le jour 10 par ses SMA 10 jours. C’est une définition différente de celle appliquée lorsque nous avons calculé l’EMA à l’aide du .ewm () méthode directement.

Les lignes de code suivantes créent une nouvelle série de prix modifiée dans laquelle les 9 premiers prix (lorsque le SMA n'est pas disponible) sont remplacés par NaN et le prix à la 10ème date devient son SMA à 10 jours:

modPrice = data['Price'].copie()
modPrice.iloc[0:10] = sma10[0:10]
modPrice.head (20)

Nous pouvons utiliser cette série de prix modifiée pour calculer une deuxième version de l'EWM. En regardant la documentation, on peut constater que le .ewm () la méthode a un régler paramètre par défaut Vrai. Ce paramètre ajuste les pondérations pour tenir compte du déséquilibre dans les périodes de début (si vous avez besoin de plus de détails, voir Fenêtres à pondération exponentielle section dans le pandas Documentation).

Si nous voulons émuler l'EMA comme dans notre feuille de calcul en utilisant notre série de prix modifiée, nous n'avons pas besoin de cet ajustement. Nous avons ensuite mis ajuster = Faux:

ema10alt = modPrice.ewm (span = 10, ajuster = False) .mean ()

Cet EMA nouvellement calculé correspondra-t-il à celui calculé dans le tableur? Regardons:

Les données['Our 2nd 10-Day EMA'] = np.round (ema10alt, décimales = 3)Les données[['Price', '10-day EMA', 'Our 10-day EMA', 'Our 2nd 10-Day EMA']]tête de lit (20)

Maintenant, nous allons beaucoup mieux. Nous avons obtenu une série EMA qui correspond à celle calculée dans le tableur.

Nous nous sommes retrouvés avec deux versions différentes d'EMA:

  1. ema10: Cette version utilise la plaine .ewm () Cette méthode commence au début de notre historique des prix mais ne correspond pas à la définition utilisée dans le tableur.
  2. ema10alt: Cette version commence le jour 10 (avec une valeur initiale égale à la SMA de 10 jours) et correspond à la définition de notre feuille de calcul.

Lequel est le meilleur à utiliser? La réponse est: cela dépend de ce dont nous avons besoin pour notre application et pour construire notre système. Si nous avons besoin d’une série EMA qui commence au jour 1, nous devrions choisir la première. D'autre part, si nous devons utiliser notre moyenne en combinaison avec d'autres moyennes qui n'ont pas de valeur pour les jours initiaux (tels que le SMA), alors le second est probablement le meilleur.

Le second EMA est largement utilisé par les analystes des marchés financiers: si nous devons mettre en œuvre un système déjà existant, nous devons faire attention à utiliser la définition correcte. Sinon, les résultats pourraient ne pas correspondre à ce que l'on attend de nous et remettre en question l'exactitude de l'ensemble de nos travaux. Dans tous les cas, la différence numérique entre ces deux moyennes est minime, avec un impact sur notre système de décision de négociation ou d'investissement limité aux premiers jours.

Examinons toutes les moyennes mobiles que nous avons utilisées jusqu’à présent dans un graphique:

plt.figure (figsize = (12,6))plt.plot (data['Price'], label = "Prix")
plt.plot (wma10, label = "WMA 10 jours")
plt.plot (sma10, label = "SMA 10 jours")
plt.plot (ema10, label = "10-Day EMA-1")
plt.plot (ema10alt, label = "10-Day EMA-2")
plt.xlabel ("Date")
plt.ylabel ("Prix")
plt.legend ()
plt.show ()

De toutes les moyennes mobiles, le WMA apparaît celui qui est plus réactif et étiquette le prix plus étroitement, tandis que le SMA est celui qui répond avec un peu plus de retard. Les deux versions du EMA ont tendance à se chevaucher, principalement dans les derniers jours.

J'espère que vous avez trouvé ce post utile. L'introduction de la moyenne mobile pondérée nous a aidés à apprendre et à mettre en œuvre une moyenne personnalisée basée sur une définition spécifique. L'utilisation de la moyenne mobile exponentielle nous a permis de souligner à quel point il est important de veiller à ce que toute fonction utilisée pour travailler sur des séries de prix corresponde à la définition que nous avons pour une tâche donnée.

Afficher plus

SupportIvy

SupportIvy.com : Un lieu pour partager le savoir et mieux comprendre le monde. Meilleure plate-forme de support gratuit pour vous, Documentation &Tutoriels par les experts.

Articles similaires

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Bouton retour en haut de la page
Fermer