English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
preview
Comment détecter les tendances et les modèles graphiques à l'aide de MQL5

Comment détecter les tendances et les modèles graphiques à l'aide de MQL5

MetaTrader 5Trading |
1 926 18
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Introduction

En tant que traders, nous utilisons tous des graphiques et nous essayons de les lire correctement afin d'être en mesure de comprendre les différents scénarios qui peuvent se produire dans l'action des prix et de prendre la bonne décision. Parce que le graphique contient de nombreux modèles qui peuvent apparaître et qui sont utiles pour prédire un mouvement de prix potentiel si nous les réalisons. Par conséquent, si nous disposons d'outils utiles qui peuvent nous aider à le faire facilement et avec précision, je pense que ce sera une bonne chose. Dans cet article, j'essaierai de fournir quelques outils utiles dans ce contexte, en expliquant comment nous pouvons détecter quelque chose qui apparaît sur le graphique, les modèles de prix que nous devons tous lire, ces modèles sont les mêmes que les tendances ou les modèles graphiques qui peuvent être formés par l'action des prix.

Nous aborderons ce sujet à travers les thèmes suivants : 

Après avoir lu cet article, vous serez en mesure de détecter les hauts et les bas, d'identifier les types de tendances, les doubles sommets et les bas en conséquence. Vous devez donc essayer d'écrire les codes mentionnés par vous-même et vous devez tester et développer ce dont vous avez besoin pour obtenir de meilleures informations et de meilleurs résultats avant de l'utiliser sur votre compte réel. L'objectif principal de cet article est de comprendre l'idée principale de la détection des hauts, des bas et des motifs graphiques pour développer votre code. Cela vous permettra de détecter des motifs significatifs plus ou moins connus, car il existe beaucoup de motifs visibles sur le graphique pouvant changer la donne pour votre trading si vous comprenez comment en tirer profit.

Nous utiliserons dans cet article l'IDE MQL5 (MetaQuotes Language) qui est intégré au terminal de trading MetaTrader 5. Si vous ne savez pas comment utiliser MQL5 et que vous voulez apprendre à télécharger MetaTrader 5 et à utiliser MQL5 pour écrire du code, vous pouvez lire la rubrique Écrire du code MQL5 dans MetaEditor de mon article précédent.

Avertissement : Toutes les informations données dans cet article sont fournies "en l'état", uniquement à des fins d'information et ne sont aucunement données à des fins de trading ou de conseil. Ces informations ne garantissent aucun type de 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.

Détection des Hauts et des Bas

Dans cette partie, nous commencerons par détecter les hauts et les bas sur le graphique à l'aide de MQL5. Puis nous l'utiliserons comme base pour déclarer nos conditions en fonction de chaque modèle de graphique. Tout d'abord, revoyons ensemble la définition des hauts et des bas :

Les Hauts

Haut signifie qu'il y a eu un mouvement à la hausse jusqu'à un niveau spécifique dû à la force des acheteurs, puis les vendeurs apparaissent et poussent le prix à la baisse à partir de ce niveau élevé. La figure suivante est un exemple.   

Haut

Les Bas

Bas signifie qu'il y a eu un mouvement à la baisse jusqu'à un niveau spécifique dû à la force des vendeurs, puis les acheteurs apparaissent et poussent le prix à la hausse à partir de ce niveau bas. La figure suivante est un exemple.

Bas

Après avoir identifié ces deux niveaux de prix importants, nous devons créer un programme MQL5 ou un Expert Advisor capable de détecter ces mouvements. Il existe de nombreuses méthodes pour y parvenir et nous allons en présenter une dans les lignes qui suivent.

Nous devons déterminer des niveaux de prix spécifiques (haut et bas), puis nous nous dirigerons vers d'autres niveaux de prix spécifiques (haut et bas) et nous comparerons le haut au haut et le bas au bas pour déterminer si nous avons un autre haut ou un autre bas. Pour ce faire, nous devons suivre les étapes spécifiques suivantes.

Créez une fonction en dehors de la portée la fonction OnTick() pour renvoyer le plus haut ou le plus bas. Nous la nommerons getNextMove, elle retournera une variable de type entier, et ses paramètres sont les suivants :

  • int move : pour déterminer si le mouvement est haut ou bas.
  • int count : pour déterminer le compte lié à la variable startPos.
  • int startPos : pour déterminer la position de départ.
int getNextMove(int move, int count, int startPos)

Dans cette fonction, nous devons effectuer les vérifications suivantes avec l'instruction if pour identifier la valeur des paramètres de la fonction : nous devons vérifier si la valeur startPos est inférieure à 0, nous devons ajouter la valeur startPos à la valeur de comptage et initialiser startPos à 0 pour commencer à partir de la barre actuelle.

   if(startPos<0)
     {
      count +=startPos;
      startPos =0;
     }

Nous avons maintenant identifié les variables count et startPos dans la fonction. La variable move sera retournée avec l'opérateur return, qui met fin à l'exécution de la fonction et avec l'opérateur ternaire (?:) qui consiste en 3 expressions : la première renvoie une donnée de type bool. Si elle est vraie, la deuxième expression est exécutée ; si elle est fausse, la troisième expression est exécutée.

Nous spécifierons donc la variable move égale à high dans le premier opérateur. Si c’est vrai, la valeur la plus élevée sera renvoyée (High) et si c'est faux, la valeur la plus basse sera renvoyée (Low).

Pour vérifier si le mouvement est élevé, nous utiliserons le fonction MODE_HIGH qui est l'un des identificateurs de série de temps utilisé dans les fonctions iHighest() et iLowest() pour renvoyer le prix le plus élevé. Pour que les paramètres des fonctions iHighest et iLowest renvoient l'indice de la valeur la plus élevée et de la valeur la plus basse, il convient de procéder comme suit :

  • symbol : nous utiliserons Symbol() pour renvoyer le nom du symbole actuel sous la forme d'une chaîne de caractères.
  • timeframe : nous utiliserons Period() pour renvoyer la période actuelle sous la forme d'un ENUM_TIMEFRAMES.
  • type : nous utiliserons ENUM_SERIESMODE pour renvoyer le type de mouvement, comme un identifiant de série temporelle. Ce type de données correspondra à la valeur la plus élevée de l'indice iHighest et à la valeur la plus basse de l'indice iLowest.
  • count : nous utiliserons la variable entière count pour renvoyer le nombre d'éléments.
  • start : nous utiliserons la variable entière startPos pour renvoyer l'index.
   return((move==MODE_HIGH)?
          iHighest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos):
          iLowest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos));

