English Русский 中文 Español Deutsch 日本語 Português
preview
Tester différents types de Moyennes Mobiles pour voir leur pertinence

Tester différents types de Moyennes Mobiles pour voir leur pertinence

MetaTrader 5Tester |
26 1
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Introduction

Dans mon article précédent, nous avons examiné les types de Moyennes Mobiles les plus courants (simples, pondérées, exponentielles) : Apprenez à concevoir différents systèmes de Moyennes Mobiles. Nous poursuivrons ce sujet dans cet article et nous utiliserons le type simple pour comparer ses résultats avec d'autres types de moyennes mobiles. De nombreux traders utilisent la moyenne mobile sous différentes formes en fonction de leurs préférences. C'est pourquoi, dans cet article, nous examinerons en détail différents types, nous testerons leurs performances et nous comparerons les résultats afin de déterminer lequel de ces types est le plus performant.

Dans le cadre de cet article, nous allons créer une application simple afin d'effectuer un backtesting des moyennes dans le Testeur de Stratégie intégré de MetaTrader 5. Pour comprendre ce sur quoi nous devons nous concentrer lorsque nous étudions les résultats des tests, veuillez consulter mon article précédent Comprendre et utiliser efficacement le Testeur de Stratégie MQL5 ; il fournit de nombreuses informations utiles.

Pour étudier les différents types de moyennes mobiles et voir comment elles fonctionnent, nous allons aborder les sujets suivants :

Veuillez noter que même si je vais essayer d'optimiser les paramètres de chaque moyenne mobile pour obtenir les meilleurs résultats, vous devez faire plus de vérifications et de tests par vous-même car l'objectif ici est uniquement l'éducation. Il convient donc de tester, d'optimiser et de trouver de meilleurs paramètres pour obtenir de meilleurs résultats. Il se peut que l'un ou l'ensemble de ces types ne conviennent pas à votre style de trading. Mais j'espère que vous y trouverez des informations qui vous aideront à améliorer vos transactions. En général, quel que soit l'idéal que vous poursuivez, il est important de mesurer la performance de toute stratégie de trading avant de l'utiliser sur un compte réel.

Avertissement : Toutes les informations sont fournies "en l'état", uniquement à des fins d'information, et ne sont pas données à des fins de trading ou de conseil. Ces informations ne garantissent aucun résultat. Si vous utilisez le contenu de cet article sur l'un de vos comptes de trading, vous le faites à vos propres risques et vous en serez le seul responsable.

Test du système de Moyenne Mobile Simple (SMA)

Dans cette partie, je partagerai les résultats du système simple qui est basé uniquement sur une stratégie simple de moyenne mobile. Il détecte le croisement entre le prix et la ligne de la moyenne mobile simple qui génère des signaux d'achat et de vente. Nous allons créer un système capable d'exécuter ces signaux automatiquement.

Nous utiliserons les signaux suivants pour effectuer des opérations de trading :


Signal d'achat :

Le prix de clôture est supérieur à la valeur de la moyenne mobile simple

Et, le prix de clôture précédent était inférieur à la valeur de la moyenne mobile simple précédente.

Signal de vente :

Le prix de clôture est inférieur à la valeur de la moyenne mobile simple

Et, le prix de clôture précédent était supérieur à la valeur de la moyenne mobile simple précédente.

Si vous voulez en savoir plus sur la moyenne mobile simple et d'autres types de moyennes mobiles populaires, je vous recommande de lire mon article précédent Apprendre à concevoir différents systèmes de moyennes mobiles, qui vous aidera à bien les comprendre et qui vous aidera à bien comprendre cet article.

Les étapes suivantes permettent de créer ce type de système de trading capable d'exécuter automatiquement des ordres d'achat et de vente sur la base des signaux mentionnés.

Dans la portée globale, nous inclurons le fichier Trade dans le logiciel, qui permet d'exécuter des ordres basés sur nos signaux en utilisant la directive de préprocesseur #include. Si vous souhaitez en savoir plus sur le préprocesseur, vous pouvez lire l'article Tout ce qu'il faut savoir sur la structure du programme MQL5 pour plus de détails.

#include <Trade\Trade.mqh>

Créez 3 entrées utilisateur pour les variables lotSize de type double, timeFrame de type ENUM_TIMEFRAMES, et MAPeriod de type integer, avec des valeurs par défaut :