Après avoir créé cette fonction qui renverra le prochain mouvement, nous créerons une autre fonction, qui sera la principale fonction pour obtenir le plus haut ou le plus bas du mouvement actuel. Son nom sera getmove avec 3 variables entières comme paramètres (move, count et startPos).

int getmove(int move, int count, int startPos)

Dans cette fonction, nous devons vérifier si le mouvement n'est pas égal à MODE_HIGH ou MODE_LOW, la valeur renvoyée sera -1.

if(move!=MODE_HIGH && move!=MODE_LOW)
      return (-1);

Création d'une nouvelle variable entière currentBar et affectation de startPos à cette variable.

int currentBar=startPos;

Création d'une nouvelle variable entière moveReturned à laquelle sera affectée le retour de la fonction getNextMove, appelée avec les paramètres suivants : move, (count*2+1), currentBar-count.

int moveReturned=getNextMove(move,count*2+1,currentBar-count);

Création d’une boucle While pour vérifier une expression. Si elle est vraie, l'opérateur sera exécuté. Ici, l'expression que nous devons vérifier est si moveReturned est différent de currentBar. Si c'est vrai, les opérateurs que nous devons exécuter sont :

  • Mise à jour de la variable currentBar avec getNextMove, avec les paramètres move, count et currentBar+1.
  • Mise à jour de la variable moveReturned avec getNextMove, avec les paramètres move, count*2+1 et currentBar-count.
   while(moveReturned!=currentBar)
     {
      currentBar=getNextMove(move,count,currentBar+1);
      moveReturned=getNextMove(move,count*2+1,currentBar-count);
     }

Utilisez ensuite la fonction return pour mettre fin à la fonction en renvoyant la valeur de la barre actuelle.

return(currentBar);

Ensuite, nous allons entrer dans la fonction OnTick() et appeler ce qui a permis de détecter les hauts et les bas. Nous allons tout d'abord créer 3 variables entières :

   int checkBars= 5; 
   int move1;
   int move2;

Mise à jour de move1 et move2 avec notre fonction getmove (avec les paramètres MODE_HIGH, checkBars et 0 pour move1, et MODE_HIGH, checkBars et move1+1 pour move2) pour détecter les deux sommets.

   move1=getmove(MODE_HIGH,checkBars,0);
   move2=getmove(MODE_HIGH,checkBars,move1+1);

Créez un objet ligne au-dessus de ces deux hauts en suivant les étapes suivantes :

Suppression d'une ligne existante à l'aide de la fonction ObjectDelete qui supprime un objet portant un nom. Cette fonction comporte plusieurs paramètres, dont le premier est chart_id, qui détermine l'identifiant du graphique. Nous utiliserons 0 pour le graphique actuel. Le deuxième paramètre est le nom. Pour déterminer le nom de l'objet, nous utiliserons topLine comme chaîne de caractères.

ObjectDelete(0,"topLine");

Création d'un nouvel objet topLine à l'aide de la fonction ObjectCreate qui crée un nouvel objet avec new. Ses paramètres sont :

  • chart_id : nous utiliserons 0 pour renvoyer un type long comme identifiant du graphique.
  • name : nous utiliserons "topLine" pour renvoyer une chaîne de caractères comme nom de l'objet.
  • type : nous utiliserons OBJ_TREND pour renvoyer un type ENUM_OBJECT ou le type d'objet.
  • nwin : nous utiliserons 0 pour le graphique actuel comme index de fenêtre.
  • time1 : pour déterminer l'heure de l'ancrage move2 et renvoyer une date. Nous utiliserons iTime(Symbol(), Period(), move2)
  • price1 : pour déterminer le prix de l'ancre move2 et retourner un type double. Nous utiliserons iHigh(Symbol(), Period(), move2).
  • timeN=0 : pour déterminer l'heure de l'ancrage move1 et renvoyer une date. Nous utiliserons iTime(Symbol(), Period(), move1).
  • priceN=0 : pour déterminer le prix de l'ancre move1 et retourner un type double. Nous utiliserons iHigh(Symbol(), Period(), move1).

Comme nous pouvons le voir, la fonction iHigh renvoie le prix le plus élevé de la barre (ses paramètres sont le symbole, la période et le décalage) et la fonction iTime renvoie l'heure d'ouverture de la barre (ses paramètres sont les mêmes que ceux de la fonction iHigh).

ObjectCreate(0,"topLine",OBJ_TREND,0,iTime(Symbol(),Period(),move2),iHigh(Symbol(),Period(),move2),iTime(Symbol(),Period(),move1),iHigh(Symbol(),Period(),move1));