input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;

Créez 2 variables simpleMA et barsTotal de type integer, sans valeur car nous les définirons plus tard dans la partie OnInit().

int simpleMA;
int barsTotal;

Créez trade comme objet de la classe CTrade pour faciliter l'accès aux fonctions de la transaction.

CTrade trade;

Dans la partie OnInit(), nous définirons simpleMA avec la fonction iMA qui renvoie le handle de l'indicateur de moyenne mobile. Ses paramètres sont les suivants :

  • symbol : pour spécifier le nom du symbole, nous utiliserons _Symbol pour le symbole actuel
  • period : pour spécifier la période de temps, nous utiliserons la saisie de l'utilisateur avec une valeur par défaut de 1 heure, mais l'utilisateur peut l'ajuster.
  • ma_period : pour spécifier la période de la moyenne mobile simple, nous utiliserons les données de l'utilisateur avec une valeur par défaut de 50, mais l'utilisateur peut également l'ajuster.
  • ma_shift : pour spécifier le décalage horizontal, nous utiliserons 0 
  • applied_price : pour spécifier le type de prix, nous utiliserons le prix de clôture pour le calcul de la moyenne mobile simple.
simpleMA = iMA(_Symbol, timeFrame, MAPeriod, 0, MODE_SMA, PRICE_CLOSE);

Et barsTotal en utilisant la fonction iBars pour retourner le nombre de barres, ses paramètres sont :

  • symbol : pour spécifier le symbole, nous utiliserons _Symbol pour le symbole actuel
  • timeframe : pour spécifier la période de temps, nous utiliserons la période définie par l'utilisateur avec une valeur par défaut de 1 heure, que l'utilisateur peut ajuster.
   barsTotal=iBars(_Symbol,timeFrame);

Dans la partie OnTick(), nous créerons 2 tableaux : l'un pour les prix en utilisant MqlRates pour stocker les informations sur les prix, les volumes et l'écart, et l'autre pour la moyenne mobile simple :

   MqlRates priceArray[];
   double mySMAArray[];

Attribuons l'indicateur AS_SERIES à ces deux tableaux créés à l'aide de la fonction ArraySetAsSeries, ses paramètres sont les suivants :

  • array[] : pour spécifier le tableau par référence
  • flag : pour spécifier le sens d'indexation du tableau
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(mySMAArray,true);

Définissons les prix Ask et Bid après avoir créé 2 variables de type double de ces prix :

   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);

Obtenons les données historiques de MqlRates en utilisant la fonction CopyRates, ses paramètres sont les suivants :

  • symbol_name : pour déterminer le nom du symbole
  • timeframe : pour déterminer la période de temps
  • start_pos : pour spécifier la position de départ
  • count : pour spécifier le nombre de données à copier
  • rates_array[] : pour spécifier le tableau cible à copier
int Data=CopyRates(_Symbol,_Period,0,3,priceArray);

Obtenons les données du buffer de l'indicateur en utilisant la fonction CopyBuffer, dont les paramètres sont les suivants :

  • indicator_handle : pour spécifier le handle de l'indicateur qui est simpleMA ici
  • buffer_num : pour spécifier le numéro du buffer de l'indicateur qui est 0
  • start_pos : pour déterminer la position de départ qui est 0, c'est-à-dire la bougie actuelle
  • count : pour spécifier la quantité à copier qui est de 3
  • buffer[] : pour spécifier le tableau cible que nous devons copier, qui est mySMAArray
CopyBuffer(simpleMA,0,0,3,mySMAArray);

Définissons le dernier cours de clôture et la valeur de la moyenne mobile simple de la même bougie après avoir créé 2 variables de type double :

   double lastClose=(priceArray[1].close);
   double SMAVal = NormalizeDouble(mySMAArray[1],_Digits);

Définissons le prix de clôture précédent et la valeur de la moyenne mobile simple de cette même bougie après avoir créé 2 autres variables de type double :

   double prevClose=(priceArray[2].close);
   double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);

Créons une variable bars de type integer à comparer avec la variable barsTotal créée :

int bars=iBars(_Symbol,timeFrame);

Vérifions la création d'une nouvelle barre en contrôlant que le nombre total de barres n'est pas égal à bars :

if(barsTotal != bars)