Définition d'une couleur, d'une largeur spécifique et d'un type de ligne pour cet objet créé à l'aide de la fonction ObjectSetInteger. Ses paramètres sont :

  • chart_id : pour déterminer l'identifiant du graphique, qui sera 0.
  • name : il s'agit du nom de l'objet, qui sera "TopLine" pour les plus hauts.
  • prop_id : pour déterminer la propriété de l'objet, on utilisera OBJPROP_COLOR pour la couleur, OBJPROP_WIDTH pour la largeur, et OBJPROP_RAY_RIGHT pour le type de ligne.
  • prop_value : pour déterminer la valeur souhaitée, ce sera clrRed pour la couleur, 3 pour la largeur et true pour le type de ligne.
   ObjectSetInteger(0,"topLine",OBJPROP_COLOR,clrRed);
   ObjectSetInteger(0,"topLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"topLine",OBJPROP_RAY_RIGHT,true);

Nous obtenons les deux creux en mettant à jour les variables move1 et move2 de la même manière que nous l'avons fait pour les sommets, mais avec le mode MODE_LOW comme identifiant de la série temporelle.

   move1=getmove(MODE_LOW,checkBars,0);
   move2=getmove(MODE_LOW,checkBars,move1+1);

La suppression et la création de l'objet ligne sous ces deux plus bas sont identiques à ce que nous avons fait pour les plus hauts, avec toutefois quelques différences au niveau du nom de l'objet qui sera "bottomLine" et de couleur verte.

   ObjectDelete(0,"bottomLine");
   ObjectCreate(0,"bottomLine",OBJ_TREND,0,iTime(Symbol(),Period(),move2),iLow(Symbol(),Period(),move2),iTime(Symbol(),Period(),move1),iLow(Symbol(),Period(),move1));
   ObjectSetInteger(0,"bottomLine",OBJPROP_COLOR,clrGreen);
   ObjectSetInteger(0,"bottomLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"bottomLine",OBJPROP_RAY_RIGHT,true);

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

//+------------------------------------------------------------------+
//|                                                   moveFinder.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   int checkBars= 5; 
   int move1;
   int move2;
   move1=getmove(MODE_HIGH,checkBars,0);
   move2=getmove(MODE_HIGH,checkBars,move1+1);
   ObjectDelete(0,"topLine");
   ObjectCreate(0,"topLine",OBJ_TREND,0,iTime(Symbol(),Period(),move2),iHigh(Symbol(),Period(),move2),iTime(Symbol(),Period(),move1),iHigh(Symbol(),Period(),move1));
   ObjectSetInteger(0,"topLine",OBJPROP_COLOR,clrRed);
   ObjectSetInteger(0,"topLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"topLine",OBJPROP_RAY_RIGHT,true);
   move1=getmove(MODE_LOW,checkBars,0);
   move2=getmove(MODE_LOW,checkBars,move1+1);
   ObjectDelete(0,"bottomLine");
   ObjectCreate(0,"bottomLine",OBJ_TREND,0,iTime(Symbol(),Period(),move2),iLow(Symbol(),Period(),move2),iTime(Symbol(),Period(),move1),iLow(Symbol(),Period(),move1));
   ObjectSetInteger(0,"bottomLine",OBJPROP_COLOR,clrGreen);
   ObjectSetInteger(0,"bottomLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"bottomLine",OBJPROP_RAY_RIGHT,true);
  }
int getmove(int move, int count, int startPos)
  {
   if(move!=MODE_HIGH && move!=MODE_LOW)
      return (-1);
   int currentBar=startPos;
   int moveReturned=getNextMove(move,count*2+1,currentBar-count);
   while(moveReturned!=currentBar)
     {
      currentBar=getNextMove(move,count,currentBar+1);
      moveReturned=getNextMove(move,count*2+1,currentBar-count);
     }
   return(currentBar);
  }
int getNextMove(int move, int count, int startPos)
  {
   if(startPos<0)
     {
      count +=startPos;
      startPos =0;
     }
   return((move==MODE_HIGH)?
          iHighest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos):
          iLowest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos));
  }

Après avoir compilé ce code sans erreur et l'avoir exécuté, nous pouvons obtenir deux lignes sur le graphique pour détecter deux sommets avec une ligne rouge au-dessus d'eux et deux creux avec une ligne verte en dessous d'eux. Les exemples suivants sont tirés de mes tests :

moveFinder signal1

Comme nous l'avons vu dans l'exemple précédent, ces deux lignes peuvent représenter un motif sur le graphique pour indiquer le mouvement du prix. Nous pouvons voir dans l'exemple précédent que nous avons un mouvement haussier important car nous avons deux lignes ascendantes et l'angle de la ligne supérieure est plus large que l'angle de la ligne inférieure. Ils peuvent donc être un outil très utile pour interpréter l'action des prix.

Voici un autre exemple avec un schéma différent en fonction d'une action de prix différente :

 moveFinder signal2

Comme nous pouvons le voir sur le graphique précédent, l'action des prix est différente et indique un mouvement différent. Les deux lignes se déplacent parallèlement, mais la ligne inférieure se déplace vers le haut et la ligne supérieure vers le bas, ce qui indique qu'il y a un équilibre entre les acheteurs et les vendeurs, les acheteurs poussant le prix à la hausse et les vendeurs, à la baisse.

Voici un exemple d'un autre schéma d'action sur les prix :

moveFinder signal3

Comme nous pouvons le voir dans le graphique précédent, nous avons une configuration graphique différente avec deux lignes parallèles vers le bas qui peuvent indiquer la force des vendeurs car ils sont capables de pousser les prix vers le bas.

Après avoir appris comment détecter les hauts et les bas sur le graphique dans la partie précédente, nous pouvons développer ce code pour détecter les tendances sur le graphique car nous avons détecté deux hauts et deux bas et c'est ce dont nous avons besoin pour identifier la tendance. La suite de cette partie de l'article concerne l’amélioration du code précédent pour détecter les tendances sur le graphique.

Simplement, les tendances sont le mouvement de l'action des prix. Ce mouvement peut être à la hausse, à la baisse ou sans direction claire (ni à la hausse ni à la baisse). Ces 3 types de tendances sont les mêmes que les suivants :

Tendance haussière

Ce type de mouvement des prix a pour conséquence que les prix continuent à monter pour atteindre des prix plus élevés car les acheteurs sont les plus forts. Ainsi, nous pouvons constater sur le graphique que le prix forme clairement des bas et des hauts plus élevés. La figure suivante est un graphique de ce type :

tendance haussière

Tendance baissière

Ce type de tendance est le scénario opposé au type de tendance haussière. Dans ce type de tendance baissière, les vendeurs sont plus forts que les acheteurs et poussent les prix à la baisse. Ainsi, nous pouvons voir sur le graphique que les prix forment des hauts et des bas plus bas.

Le graphique suivant décrit la situation d'un point de vue visuel :

tendance baissière

Mouvement latéral

Dans ce type, nous ne trouvons pas de mouvement de prix qui puisse être décrit comme une tendance haussière ou baissière. Il s'agit donc de n'importe quelle forme, à l'exception de la tendance haussière ou baissière. Il existe de nombreuses formes, dont les figures suivantes font partie :

noTrend noTrend2 noTrend3

Maintenant, nous devons créer un EA MQL5 qui peut détecter si nous avons une tendance (à la hausse ou à la baisse) ou si nous n'avons pas de tendance (latérale). Le code suivant permet de créer ce type d'EA :

//+------------------------------------------------------------------+
//|                                                  trendFinder.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   int checkBars= 5;
   int high1, high2, low1, low2;
   double highVal1, highVal2, lowVal1, lowVal2;
   high1=getmove(MODE_HIGH,checkBars,0);
   high2=getmove(MODE_HIGH,checkBars,high1+1);
   highVal1=NormalizeDouble(iHigh(_Symbol,_Period,high1),5);
   highVal2=NormalizeDouble(iHigh(_Symbol,_Period,high2),5);
   ObjectDelete(0,"topLine");
   ObjectCreate(0,"topLine",OBJ_TREND,0,iTime(Symbol(),Period(),high2),iHigh(Symbol(),Period(),high2),iTime(Symbol(),Period(),high1),iHigh(Symbol(),Period(),high1));
   ObjectSetInteger(0,"topLine",OBJPROP_COLOR,clrRed);
   ObjectSetInteger(0,"topLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"topLine",OBJPROP_RAY_RIGHT,true);
   low1=getmove(MODE_LOW,checkBars,0);
   low2=getmove(MODE_LOW,checkBars,low1+1);
   lowVal1=NormalizeDouble(iLow(_Symbol,_Period,low1),5);
   lowVal2=NormalizeDouble(iLow(_Symbol,_Period,low2),5);
   ObjectDelete(0,"bottomLine");
   ObjectCreate(0,"bottomLine",OBJ_TREND,0,iTime(Symbol(),Period(),low2),iLow(Symbol(),Period(),low2),iTime(Symbol(),Period(),low1),iLow(Symbol(),Period(),low1));
   ObjectSetInteger(0,"bottomLine",OBJPROP_COLOR,clrGreen);
   ObjectSetInteger(0,"bottomLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"bottomLine",OBJPROP_RAY_RIGHT,true);
   if(lowVal1>lowVal2&&highVal1>highVal2)
     {
      Comment("Uptrend",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
     }
   else
      if(highVal1<highVal2&&lowVal1<lowVal2)
        {
         Comment("Downtrend",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }
      else
        {
         Comment("Sideways",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }
  }
int getmove(int move, int count, int startPos)
  {
   if(move!=MODE_HIGH && move!=MODE_LOW)
      return (-1);
   int currentBar=startPos;
   int moveReturned=getNextMove(move,count*2+1,currentBar-count);
   while(moveReturned!=currentBar)
     {
      currentBar=getNextMove(move,count,currentBar+1);
      moveReturned=getNextMove(move,count*2+1,currentBar-count);
     }
   return(currentBar);
  }
int getNextMove(int move, int count, int startPos)
  {
   if(startPos<0)
     {
      count +=startPos;
      startPos =0;
     }
   return((move==MODE_HIGH)?
          iHighest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos):
          iLowest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos));
  }

Les différences suivantes dans ce code permettent de détecter des tendances.

Création de 4 variables entières pour deux sommets et deux creux, et de 4 variables doubles pour deux sommets et deux creux à l'intérieur de la portée de la fonction OnTick :

   int high1, high2, low1, low2;
   double highVal1, highVal2, lowVal1, lowVal2;

Mise à jour des deux valeurs des hauts (highVal1, highVal2) en utilisant la fonction NormalizeDouble pour arrondir le résultat. Ses paramètres sont :

  • value : le nombre que nous devons normaliser, nous utiliserons la fonction iHigh pour retourner le prix le plus haut. Ses paramètres sont le symbole, qui sera _Symbol pour le symbole actuel, la période qui sera _Period pour la période actuelle, et le décalage d'indice qui sera high1 et high2.
  • digits : le nombre de chiffres après la virgule, sera de 5.
   highVal1=NormalizeDouble(iHigh(_Symbol,_Period,high1),5);
   highVal2=NormalizeDouble(iHigh(_Symbol,_Period,high2),5);

Mise à jour des deux valeurs basses (lowVal1, lowVal2) en utilisant la fonction NormalizeDouble avec les mêmes paramètres que ceux mentionnés précédemment mais avec les différences suivantes :

  • valeur : utiliser la fonction iLow pour renvoyer le prix le plus bas ; ses paramètres sont les mêmes, à l'exception du décalage de l'indice qui sera low1 et low.
   lowVal1=NormalizeDouble(iLow(_Symbol,_Period,low1),5);
   lowVal2=NormalizeDouble(iLow(_Symbol,_Period,low2),5);

Les conditions que nous devons définir pour identifier les tendances. Nous utiliserons l'instruction if. Nous devons laisser l'EA vérifier les 4 valeurs des hauts et des bas en continu, puis décider de leurs positions l'une par rapport à l'autre pour décider si nous avons une tendance (vers le haut ou vers le bas) ou si nous n'avons pas de tendance (latérale).

Condition de la tendance haussière :

Si lowVal1 est supérieur à lowVal2 et qu'en même temps highVal1 est supérieur à highVal2, nous avons une tendance haussière. L'EA doit renvoyer un commentaire sur le graphique avec ce qui suit :

  • Tendance haussière
  • Haut actuel
  • Haut précédent
  • Bas actuel
  • Bas précédent
   if(lowVal1>lowVal2&&highVal1>highVal2)
     {
      Comment("Uptrend",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
     }

Condition de la tendance baissière :

Si highVal1 est inférieur à highVal2 et qu'en même temps lowVal1 est inférieur à lowVal2, nous avons une tendance baissière. L'EA doit renvoyer un commentaire sur le graphique avec ce qui suit :

  • Tendance baissière
  • Haut actuel
  • Haut précédent
  • Bas actuel
  • Bas précédent
   else
      if(highVal1<highVal2&&lowVal1<lowVal2)
        {
         Comment("Downtrend",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }

Condition de latéralité :

Si les positions des 4 valeurs sont autres que des conditions de tendance haussière et baissière, nous avons une tendance latérale. L'EA doit renvoyer ce qui suit comme commentaire sur le graphique :

      else
        {
         Comment("Sideways",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }

Après avoir compilé ce code sans erreur et exécuté son EA, nous pouvons recevoir des signaux de tendances identiques à ceux dont nous avons besoin. Les exemples suivants sont tirés de tests effectués en fonction du type de tendance et de son état.

Tendance haussière

trendFinder - Signal de tendance haussière

Nous pouvons voir dans la figure précédente que nous avons un exemple de tendance haussière car nous avons un plus haut et un plus bas sur l'action des prix de ce graphique. Nous avons donc reçu un signal de tendance haussière sous la forme d'un commentaire dans le coin supérieur gauche du graphique.

Tendance baissière

trendFinder - Signal de tendance baissière

Comme nous pouvons le voir clairement dans le graphique précédent, nous avons une tendance baissière car nous avons un plus haut et un plus bas selon l'action des prix. Nous avons donc reçu un signal de tendance baissière comme commentaire sur le graphique.

Mouvement latéral

trendFinder - Signal latéral

Comme nous pouvons le voir dans l'exemple précédent, nous avons une forme qui diffère de la tendance haussière et de la tendance baissière. Nous avons un haut plus bas et un bas plus haut, ce qui est latéral. Nous avons donc obtenu un signal latéral en guise de commentaire sur le graphique.

Graphique Détection des Doubles Sommets

Après avoir appris à détecter les hauts et les bas, nous avons détecté les tendances en développant le code de base de la détection des hauts et des bas. Ainsi, en réfléchissant, nous pouvons développer le code pour essayer de détecter des graphiques spécifiques ou des modèles d'action de prix pouvant indiquer un mouvement potentiel.

Dans cette partie, je fournirai un exemple de ces modèles graphiques avec peu de changements dans le code pour comprendre l'idée principale. Vous pourrez effectuer plus de changements pour détecter des modèles plus significatifs, en particulier si vous fusionnez des outils techniques. Dans cette partie de l'article, nous verrons l'une des configurations graphiques les plus courantes, à savoir les doubles sommets.

Les doubles sommets sont une configuration graphique que l'on peut voir sur le graphique et qui consiste en des sommets à moitié identiques, ce qui indique qu'il y a une faiblesse dans le pouvoir d'achat et qu'il y a un potentiel de baisse des prix. Il y a de nombreux détails à prendre en compte mais si nous ne mentionnons que sa forme, nous verrons que c'est la même que celle que nous avons mentionnée. Le graphique suivant est un exemple visuel d'une configuration potentielle de double sommet :

Potentiel DT

Si vous l’avez remarqué, nous avons mentionné dans l'exemple précédent qu'il s'agit d'une figure ’potentielle’ et qu'elle sera une figure ’conforme’ lorsque les prix casseront et clôtureront en dessous du plus bas entre les deux plus hauts, comme dans le graphique suivant :

DT

Nous devons maintenant créer un EA MQL5 qui peut être utilisé pour détecter ces deux figures dans MetaTrader 5. Nous avons besoin que l'EA vérifie les deux sommets et les deux creux en continu et qu’il détermine leurs positions l'une par rapport à l'autre pour renvoyer un résultat spécifique basé sur une condition spécifique, qui est la condition de la configuration Double Top. Ainsi, si le sommet actuel est inférieur ou égal au précédent et que, dans le même temps, le creux actuel est supérieur au précédent, il s'agira d'un signal de double sommet potentiel. Si le sommet actuel est inférieur ou égal au précédent et que, dans le même temps, le creux actuel est inférieur au précédent, il s'agit d'un signal de Double Top.

Vous trouverez ci-dessous le code complet pour effectuer cette opération :

//+------------------------------------------------------------------+
//|                                             DT patternFinder.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   int checkBars= 5;
   int high1, high2, low1, low2;
   double highVal1, highVal2, lowVal1, lowVal2;
   high1=getmove(MODE_HIGH,checkBars,0);
   high2=getmove(MODE_HIGH,checkBars,high1+1);
   highVal1=NormalizeDouble(iHigh(_Symbol,_Period,high1),5);
   highVal2=NormalizeDouble(iHigh(_Symbol,_Period,high2),5);
   ObjectDelete(0,"topLine");
   ObjectCreate(0,"topLine",OBJ_TREND,0,iTime(Symbol(),Period(),high2),iHigh(Symbol(),Period(),high2),iTime(Symbol(),Period(),high1),iHigh(Symbol(),Period(),high1));
   ObjectSetInteger(0,"topLine",OBJPROP_COLOR,clrRed);
   ObjectSetInteger(0,"topLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"topLine",OBJPROP_RAY_RIGHT,true);
   low1=getmove(MODE_LOW,checkBars,0);
   low2=getmove(MODE_LOW,checkBars,low1+1);
   lowVal1=NormalizeDouble(iLow(_Symbol,_Period,low1),5);
   lowVal2=NormalizeDouble(iLow(_Symbol,_Period,low2),5);
   ObjectDelete(0,"bottomLine");
   ObjectCreate(0,"bottomLine",OBJ_TREND,0,iTime(Symbol(),Period(),low2),iLow(Symbol(),Period(),low2),iTime(Symbol(),Period(),low1),iLow(Symbol(),Period(),low1));
   ObjectSetInteger(0,"bottomLine",OBJPROP_COLOR,clrGreen);
   ObjectSetInteger(0,"bottomLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"bottomLine",OBJPROP_RAY_RIGHT,true);
   if(highVal1<=highVal2&&lowVal1>lowVal2)
     {
      Comment("Potential Double Top",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
     }

   else
      if(highVal1<=highVal2&&lowVal1<lowVal2)
        {
         Comment("Double Top",
                 "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
                 "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }
      else
         Comment(" ");
  }
int getmove(int move, int count, int startPos)
  {
   if(move!=MODE_HIGH && move!=MODE_LOW)
      return (-1);
   int currentBar=startPos;
   int moveReturned=getNextMove(move,count*2+1,currentBar-count);
   while(moveReturned!=currentBar)
     {
      currentBar=getNextMove(move,count,currentBar+1);
      moveReturned=getNextMove(move,count*2+1,currentBar-count);
     }
   return(currentBar);
  }
int getNextMove(int move, int count, int startPos)
  {
   if(startPos<0)
     {
      count +=startPos;
      startPos =0;
     }
   return((move==MODE_HIGH)?
          iHighest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos):
          iLowest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos));
  }

Les différences dans ce code sont des conditions du modèle.

Dans le cas d'un double sommet potentiel, si la valeur haute highVal1 est inférieure ou égale à la valeur haute highVal2, et que la valeur basse lowVal1 est supérieure à la valeur basse lowVal2, nous devons obtenir un signal sous la forme d'un commentaire sur le graphique avec les valeurs suivantes :

  • Potentiel Double Top
  • Haut actuel
  • Haut précédent
  • Bas actuel
  • Bas précédent
   if(highVal1<=highVal2&&lowVal1>lowVal2)
     {
      Comment("Potential Double Top",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
     }

Dans le cas d'un Double Top, si le highVal1 est inférieur ou égal au highVal2, et que le lowVal1 est inférieur au lowVal2, nous devons obtenir un signal sous forme de commentaire sur le graphique avec les valeurs suivantes :

  • Double Top
  • Haut actuel
  • Haut précédent
  • Bas actuel
  • Bas précédent
   else
      if(highVal1<=highVal2&&lowVal1<lowVal2)
        {
         Comment("Double Top",
                 "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
                 "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }

Dans le cas d'une absence de potentiel ou d'un double top, ne rien renvoyer comme commentaire.

      else
         Comment(" ");

Après avoir compilé ce code sans erreur et exécuté son EA, nous pouvons voir l'exemple suivant de test de signal.

Dans le cas d'un double sommet potentiel :

DT patternFinder signal potentiel

Comme nous pouvons le voir dans le graphique précédent, nous avons un signal potentiel de double sommet car il y a une correspondance avec les conditions prédéfinies, qui sont un bas plus élevé et un haut équivalent.

Dans le cas de Double Top :

 DT patternFinder DT signal

Comme nous pouvons le voir dans le graphique précédent, nous avons un signal de double sommet car il y a une correspondance avec les conditions préétablies, c'est-à-dire un haut plus bas ou équivalent et un bas plus bas.

Graphique Détection des doubles creux

Dans cette partie, nous allons apprendre à détecter la configuration opposée au double sommet, à savoir le double creux. Les doubles creux sont un schéma graphique que l'on peut voir sur le graphique et qui consiste en des bas semi-similaires qui indiquent qu'il y a une faiblesse dans le pouvoir de vente et qu'il y a un potentiel de hausse des prix. Il y a de nombreux détails à prendre en compte mais si nous ne mentionnons que sa forme, nous constaterons qu'elle est la même que celle que nous avons mentionnée. Le graphique suivant est un exemple visuel d'une configuration potentielle de double creux :

DB Potentiel

La configuration de double creux potentiel précédente sera confirmée lorsque les prix casseront et clôtureront au-dessus du plus haut entre les deux plus bas, comme le montre le graphique suivant :

DB

Nous devons créer un autre EA MQL5 qui peut être utilisé pour détecter les deux figures précédentes dans MetaTrader 5. L'EA doit vérifie continuellement les deux bas et les deux hauts et détermine leurs positions l'une par rapport à l'autre pour renvoyer un résultat spécifique basé sur la condition de la configuration Double Bottom. Le même développement simple dans le code sera appliqué avec le cas opposé pour approcher un schéma pratique avec un bas légèrement plus haut ou plus bas non seulement le même haut, Donc si le bas actuel est plus haut ou égal au précédent et en même temps le haut actuel est plus bas que le précédent, mais ce sera un signal de Double Bottom potentiel. Si le bas actuel est supérieur ou égal au précédent et que, dans le même temps, le haut actuel est supérieur au précédent, il s'agit d'un signal de Double Bottom.

Vous trouverez ci-dessous le code complet pour effectuer cette opération :

//+------------------------------------------------------------------+
//|                                             DB patternFinder.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   int checkBars= 5;
   int high1, high2, low1, low2;
   double highVal1, highVal2, lowVal1, lowVal2;
   high1=getmove(MODE_HIGH,checkBars,0);
   high2=getmove(MODE_HIGH,checkBars,high1+1);
   highVal1=NormalizeDouble(iHigh(_Symbol,_Period,high1),5);
   highVal2=NormalizeDouble(iHigh(_Symbol,_Period,high2),5);
   ObjectDelete(0,"topLine");
   ObjectCreate(0,"topLine",OBJ_TREND,0,iTime(Symbol(),Period(),high2),iHigh(Symbol(),Period(),high2),iTime(Symbol(),Period(),high1),iHigh(Symbol(),Period(),high1));
   ObjectSetInteger(0,"topLine",OBJPROP_COLOR,clrRed);
   ObjectSetInteger(0,"topLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"topLine",OBJPROP_RAY_RIGHT,true);
   low1=getmove(MODE_LOW,checkBars,0);
   low2=getmove(MODE_LOW,checkBars,low1+1);
   lowVal1=NormalizeDouble(iLow(_Symbol,_Period,low1),5);
   lowVal2=NormalizeDouble(iLow(_Symbol,_Period,low2),5);
   ObjectDelete(0,"bottomLine");
   ObjectCreate(0,"bottomLine",OBJ_TREND,0,iTime(Symbol(),Period(),low2),iLow(Symbol(),Period(),low2),iTime(Symbol(),Period(),low1),iLow(Symbol(),Period(),low1));
   ObjectSetInteger(0,"bottomLine",OBJPROP_COLOR,clrGreen);
   ObjectSetInteger(0,"bottomLine",OBJPROP_WIDTH,3);
   ObjectSetInteger(0,"bottomLine",OBJPROP_RAY_RIGHT,true);
   if(lowVal1>=lowVal2&&highVal1<highVal2)
     {
      Comment("Potential Double Bottom",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
     }
   else
      if(lowVal1>=lowVal2&&highVal1>highVal2)
        {
         Comment("Double Bottom",
                 "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
                 "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }
      else
         Comment(" ");
  }
int getmove(int move, int count, int startPos)
  {
   if(move!=MODE_HIGH && move!=MODE_LOW)
      return (-1);
   int currentBar=startPos;
   int moveReturned=getNextMove(move,count*2+1,currentBar-count);
   while(moveReturned!=currentBar)
     {
      currentBar=getNextMove(move,count,currentBar+1);
      moveReturned=getNextMove(move,count*2+1,currentBar-count);
     }
   return(currentBar);
  }
int getNextMove(int move, int count, int startPos)
  {
   if(startPos<0)
     {
      count +=startPos;
      startPos =0;
     }
   return((move==MODE_HIGH)?
          iHighest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos):
          iLowest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos));
  }

Les différences dans ce code sont des conditions du modèle.

Dans le cas d'un double creux potentiel, si la valeur basse 1 est supérieure ou égale à la valeur basse 2 et que la valeur haute 1 est inférieure à la valeur haute 2, nous devons obtenir un signal sous la forme d'un commentaire sur le graphique avec les valeurs suivantes :

  • Double creux potentiel
  • Haut actuel
  • Haut précédent
  • Bas actuel
  • Bas précédent
   if(lowVal1>=lowVal2&&highVal1<highVal2)
     {
      Comment("Potential Double Bottom",
              "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
              "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
     }

Dans le cas du Double Sommet, si le lowVal1 est supérieur ou égal au lowVal2 et que le highVal1 est supérieur au highVal2, nous devons obtenir un signal sous forme de commentaire sur le graphique avec les valeurs suivantes :

  • Double Creux
  • Haut actuel
  • Haut précédent
  • Bas actuel
  • Bas précédent
   else
      if(lowVal1>=lowVal2&&highVal1>highVal2)
        {
         Comment("Double Bottom",
                 "\nCurrent High ",highVal1,"\nPrevious High ",highVal2,
                 "\nCurrent Low ",lowVal1,"\nPrevious Low ",lowVal2);
        }

Après avoir compilé ce code sans erreur et exécuté son EA, nous pouvons obtenir les signaux suivants comme exemples de tests.

Dans le cas du double creux potentiel :

 DB patternFinder signal potentiel

Comme nous pouvons le voir dans le graphique précédent, nous avons un signal potentiel de double creux car il y a une correspondance avec les conditions prédéfinies, à savoir un haut plus bas et un bas équivalent ou plus haut.

Dans le cas du Double Creux :

DB

Comme nous pouvons le voir dans le graphique précédent, nous avons un signal de double creux car il y a une correspondance avec les conditions préétablies, à savoir un haut plus élevé et un bas équivalent ou plus élevé.

Conclusion

L'action des prix est la chose la plus importante pour les traders car ils négocient en se basant sur la compréhension de cette action des prix. S'ils la comprennent très bien, ils peuvent prendre de meilleures décisions d'investissement ou de trading. L'action des prix forme de nombreux modèles que nous devons également lire et comprendre. Nous avons essayé dans cet article de fournir ce qui peut faciliter cette tâche en créant des systèmes MQL5 à utiliser dans le terminal de trading MetaTrader 5.

Nous avons appris à détecter les tendances (haussières, baissières et latérales) et l'une des configurations graphiques les plus populaires, à savoir le double sommet et son opposé, le double creux, après avoir appris à détecter les hauts et les bas. Nous avons également fourni une bonne base pour chaque concept de tendance et de type de graphique pour développer les programmes ou les systèmes mentionnés en fonction des conditions qui vous conviennent. De plus, après avoir appris le concept principal pour créer un système qui peut détecter les hauts et les bas, vous pouvez améliorer ce système pour être capable de détecter d'autres configurations graphiques comme la tête et les épaules, les triangles, les rectangles...etc. J'espère que cet article vous sera utile pour développer votre trading et votre système de trading en conséquence afin d'obtenir de meilleurs résultats dans votre activité de trading.

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

Fichiers joints |
moveFinder.mq5 (2.24 KB)
trendFinder.mq5 (3.18 KB)
Derniers commentaires | Aller à la discussion (18)
Juan Luis De Frutos Blanco
Juan Luis De Frutos Blanco | 20 avr. 2023 à 20:49
Je suis ravi d'avoir lu votre article, Mohamed.
Je me suis permis (j'espère que vous n'en prendrez pas ombrage) d'unifier les codes pour voir les résultats regroupés : C'est ce à quoi je pense pour continuer à faire des pas vers la création d'un éventuel EA.
Qui est encouragé à mettre en place des commandes aux différents états graphiques ?

Je vous prie d'agréer, Madame, Monsieur, l'expression de mes salutations distinguées.

//+------------------------------------------------------------------+
//|TrendDTDB.mq5 |
//+------------------------------------------------------------------+

input int checkBars= 20;
   int high1, high2, low1, low2;
   double highVal1, highVal2, lowVal1, lowVal2;

void OnInit()
{
   PonEtiquetas();
}


void OnTick()
{
   high1=getmove(MODE_HIGH,checkBars,0);
   high2=getmove(MODE_HIGH,checkBars,high1+1);
   highVal1=NormalizeDouble(iHigh(_Symbol,_Period,high1),5);
   highVal2=NormalizeDouble(iHigh(_Symbol,_Period,high2),5);
   
   low1=getmove(MODE_LOW,checkBars,0);
   low2=getmove(MODE_LOW,checkBars,low1+1);
   lowVal1=NormalizeDouble(iLow(_Symbol,_Period,low1),5);
   lowVal2=NormalizeDouble(iLow(_Symbol,_Period,low2),5);

// DOBLE TECHO
   if(highVal1<=highVal2&&lowVal1>lowVal2){ObjectSetString((int)_Symbol,"LS0",OBJPROP_TEXT,0,"Potencial DT-DOBLE TECHO"); DibujaArriba("DTP",clrGreen);}
   else if(highVal1<=highVal2&&lowVal1<lowVal2){ObjectSetString((int)_Symbol,"LS0",OBJPROP_TEXT,0,"DT-DOBLE TECHO");DibujaArriba("DT",clrGreen);}
        else{ObjectSetString((int)_Symbol,"LS0",OBJPROP_TEXT,0,"."); ObjectsDeleteAll(0,"DT",0,-1);}

//DOBLE SUELO
   if(lowVal1>=lowVal2&&highVal1<highVal2){ObjectSetString((int)_Symbol,"LS1",OBJPROP_TEXT,0,"Potencial DS-DOBLE SUELO"); DibujaAbajo("DSP",clrRed);}
   else if(lowVal1>=lowVal2&&highVal1>highVal2){ObjectSetString((int)_Symbol,"LS1",OBJPROP_TEXT,0,"DT-DOBLE TECHO");DibujaArriba("DS",clrGreen);}
        else{ObjectSetString((int)_Symbol,"LS1",OBJPROP_TEXT,0,"."); ObjectsDeleteAll(0,"DS",0,-1);}

// CHASSEUR DE TENDANCES
   if(lowVal1>lowVal2&&highVal1>highVal2){ObjectSetString((int)_Symbol,"LS2",OBJPROP_TEXT,0,"UP-Tendencia ALCISTA");DibujaArriba("T",clrGreen);}
   else if(highVal1<highVal2&&lowVal1<lowVal2){ObjectSetString((int)_Symbol,"LS2",OBJPROP_TEXT,0,"DOWN-Tendencia BAJISTA");DibujaAbajo("T",clrRed);}
        else{ObjectSetString((int)_Symbol,"LS2",OBJPROP_TEXT,0,"SW-Tendencia LATERAL");  ObjectsDeleteAll(0,"T",0,-1);}
      
}


int getmove(int move, int count, int startPos)
{
   if(move!=MODE_HIGH && move!=MODE_LOW)
      return (-1);
   int currentBar=startPos;
   int moveReturned=getNextMove(move,count*2+1,currentBar-count);
   while(moveReturned!=currentBar)
     {
      currentBar=getNextMove(move,count,currentBar+1);
      moveReturned=getNextMove(move,count*2+1,currentBar-count);
     }
   return(currentBar);
}
  
int getNextMove(int move, int count, int startPos)
{
   if(startPos<0)
     {
      count +=startPos;
      startPos =0;
     }
   return((move==MODE_HIGH)?
          iHighest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos):
          iLowest(Symbol(),Period(),(ENUM_SERIESMODE)move,count,startPos));
}
  
void DibujaArriba(string Nombre, int mColor)
{ 
   ObjectDelete(0,Nombre);
   ObjectCreate(0,Nombre,OBJ_TREND,0,iTime(Symbol(),Period(),high2),iHigh(Symbol(),Period(),high2),iTime(Symbol(),Period(),high1),iHigh(Symbol(),Period(),high1));
   ObjectSetInteger(0,Nombre,OBJPROP_COLOR,mColor);
   ObjectSetInteger(0,Nombre,OBJPROP_WIDTH,1);
   ObjectSetInteger(0,Nombre,OBJPROP_RAY_RIGHT,true);

}

void DibujaAbajo(string Nombre, int mColor)
{ 
   ObjectDelete(0,Nombre);
   ObjectCreate(0,Nombre,OBJ_TREND,0,iTime(Symbol(),Period(),low2),iLow(Symbol(),Period(),low2),iTime(Symbol(),Period(),low1),iLow(Symbol(),Period(),low1));
   ObjectSetInteger(0,Nombre,OBJPROP_COLOR,mColor);
   ObjectSetInteger(0,Nombre,OBJPROP_WIDTH,1);
   ObjectSetInteger(0,Nombre,OBJPROP_RAY_RIGHT,true);
}

void PonEtiquetas()
{ 
   ObjectCreate((int)_Symbol,"LS0", OBJ_LABEL, 0, 0, 0);
   ObjectSetString(0,"LS0",OBJPROP_FONT,"Arial");
   ObjectSetInteger(0,"LS0",OBJPROP_FONTSIZE,25); 
   ObjectSetInteger(0,"LS0",OBJPROP_COLOR,clrGreen);    
   ObjectSetInteger(0,"LS0", OBJPROP_CORNER, 4);   
   ObjectSetInteger(0,"LS0", OBJPROP_XDISTANCE, 800);
   ObjectSetInteger(0,"LS0", OBJPROP_YDISTANCE, 50);
   ObjectSetString((int)_Symbol,"LS0",OBJPROP_TEXT,0,"-");  
   
   ObjectCreate((int)_Symbol,"LS1", OBJ_LABEL, 0, 0, 0);
   ObjectSetString(0,"LS1",OBJPROP_FONT,"Arial");
   ObjectSetInteger(0,"LS1",OBJPROP_FONTSIZE,25); 
   ObjectSetInteger(0,"LS1",OBJPROP_COLOR,clrRed);    
   ObjectSetInteger(0,"LS1", OBJPROP_CORNER, 4);   
   ObjectSetInteger(0,"LS1", OBJPROP_XDISTANCE, 800);
   ObjectSetInteger(0,"LS1", OBJPROP_YDISTANCE, 90);
   ObjectSetString((int)_Symbol,"LS1",OBJPROP_TEXT,0,"-");  
   
   ObjectCreate((int)_Symbol,"LS2", OBJ_LABEL, 0, 0, 0);
   ObjectSetString(0,"LS2",OBJPROP_FONT,"Arial");
   ObjectSetInteger(0,"LS2",OBJPROP_FONTSIZE,25); 
   ObjectSetInteger(0,"LS2",OBJPROP_COLOR,clrWhiteSmoke);    
   ObjectSetInteger(0,"LS2", OBJPROP_CORNER, 4);   
   ObjectSetInteger(0,"LS2", OBJPROP_XDISTANCE, 800);
   ObjectSetInteger(0,"LS2", OBJPROP_YDISTANCE, 130);
   ObjectSetString((int)_Symbol,"LS2",OBJPROP_TEXT,0,"-");        
}
JRandomTrader
JRandomTrader | 27 sept. 2023 à 10:06
La création d'objets graphiques à chaque tic n'est pas une bonne idée.
Aitor Esteban Yague
Aitor Esteban Yague | 4 oct. 2023 à 17:25
Très bonne contribution, félicitations, merci beaucoup !
Hilario Miguel Ofarril Gonzalez
Hilario Miguel Ofarril Gonzalez | 6 oct. 2023 à 07:51
Assez clair et visible .et intéressant
Echo1Zulu1
Echo1Zulu1 | 25 août 2024 à 00:09

Bonjour Mohamed, j'ai lu votre article et votre code. Il m'a beaucoup aidé.


Il y a une seule chose que je ne comprends pas. Où trouvez-vous la fonction "getmove" ? J'ai essayé de la chercher sur MTQL.

Je débute, donc désolé pour la question si la réponse est facile.

Eugène

Algorithmes d'optimisation de la population : Harmony Search (HS) Algorithmes d'optimisation de la population : Harmony Search (HS)
Dans cet article, j'étudierai et testerai l'algorithme d'optimisation le plus puissant : la recherche harmonique (HS), inspirée par le processus de recherche de l'harmonie sonore parfaite. Quel est donc l'algorithme qui domine aujourd'hui notre classement ?
MetaTrader 4 sur Mac OS MetaTrader 4 sur Mac OS
Nous fournissons un programme d'installation spécial pour la plateforme de trading MetaTrader 4 sur macOS. Il s'agit d'un assistant à part entière qui vous permet d'installer l'application de manière native. Le programme d'installation effectue toutes les étapes nécessaires : il identifie votre système, télécharge et installe la dernière version de Wine, le configure et y installe MetaTrader. Toutes les étapes sont réalisées en mode automatique et vous pouvez commencer à utiliser la plateforme immédiatement après son installation.
Comment créer un indicateur personnalisé Heiken Ashi en utilisant MQL5 Comment créer un indicateur personnalisé Heiken Ashi en utilisant MQL5
Dans cet article, nous allons apprendre à créer un indicateur personnalisé à l'aide de MQL5 pour l'utiliser dans MetaTrader 5 pour nous aider à lire les graphiques ou pour l'utiliser dans les Expert Advisors automatisés.
Algorithme de rachat : Simulation de trading multi-devises Algorithme de rachat : Simulation de trading multi-devises
Dans cet article, nous allons créer un modèle mathématique pour simuler la fixation des prix en multidevises et compléter l'étude du principe de diversification dans le cadre de la recherche de mécanismes permettant d'accroître l'efficacité des transactions, que j'ai commencée dans l'article précédent par des calculs théoriques.