Si barsTotal n'est pas égal à bars, nous devons mettre à jour barsTotal avec la valeur de bars :

barsTotal=bars;

Si barsTotal n'est pas égal à bars, nous devons également vérifier les conditions de la stratégie : si la clôture de l’avant-dernière barre est inférieure à la valeur de la moyenne mobile simple de la même bougie, et qu'en même temps le dernier prix de clôture est supérieur à la valeur de la moyenne mobile simple de la même bougie. Le programme doit fermer la position ouverte actuelle et ouvrir une position d'achat.

      if(prevClose<prevSMAVal && lastClose>SMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }

Si la clôture de l’avant-dernière barre est supérieure à la valeur de la moyenne mobile simple de la même bougie, et qu'en même temps le dernier prix de clôture est inférieur à la valeur de la moyenne mobile simple de la même bougie. Le programme doit fermer la position ouverte actuelle et ouvrir une position de vente.

      if(prevClose>prevSMAVal && lastClose<SMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }

Ensuite, nous compilerons le code et nous constaterons qu'il a été compilé sans aucune erreur ou avertissement.

Le code suivant est le code complet en un seul bloc :

//+------------------------------------------------------------------+
//|                                                   SMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
int simpleMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   simpleMA = iMA(_Symbol, timeFrame, MAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double mySMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(mySMAArray,true);
   int Data=CopyRates(_Symbol,_Period,0,3,priceArray);
   CopyBuffer(simpleMA,0,0,3,mySMAArray);
   double lastClose=(priceArray[1].close);
   double SMAVal = NormalizeDouble(mySMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(prevClose<prevSMAVal && lastClose>SMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(prevClose>prevSMAVal && lastClose<SMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

Nous compilons l'EA et l'exécutons sur les données EURUSD pour backtester la stratégie. La période de test s'étend du 1er janvier au 30 juin 2022, comme nous l'avons fait pour tous les types de moyennes mobiles mentionnés. Nos paramètres pour la SMA seront les suivants :

  • Taille du lot : 1
  • Période : 1 heure
  • Période de la MA : 50

Les résultats du test :

Résultats de la SMA

Comme nous pouvons le voir, les chiffres suivants doivent être étudiés après avoir testé l'indicateur SMA :

  • Bénéfice Net (Net Profit) : 2700,30 (27%)
  • DD relatif du solde : 37,07%
  • DD relatif des fonds : 41,76%
  • Facteur de profit : 1,10
  • Gain attendu : 12,68
  • Facteur de récupération : 0,45
  • Ratio de Sharpe : 0,57

Moyenne Mobile Adaptative (iAMA)

Dans cette partie, nous allons découvrir un autre type de moyenne mobile, l'AMA (Adaptive Moving Average en anglais). Elle a été développée par Perry J. Kaufman et s'appelle KAMA. Le concept principal est de réduire le bruit dans le mouvement des prix. Elle suit l'évolution des prix, quelle que soit la volatilité de cette évolution, en s'y adaptant. L'indicateur est un indicateur de suivi de tendance, il peut donc être utilisé pour identifier la tendance et les points de retournement.

L'indicateur est calculé en quelques étapes.

Première étape : Calcul de l'AMA ou de la KAMA

première étape

Deuxième étape : Calcul de la constante de lissage SC

étape 2

Troisième étape : Calcul du ratio d'Efficacité RE

 étape 3

Nous avons appris à calculer l'indicateur AMA manuellement, mais cela n'est pas nécessaire car nous pouvons l'insérer automatiquement dans MetaTrader 5 en le choisissant parmi les indicateurs prêts à l'emploi disponibles. Il est temps de créer un système de trading capable d'exécuter des ordres d'achat et de vente sur la base du croisement entre le cours de clôture et l'indicateur AMA. Nous utiliserons donc les signaux suivants pour notre stratégie.

Signal d'achat :

Le prix de clôture est supérieur à la valeur de la moyenne mobile adaptative

Et, le prix de clôture précédent était inférieur à la valeur de la moyenne mobile adaptative précédente.

Signal de vente :

Le prix de clôture est inférieur à la valeur de la moyenne mobile adaptative

Le prix de clôture précédent était supérieur à la valeur de la moyenne mobile adaptative précédente.

Voici le code complet permettant de créer ce type de système de trading :

//+------------------------------------------------------------------+
//|                                                  iAMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
input int fastMAPeriod= 5;
input int slowMAPeriod= 100;
int adaptiveMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   adaptiveMA = iAMA(_Symbol, timeFrame, MAPeriod,fastMAPeriod,slowMAPeriod, 0, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double myAMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(myAMAArray,true);
   int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray);
   CopyBuffer(adaptiveMA,0,0,3,myAMAArray);
   double lastClose=(priceArray[1].close);
   double AMAVal = NormalizeDouble(myAMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevAMAVal = NormalizeDouble(myAMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(lastClose>AMAVal && prevClose<prevAMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(lastClose<AMAVal && prevClose>prevAMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

La différence dans ce code est l'utilisation de la fonction iAMA qui renvoie le handle de l'indicateur de moyenne mobile adaptative et ses paramètres sont :

  • symbol : pour spécifier le nom du symbole, nous utiliserons _Symbol pour le symbole actuel
  • period : pour spécifier la période de temps qui sera utilisée par l'utilisateur, avec une valeur par défaut de 1 heure.
  • ama_period : pour spécifier la période de la moyenne mobile adaptative
  • fast_ma_period : pour spécifier la période de la MA rapide
  • slow_ma_period : pour spécifier la période de la MA lente
  • ama_shift : pour spécifier le décalage horizontal, nous utiliserons 0
  • applied_price : pour spécifier le type de prix, nous utiliserons le prix de clôture

Nous devons backtester l'indicateur AMA pour la même période afin de voir ses résultats :

  • Taille du lot = 1
  • Période = 1 heure
  • Période MA = 50
  • MA rapide = 5
  • MA lente = 100

Voici les résultats :

Résultats AMA

Comme nous pouvons le voir, les chiffres suivants doivent être étudiés après avoir testé l'indicateur AMA :

  • Bénéfice Net (Net Profit) : 3638,20 (36.39%)
  • DD relatif du solde : 22,48%
  • DD relatif des fonds : 35,53%
  • Facteur de profit : 1,31
  • Gain attendu : 35,67
  • Facteur de récupération : 0,65
  • Ratio de Sharpe : 0,86

Moyenne Mobile Exponentielle Double (iDEMA)

Dans cette partie, nous allons identifier un autre type de moyenne mobile : l'indicateur technique Double Exponential Moving Average (DEMA), ou Moyenne Mobile Exponentielle Double. Il s'agit d'un indicateur de suivi de tendance développé par Patrick Mulloy. L'objectif principal de cet indicateur est de réduire le décalage des EMA mais de le rendre plus réactif aux mouvements du marché comme nous le verrons dans son calcul.

Cet indicateur peut être utilisé pour identifier la tendance ou les points de retournement de la tendance en détectant la position des prix par rapport à cette moyenne mobile. Les étapes du calcul de l'indicateur sont présentées ci-dessous :

1. Calcul de la première moyenne mobile exponentielle (EMA)

EMA 1 = EMA de n périodes de prix

2. Calcul de l'EMA de l'EMA 1

EMA 2 = EMA de EMA 1

3. Calcul du DEMA

DEMA = (2 * EMA 1) - EMA 2

Comme nous le savons, nous n'avons pas besoin de faire ce calcul manuel, c'est pour bien le comprendre. Cet indicateur, comme beaucoup d'autres indicateurs techniques, est directement disponible dans MetaTrader 5. Nous devons maintenant créer le même système de trading que celui que nous avons créé précédemment, mais nous utiliserons cette fois le DEMA pour tester ses résultats par rapport à d'autres types. Ce système de trading sera exécuté avec les mêmes ordres mentionnés qui achètent et vendent sur la base du croisement, mais cette fois-ci, il s'agira du croisement entre le prix et l'indicateur DEMA. Les signaux seront :

Signal d'achat :

Le prix de clôture est supérieur à la valeur de la moyenne mobile exponentielle double (DEMA).

Et, le prix de clôture précédent était inférieur à la valeur DEMA précédente.

Signal de vente :

Le prix de clôture est inférieur à la valeur DEMA

Et, le prix de clôture précédent était supérieur à la valeur DEMA précédente.

Voici le code complet de ce système de trading avec la petite différence d'utiliser la fonction iDEMA pour retourner la poignée de l'indicateur de moyenne mobile exponentielle double, dont les paramètres sont :

  • symbol : pour spécifier le nom du symbole, nous utiliserons _Symbol pour le symbole actuel
  • period : pour spécifier la période de temps, nous utiliserons les données saisies par l'utilisateur, le délai par défaut étant de 1 heure
  • ma_period : pour spécifier la période de la moyenne mobile, nous utiliserons la saisie de l'utilisateur avec une valeur par défaut de 50
  • ma_shift : pour spécifier le décalage horizontal, nous utiliserons 0 car nous n'avons pas besoin de décalage sur le graphique.
  • applied_price : pour spécifier le type de prix, nous utiliserons le prix de clôture pour calculer la moyenne mobile.

Ce sera la même chose que le bloc de code ci-dessous :

//+------------------------------------------------------------------+
//|                                                 iDEMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
int DEMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   DEMA = iDEMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double myDEMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(myDEMAArray,true);
   int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray);
   CopyBuffer(DEMA,0,0,3,myDEMAArray);
   double lastClose=(priceArray[1].close);
   double DEMAVal = NormalizeDouble(myDEMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevDEMAVal = NormalizeDouble(myDEMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(lastClose>DEMAVal && prevClose<prevDEMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(lastClose<DEMAVal && prevClose>prevDEMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

Après avoir compilé ce code, nous pouvons effectuer un backtest sur la même période que celle utilisée pour les autres types précédents, et les paramètres ou entrées de cet indicateur seront les suivants :

  • Taille du lot = 1
  • Période = 1 heure
  • Période MA = 50

Après avoir exécuté le test, nous obtenons les résultats suivants :

Résultats du DEMA

Comme nous pouvons le voir, les figures suivantes doivent être étudiées après avoir testé iDEMA :

  • Bénéfice net : - 961,60 (- 9,62%)
  • DD relatif du solde : 39,62%
  • DD relatif des fonds : 41,15%
  • Facteur de profit : 0,97
  • Gain attendu : - 3,12
  • Facteur de récupération : - 0,18
  • Ratio de Sharpe : - 0,21

Moyenne Mobile Exponentielle Triple (iTEMA)

Nous allons maintenant identifier un autre type de moyenne mobile, la Triple Exponential Moving Average (TEMA), ou Moyenne Mobile Exponentielle Triple, qui a été développée par Patrick Mulloy pour ajouter plus de réactivité à l'indicateur afin qu'il soit adapté au trading à court terme. Dans cet indicateur, nous utilisons des EMA à triple lissage, des EMA à simple lissage et des EMA à double lissage. Ainsi, cet indicateur sera plus proche du prix pour être plus réactif. De la même manière que nous avons utilisé la moyenne mobile exponentielle double, nous pouvons utiliser la TEMA. En plus de sa réponse plus rapide au prix, elle peut être utilisée pour identifier la tendance et les points d'inflexion ou les changements de tendance.

Les étapes suivantes permettent de calculer cet indicateur TEMA :

1. Calcul de la première moyenne mobile exponentielle (EMA)

EMA 1 = EMA de n périodes de prix

2. Calcul de l'EMA de l'EMA 1

EMA 2 = EMA de EMA 1

3. Calcul de l'EMA de l'EMA 2

EMA 3 = EMA de EMA 2

4. Calcul de la TEMA

DEMA = (3 * EMA 1) - (3 * EMA 2) + (EMA 3)

Nous pouvons insérer cet indicateur à partir des indicateurs techniques prêts à l'emploi disponibles dans MetaTrader 5 sans calcul manuel. Nous devons ensuite créer notre système de trading en utilisant cet indicateur TEMA pour le tester et comparer ses résultats avec d'autres types d'indicateurs. Voici donc le code complet pour créer ce système de trading, comme nous l'avons fait précédemment, avec la différence d'utiliser la fonction iTEMA pour retourner le handle de l'indicateur Triple Exponential Moving Average. Ses paramètres sont les mêmes que ceux que nous avons mentionnés pour le DEMA et le SMA.

//+------------------------------------------------------------------+
//|                                                 iTEMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
int TEMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   TEMA = iTEMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double myTEMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(myTEMAArray,true);
   int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray);
   CopyBuffer(TEMA,0,0,3,myTEMAArray);
   double lastClose=(priceArray[1].close);
   double TEMAVal = NormalizeDouble(myTEMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevTEMAVal = NormalizeDouble(myTEMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(lastClose>TEMAVal && prevClose<prevTEMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(lastClose<TEMAVal && prevClose>prevTEMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

Après avoir compilé et exécuté cet indicateur, nous pouvons effectuer un backtest sur la même période afin de comparer ses résultats à ceux d'autres types de moyennes mobiles. Les paramètres suivants sont utilisés pour essayer de fixer tous les paramètres dans le cadre de ce processus de test :

  • Taille du lot = 1
  • Période = 1 heure
  • Période MA = 50

Après l'exécution et l'achèvement de ce test, nous pouvons obtenir les résultats suivants :

Résultats de TEMA

Comme nous pouvons le voir, les chiffres suivants doivent être étudiés :

  • Bénéfice net : - 3973,10 (- 39,74%)
  • DD relatif du solde : 63,98%
  • DD relatif des fonds : 66,06%
  • Facteur de profit : 0,90
  • Gain attendu : - 10,59
  • Facteur de récupération : - 0,52
  • Ratio de Sharpe : - 0,83

Moyenne Mobile Adaptative Fractale (iFrAMA)

Voici le dernier type de moyenne mobile que nous devons identifier dans cet article. Il s'agit de l'indicateur Fractal Adaptive Moving Average (FrAMA), ou Moyenne Mobile Adaptative Fractale, développé par John Ehlers. Il s'agit d'un indicateur de suivi de tendance qui suppose que les prix du marché sont fractals. Il peut également être utilisé pour détecter les tendances et les points d'inflexion. Les étapes suivantes permettent de le calculer :

 FrAMA

Nous pouvons insérer cet indicateur à partir de l'indicateur technique prêt à l'emploi disponible dans MetaTrader 5. Nous devons maintenant créer le même système de trading avec la même stratégie, mais nous utiliserons l'indicateur FrAMA à la place ici pour comparer ses résultats après avoir testé d'autres types également. La stratégie est le croisement entre le prix et l'indicateur FrAMA : lorsque le prix passe au-dessus du FrAMA, il s'agit d'un signal d'achat et lorsque le prix passe en dessous du FrAMA, il s'agit d'un signal de vente.

Signal d'achat :

Le prix de clôture est supérieur à la valeur de la moyenne mobile adaptative fractale FrAMA.

Et, le prix de clôture précédent était inférieur à la valeur FrAMA précédente.

Signal de vente :

Le prix de clôture est inférieur à la valeur FrAMA

Et, le prix de clôture précédent était supérieur à la valeur FrAMA précédente.

Le code suivant est le code complet pour créer ce système de trading. Il sera le même que celui que nous avons mentionné précédemment dans d'autres types mais nous utiliserons la fonction iFrAMA pour retourner la poignée de la moyenne mobile adaptative fractale. Ses paramètres sont :

  • symbol : pour spécifier le nom du symbole, nous utiliserons _Symbol pour le symbole actuel
  • period : pour spécifier la période de temps qui sera utilisée par l'utilisateur, avec une valeur par défaut de 1 heure.
  • ma_period : pour spécifier la période de la moyenne mobile, nous utiliserons la saisie de l'utilisateur avec une valeur par défaut de 50
  • ma_shift : pour spécifier le décalage horizontal, nous utiliserons 0 
  • applied_price : pour spécifier le type de prix, nous utiliserons le prix de clôture
//+------------------------------------------------------------------+
//|                                                iFrAMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
int FrAMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   FrAMA = iFrAMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double myFrAMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(myFrAMAArray,true);
   int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray);
   CopyBuffer(FrAMA,0,0,3,myFrAMAArray);
   double lastClose=(priceArray[1].close);
   double FrAMAVal = NormalizeDouble(myFrAMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevFrAMAVal = NormalizeDouble(myFrAMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(lastClose>FrAMAVal && prevClose<prevFrAMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(lastClose<FrAMAVal && prevClose>prevFrAMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

Après avoir compilé et exécuté cet EA pour tester cette stratégie en utilisant l'indicateur FrAMA avec les mêmes paramètres ou entrées :

  • Taille du lot : 1
  • Période : 1 heure
  • Période de la MA : 50

Nous testons cet EA sur la même période que toutes les autres moyennes mobiles mentionnées, et nous obtenons les résultats suivants :

Résultats du FrAMA

Comme nous pouvons le constater, les chiffres les plus importants que nous devons étudier sont les suivants :

  • Bénéfice net : - 2993,70 (- 29,94%)
  • DD relatif du solde : 73,28%
  • DD relatif des fonds : 74,81%
  • Facteur de profit : 0,.93
  • Gain attendu : - 6,45
  • Facteur de récupération : - 0,33
  • Ratio de Sharpe : - 0,46

Comparaison des résultats avec ceux de la Moyenne Mobile Simple (SMA)

Dans cette partie, je fournirai une comparaison des résultats de chaque type de moyenne mobile mentionné. Vous devez savoir que j'essaierai de fournir les meilleurs résultats possibles, mais chaque moyenne mobile peut donner des résultats différents si nous l'optimisons et si nous changeons les périodes ou les périodes testées, car comme nous le savons, la moyenne mobile peut donner des résultats différents en fonction des paramètres de l'indicateur et des conditions du marché.

L'objectif principal ici est de fournir les mêmes conditions autant que possible pour voir s'il y a un type meilleur que les autres avec les meilleurs réglages que nous pouvons choisir de notre point de vue. Mais pour comprendre ce que nous recherchons, nous avons besoin de voir les mesures les plus importantes dans leur plus grande performance :

  • Bénéfice Net (Net Profit) : La valeur la plus élevée est la meilleure
  • Le Drawdown (DD) : Le plus bas est le meilleur
  • Facteur de Profit (Profit Factor) : Le plus haut est le meilleur
  • Gain attendu : La valeur la plus élevée est la meilleure
  • Facteur de récupération : Le plus élevé est le meilleur
  • Ratio de Sharpe : Le ratio de Sharpe le plus élevé est le meilleur

Nous allons maintenant comparer les résultats de la moyenne mobile simple précédente avec d'autres types de moyennes mobiles basées sur ce contexte précédent dans le tableau suivant :

Mesures SMA AMA DEMA TEMA FrAMA
Bénéfice net 2700,30 (27%) 3638,20 (36.39%) - 961,60 (- 9.62%) - 3973,10 (- 39.74%) - 2993,70 (- 29.94%)
Drawdown Relatif de la Balance 37,07% 22,48% 39,62% 63,98% 73,28%
Drawdown Relatif des Fonds  41,76% 35,53% 41,15% 66,06% 74,81%
Facteur de Profit 1,10 1,31 0,97 0,90 0,.93
Gain Attendu 12,68 35,67 - 3,12 - 10,59 - 6,45
Facteur de Récupération 0,45 0,65 - 0,18 - 0,52 - 0,33
Ratio de Sharpe 0,57 0,86 - 0,21 - 0,83 - 0,46

D'après les résultats de tous nos tests, nous avons deux types qui ont les meilleures performances en fonction des paramètres et de la période testée. Il s'agit de la moyenne mobile simple et de la moyenne mobile adaptative. La meilleure est la moyenne mobile adaptative. C'est le cas :

  • Le bénéfice net le plus élevé
  • Le drawdown de la balance le plus bas
  • Le drawdown des fonds le plus bas
  • Le meilleur facteur de profit
  • Le gain attendu le plus élevé
  • Le facteur de récupération plus élevé
  • Le ratio de Sharpe le plus élevé

Comme nous l'avons mentionné précédemment, nous pouvons obtenir de meilleurs résultats en optimisant davantage les paramètres et les stratégies, mais l'objectif ici est de comprendre et d'appliquer le processus de test sur un exemple réel, puis d'utiliser le même processus pour n'importe quel objectif de test.

Conclusion

Dans cet article, nous avons examiné les performances des types de moyennes mobiles suivants :

  • La Moyenne Mobile Adaptative (AMA)
  • La Moyenne Mobile Exponentielle Double (DEMA)
  • La Moyenne Mobile Exponentielle Triple (TEMA)
  • La Moyenne Mobile Adaptative Fractale (FrAMA)

Nous avons créé des systèmes de trading pour chaque type de moyenne mobile et nous avons comparé leurs résultats avec la moyenne mobile simple, qui est le type de moyenne mobile le plus répandu. D'après les résultats des tests, nous avons constaté que les meilleurs résultats étaient générés par la moyenne mobile simple et la moyenne mobile adaptative, la meilleure étant la moyenne adaptative (AMA). Nous avons analysé et comparé les paramètres suivants pour identifier le gagnant :

  • Bénéfice net
  • Drawdown (DD)
  • Facteur de Profit
  • Gain Attendu
  • Facteur de Récupération
  • Ratio de Sharpe

Les tests sont un sujet très important dans le domaine du trading. Je vous encourage donc à tester davantage de stratégies. Outre l'évaluation de la stratégie elle-même, elle peut vous apporter des informations inattendues, car chaque test permet d'approfondir votre compréhension.

Merci pour le temps que vous avez consacré à la lecture de cet article. J'espère que cet article vous a été utile et qu'il a apporté une valeur ajoutée à vos connaissances. Si vous souhaitez lire d'autres articles sur la création de systèmes de trading basés sur les indicateurs techniques populaires tels que RSI, MACD, Stochastique, Bandes de Bollinger, et d'autres sujets, vous pouvez consulter mes articles à travers les Publications, j'espère qu'ils vous seront utiles également.

Traduit de l’anglais par MetaQuotes Ltd.
Article original : https://www.mql5.com/en/articles/13130

Fichiers joints |
SMA_System.mq5 (2.07 KB)
iAMA_System.mq5 (2.15 KB)
iDEMA_System.mq5 (2.06 KB)
iTEMA_System.mq5 (2.06 KB)
iFrAMA_System.mq5 (2.08 KB)
Derniers commentaires | Aller à la discussion (1)
go123
go123 | 26 févr. 2024 à 03:27
Est-ce que je peux faire du profit en utilisant une seule moyenne adaptative pour un cycle de 1 heure sur le forex ? Pourquoi est-ce que je perds de l'argent sur la plupart des produits forex lorsque je les backtestes ?
Comment Échanger des Données : Une DLL pour MQL5 en 10 minutes Comment Échanger des Données : Une DLL pour MQL5 en 10 minutes
Maintenant, peu de développeurs se rappellent de la façon d'écrire une DLL simple et des caractéristiques spéciales des différentes liaisons système. À l'aide de plusieurs exemples, je vais tenter de montrer l'ensemble du processus de création de la DLL simple en 10 minutes, ainsi que de discuter de certains détails techniques de notre implémentation de liaison. Je vais montrer étape par étape le processus de la création de DLL dans Visual Studio avec des exemples d'échange de différents types de variables (nombres, tableaux, chaînes, etc.). En outre, je vais vous expliquer comment protéger votre terminal client des plantages dans les DLL personnalisées.
Démarrer avec MQL5 Algo Forge Démarrer avec MQL5 Algo Forge
Nous présentons MQL5 Algo Forge — un portail dédié aux développeurs de trading algorithmique. Il combine la puissance de Git avec une interface intuitive pour gérer et organiser les projets au sein de l'écosystème MQL5. Vous pouvez y suivre des auteurs intéressants, former des équipes et collaborer à des projets de trading algorithmique.
L'Histogramme des prix (Profile du Marché) et son implémentation  en MQL5 L'Histogramme des prix (Profile du Marché) et son implémentation en MQL5
Le Profile du Marché a été élaboré par le brillant penseur Peter Steidlmayer. Il a suggéré l’utilisation de la représentation alternative de l'information sur les mouvements de marché « horizontaux » et « verticaux » qui conduit à un ensemble de modèles complètement différent. Il a assumé qu'il existe une impulsion sous-jacente du marché ou un modèle fondamental appelé cycle d'équilibre et de déséquilibre. Dans cet article, j’examinerai l'Histogramme des Prix - un modèle simplifié de profil de marché, et décrirai son implémentation dans MQL5.
Tout ce qu'il faut savoir sur la structure d’un programme MQL5 Tout ce qu'il faut savoir sur la structure d’un programme MQL5
Tout programme, quel que soit le langage de programmation, a une structure spécifique. Dans cet article, vous apprendrez les parties essentielles de la structure d’un programme MQL5 en comprenant les bases de la programmation de chaque partie, ce qui peut être très utile lors de la création de notre système de trading MQL5 ou d'un outil de trading pouvant être exécuté dans MetaTrader 5.