English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Tracer des lignes de tendance basées sur des fractales à l’aide de MQL4 et MQL5

Tracer des lignes de tendance basées sur des fractales à l’aide de MQL4 et MQL5

MetaTrader 5Trading | 13 janvier 2022, 15:54
491 0
Almat Kaldybay
Almat Kaldybay

Table des matières


Introduction

Récemment, j’ai pensé à utiliser des lignes de tendance. Il y avait une question sur le choix d’une méthode pour déterminer les points pour tracer les lignes, et aussi sur la précision du traçage. J’ai décidé d’utiliser les fractales comme base.

J’analyse souvent les marchés à mon travail principal où je peux passer du temps sur le trading. En outre, vous ne pouvez pas simplement tracer les lignes sur une période plus longue - la ligne doit être tracée par des points extrêmes avec une précision allant jusqu’à 15 minutes. La raison en est que le temps fractal sur une période plus longue ne correspond pas toujours au temps du même point extrême sur M15. En bref, c’est là que l’automatisation vient vous aider. Il est arrivé que j’ai commencé à écrire le code en utilisant MQL5, puis je suis passé à MQL4, parce que j’avais besoin de ce programme.

Dans cet article, j’ai présenté ma solution du problème en utilisant MQL4 et MQL5. L’article fournit le point de vue comparatif, mais ce serait inapproprié de comparer l’efficacité de MQL4 et MQL5 ici. Aussi, je comprends qu’il y a probablement d’autres solutions, plus efficaces que la mienne. L’article peut être utile aux débutants qui écrivent des scripts en utilisant MQL4 ou MQL5, en particulier à ceux qui envisagent d’utiliser des fractales et des lignes de tendance.


1. Paramètres d’entrée, fonction DeInit() et déclaration initiale des variables

J’ai utilisé les variables suivantes comme paramètres d’entrée :

input color Resistance_Color=Red;       // setting the resistance line color
input ENUM_LINE_STYLE Resistance_Style; // setting the resistance line style
input int Resistance_Width=1;           // setting the resistance line width
input color Support_Color=Red;          // setting the support line color
input ENUM_LINE_STYLE Support_Style;    // setting the support line style
input int Support_Width=1;              // setting the support line width

Ces paramètres sont les mêmes pour MQL4 et MQL5.

Dans MQL5, nous devons créer l’indicateur à l’avance:

//--- iFractals indicator handle 
int Fractal;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- getting the iFractals indicator handle
   Fractal=iFractals(Symbol(),PERIOD_D1);
//---
   return(INIT_SUCCEEDED);
  }

Étant donné que le programme dessinera des objets graphiques, il est logique de les supprimer lors de la suppression de l’Expert Advisor du graphique :

void OnDeinit(const int reason)
  {
   ObjectDelete(0,"TL_Resistance");
   ObjectDelete(0,"TL_Support");
  }

Tracer deux lignes (support et résistance) nécessite quatre points. Pour déterminer le point de passage de la ligne, nous devons connaître le temps et le prix .

Les coordonnées sont déterminées dans cet ordre: tout d’abord, nous trouvons la barre extrême, connaissant la barre extrême, nous pouvons déterminer le prix et l’heure du point extrême.

Déclaration de variables dans la fonction OnTick() :

MQL4
//--- declaration of variables
int n,UpperFractal_1,UpperFractal_2,LowerFractal_1,LowerFractal_2;
MQL5
//--- declaration of variables
int n,UpperFractal_1,UpperFractal_2,LowerFractal_1,LowerFractal_2;
//--- declaring the arrays for writing values of the iFractal indicator buffer
double FractalDown[],FractalUp[];
double UpFractal_1,UpFractal_2,LowFractal_1,LowFractal_2;

Tout d’abord, je n’ai déclaré que les variables qui stockent des index de barres avec des fractales formées.

Dans MQL4 :

  1. n - la variable est nécessaire pour trouver la fractale connue la plus proche à l’aide de l’opérateur de boucle;
  2. UpperFractal_1, UpperFractal_2, LowerFractal_1, LowerFractal_2 - ces variables stockeront l’indice d’une barre au premier et au deuxième point extrême le plus proche avec le prix le plus élevé / le plus bas (en termes de détermination des fractales);

Dans MQL5, nous introduisons des variables supplémentaires:

  1. FractalDown[],FractalUp[]; - déclarer des tableaux de valeurs doubles pour stocker les valeurs du tampon indicateur iFractals;
  2. Ensuite, les variables de type double : UpFractal_1,UpFractal_2,LowFractal_1,LowFractal_2. Ils stockeront les valeurs de prix des points extrêmes.

2. Recherche des fractales les plus proches

Pour trouver l’index d’une barre avec une fractale formée, nous utilisons l’opérateur de boucle.

Déterminons les indices des deux premières barres qui correspondent aux première et deuxième fractales supérieures :

MQL4
//--- finding the bar index of the first nearest upper fractal
   for(n=0; n<(Bars-1);n++)
     {
      if(iFractals(NULL,1440,MODE_UPPER,n)!=NULL)
         break;
      UpperFractal_1=n+1;
     }
//--- finding the bar index of the second nearest upper fractal
   for(n=UpperFractal_1+1; n<(Bars-1);n++)
     {
      if(iFractals(NULL,1440,MODE_UPPER,n)!=NULL)
         break;
      UpperFractal_2=n+1;
     }
 MQL5
//--- first, we need to write the Fractal indicator buffer values into the arrays
//--- filling arrays with buffer values
   CopyBuffer(Fractal,0,TimeCurrent(),Bars(Symbol(),PERIOD_D1),FractalUp);
   CopyBuffer(Fractal,1,TimeCurrent(),Bars(Symbol(),PERIOD_D1),FractalDown);
//--- indexing like in timeseries
   ArraySetAsSeries(FractalUp,true);
   ArraySetAsSeries(FractalDown,true);
//--- next, we use the for loop operator to find the first upper fractal
   for(n=0; n<Bars(Symbol(),PERIOD_D1); n++)
     {
      //--- if the value is not empty, break the loop
      if(FractalUp[n]!=EMPTY_VALUE)
         break;
     }
//--- writing the price value of the first fractal into the variable
   UpFractal_1=FractalUp[n];
//--- writing the index of the first fractal into the variable
   UpperFractal_1=n;
//--- finding the second upper fractal 
   for(n=UpperFractal_1+1; n<Bars(Symbol(),PERIOD_D1); n++)
     {
      if(FractalUp[n]!=EMPTY_VALUE) //if the value is not empty, break the loop
         break;
     }
//--- writing the price value of the second fractal into the variable
   UpFractal_2=FractalUp[n];
//--- writing the index of the second fractal into the variable
   UpperFractal_2=n;

Ici, j’ai clairement démontré l’une des principales différences entre MQL5 et MQL4 - en utilisant les fonctions d’accès aux séries chronologiques.

Dans MQL4, j’ai immédiatement commencé à trouver l’index de la barre avec une fractale formée, mais dans MQL5, j’ai spécifié les tableaux FractalUp[] et FractalDown[] pour stocker les valeurs de prix des fractales supérieures et inférieures en accédant à l’indicateur iFractals avec la fonction CopyBuffer(). Ensuite, je définis l’indexation de ces tableaux comme dans les séries chronologiques à l’aide de la fonction ArraySetAsSeries().

Dans MQL4, je n’ai obtenu que des index des barres avec des fractales connues, mais dans MQL5, j’ai utilisé la fonction CopyBuffer() pour obtenir les index de barres et les valeurs de prix des fractales.

De même, on retrouve les deux premières fractales inférieures :

MQL4
//--- finding the bar index of the first nearest lower fractal
   for(n=0; n<(Bars-1);n++)
     {
      if(iFractals(NULL,1440,MODE_LOWER,n)!=NULL)
         break;
      LowerFractal_1=n+1;
     }
//--- finding the bar index of the second nearest lower fractal
   for(n=LowerFractal_1+1; n<(Bars-1);n++)
     {
      if(iFractals(NULL,1440,MODE_LOWER,n)!=NULL)
         break;
      LowerFractal_2=n+1;
     }
 MQL5
//--- finding the values of the lower fractals
//--- finding the first lower fractal
   for(n=0; n<Bars(Symbol(),PERIOD_D1); n++)
     {
      //--- if the value is not empty, break the loop
      if(FractalDown[n]!=EMPTY_VALUE)
         break;
     }
//--- writing the price value of the first fractal into the variable
   LowFractal_1=FractalDown[n];
//--- writing the index of the first fractal into the variable
   LowerFractal_1=n;
//--- finding the second lower fractal 
   for(n=LowerFractal_1+1; n<Bars(Symbol(),PERIOD_D1); n++)
     {
      if(FractalDown[n]!=EMPTY_VALUE)
         break;
     }
//--- writing the price value of the second fractal into the variable
   LowFractal_2=FractalDown[n];
//--- writing the index of the second fractal into the variable
   LowerFractal_2=n;

Comme vous le voyez, le code est très similaire dans MQL4 et MQL5. Il y a une légère différence de syntaxe.


3. Détermination des valeurs de prix et de temps des fractales

Pour tracer la ligne, nous devons déterminer le temps et le prix d’une fractale. Bien sûr, dans MQL4, nous pourrions simplement utiliser les séries chronologiques, prédéfinies High[] et Low[] et la fonction iTime(), mais nous devons également obtenir des coordonnées temporelles plus précises pour assurer le tracé correct de la ligne de tendance.

La Fig. 1-2 montre la différence entre les valeurs temporelles des points extrêmes sur les périodes H4 et M15.

Fig.1. La valeur de temps du point extrême sur H4

Fig.1. La valeur de temps de point extrême sur H4

Fig.2. La valeur de temps du point extrême sur M15

Fig.2. La valeur de temps de point extrême sur M15

Je suis arrivé à la conclusion que la précision extrême de 15 minutes est tout à fait suffisante pour mes besoins.

En général, le principe de clarification des points extrêmes est presque le même pour MQL4 et MQL5, mais il existe certaines différences dans les détails:

MQL4MQL5
  1. Déterminer la valeur de temps point extrême sur une période plus longue;
  2. À l’aide de la valeur de temps trouvée, déterminez l’index de la barre extrême sur une période plus courte à l’aide de la fonction iBarShift() ;
  3. Étant donné que 24 heures peuvent être représentées sous la forme d’un tableau de 96 barres de 15 minutes, nous recherchons un point extrême (la valeur la plus élevée/la plus basse) parmi ces 96 éléments à l’aide des fonctions iHigh()iLow() ,iTime(), ArrayMaximum() et ArrayMinimum().
  1. Déterminer la valeur de temps point extrême sur une période plus longue;
  2. À l’aide de la valeur de temps trouvée, déterminez l’heure de génération de la barre du lendemain. Nous avons besoin de cette valeur pour l’utiliser dans les fonctions CopyHigh(), CopyLow() et CopyTime() ;
  3. Déclarez et remplissez les tableaux pour stocker les valeurs de prix et de temps pour la période de 15 minutes ;
  4. À l’aide des fonctions ArrayMaximum() et ArrayMinimum(), recherchez les valeurs de prix les plus basses et les plus élevées, ainsi que les valeurs temporelles des points extrêmes clarifiés. 

Le code de chaque étape est illustré ci-dessous :

 MQL4
// Step 1. Determining the extreme point time value on a larger timeframe:
//--- determining the time of fractals
   datetime UpFractalTime_1=iTime(NULL, 1440,UpperFractal_1);
   datetime UpFractalTime_2=iTime(NULL, 1440,UpperFractal_2);
   datetime LowFractalTime_1=iTime(NULL, 1440,LowerFractal_1);
   datetime LowFractalTime_2=iTime(NULL, 1440,LowerFractal_2);
// Step 2.  Determining the index of the extreme bar on a smaller timeframe:   
//--- finding the fractal index on M15
   int UpperFractal_1_m15=iBarShift(NULL, 15, UpFractalTime_1,true);
   int UpperFractal_2_m15=iBarShift(NULL, 15, UpFractalTime_2,true);
   int LowerFractal_1_m15=iBarShift(NULL, 15, LowFractalTime_1,true);
   int LowerFractal_2_m15=iBarShift(NULL, 15, LowFractalTime_2,true);

// Step 3. Using the arrays to find the clarified extreme points on М15:
//--- using the arrays to find the clarified extreme points
//--- introducing the i variable to use in the for loop operator
   int i;
//--- 1. First, find the lower extreme points
//--- 3.1 Finding the first lower extreme point
//--- declaring the array for storing the index values of the bars
   int Lower_1_m15[96];
//--- declaring the array for storing the price values
   double LowerPrice_1_m15[96];
//--- starting the for loop:
   for(i=0;i<=95;i++)
     {
      //--- filling the array with the bar index values
      Lower_1_m15[i]=LowerFractal_1_m15-i;
      //--- filling the array with the price values
      LowerPrice_1_m15[i]=iLow(NULL,15,LowerFractal_1_m15-i);
     }
//--- determining the minimum price value in the array
   int LowestPrice_1_m15=ArrayMinimum(LowerPrice_1_m15,WHOLE_ARRAY,0);
//--- determining the bar with the lowest price in the array
   int LowestBar_1_m15=Lower_1_m15[LowestPrice_1_m15];
//--- determining the time of the lowest price bar
   datetime LowestBarTime_1_m15=iTime(NULL,15,Lower_1_m15[LowestPrice_1_m15]);

//--- 3.2 Finding the second lower extreme point
   int Lower_2_m15[96];
   double LowerPrice_2_m15[96];
   for(i=0;i<=95;i++)
     {
      //--- filling the array with the bar index values
      Lower_2_m15[i]=LowerFractal_2_m15-i;
      //--- filling the array with the price values
      LowerPrice_2_m15[i]=iLow(NULL,15,LowerFractal_2_m15-i);
     }
//--- determining the minimum price value in the array
   int LowestPrice_2_m15=ArrayMinimum(LowerPrice_2_m15,WHOLE_ARRAY,0);
//--- determining the bar with the lowest price in the array
   int LowestBar_2_m15=Lower_2_m15[LowestPrice_2_m15];
//--- determining the time of the lowest price bar
   datetime LowestBarTime_2_m15=iTime(NULL,15,Lower_2_m15[LowestPrice_2_m15]);

//--- 3.3 Finding the first upper extreme point
   int Upper_1_m15[96];
   double UpperPrice_1_m15[96];
   for(i=0;i<=95;i++)
     {
      //--- filling the array with the bar index values
      Upper_1_m15[i]=UpperFractal_1_m15-i;
      //--- filling the array with the price values
      UpperPrice_1_m15[i]=iHigh(NULL,15,UpperFractal_1_m15-i);
     }
//--- determining the maximum price value in the array
   int HighestPrice_1_m15=ArrayMaximum(UpperPrice_1_m15,WHOLE_ARRAY,0);
//--- determining the bar with the highest price in the array
   int HighestBar_1_m15=Upper_1_m15[HighestPrice_1_m15];
//--- determining the time of the highest price bar
   datetime HighestBarTime_1_m15=iTime(NULL,15,Upper_1_m15[HighestPrice_1_m15]);

//--- 3.4 Finding the second upper extreme point
   int Upper_2_m15[96];
   double UpperPrice_2_m15[96];
   for(i=0;i<=95;i++)
     {
      //--- filling the array with the bar index values
      Upper_2_m15[i]=UpperFractal_2_m15-i;
      //--- filling the array with the price values
      UpperPrice_2_m15[i]=iHigh(NULL,15,UpperFractal_2_m15-i);
     }
 MQL5
// Step 1. Determining the extreme point time value on a larger timeframe:
//--- declaring the arrays for storing the time values of the corresponding bar index on a larger timeframe
   datetime UpFractalTime_1[],LowFractalTime_1[],UpFractalTime_2[],LowFractalTime_2[];
//--- determining the time of fractals on a larger timeframe
   CopyTime(Symbol(),PERIOD_D1,UpperFractal_1,1,UpFractalTime_1);
   CopyTime(Symbol(),PERIOD_D1,LowerFractal_1,1,LowFractalTime_1);
   CopyTime(Symbol(),PERIOD_D1,UpperFractal_2,1,UpFractalTime_2);
   CopyTime(Symbol(),PERIOD_D1,LowerFractal_2,1,LowFractalTime_2);

// Step 2. Determining the generation time of the next day bar:
//--- determining the generation time of the next day bar (the stop time for CopyHigh(), CopyLow() and CopyTime())
   datetime UpFractalTime_1_15=UpFractalTime_1[0]+86400;
   datetime UpFractalTime_2_15=UpFractalTime_2[0]+86400;
   datetime LowFractalTime_1_15=LowFractalTime_1[0]+86400;
   datetime LowFractalTime_2_15=LowFractalTime_2[0]+86400;

// Step 3. Declaring and filling the arrays for storing the price and time values for the 15-minute timeframe:   
//--- declaring the arrays for storing the maximum and minimum price values
   double High_1_15[],Low_1_15[],High_2_15[],Low_2_15[];
//--- filling the arrays with the CopyHigh() and CopyLow() functions
   CopyHigh(Symbol(),PERIOD_M15,UpFractalTime_1[0],UpFractalTime_1_15,High_1_15);
   CopyHigh(Symbol(),PERIOD_M15,UpFractalTime_2[0],UpFractalTime_2_15,High_2_15);
   CopyLow(Symbol(),PERIOD_M15,LowFractalTime_1[0],LowFractalTime_1_15,Low_1_15);
   CopyLow(Symbol(),PERIOD_M15,LowFractalTime_2[0],LowFractalTime_2_15,Low_2_15);
//--- declaring the arrays for storing the time values corresponding to the extreme bar indexes  
   datetime High_1_15_time[],High_2_15_time[],Low_1_15_time[],Low_2_15_time[];
//--- filling the arrays
   CopyTime(Symbol(),PERIOD_M15,UpFractalTime_1[0],UpFractalTime_1_15,High_1_15_time);
   CopyTime(Symbol(),PERIOD_M15,UpFractalTime_2[0],UpFractalTime_2_15,High_2_15_time);
   CopyTime(Symbol(),PERIOD_M15,LowFractalTime_1[0],LowFractalTime_1_15,Low_1_15_time);
   CopyTime(Symbol(),PERIOD_M15,LowFractalTime_2[0],LowFractalTime_2_15,Low_2_15_time);
// Step 4. Finding the lowest and highest price values, and the time values of the clarified extreme points:
//--- determining the highest and lowest price and time values with the ArrayMaximum() and ArrayMinimum() functions
   int Max_M15_1=ArrayMaximum(High_1_15,0,96);
   int Max_M15_2=ArrayMaximum(High_2_15,0,96);
   int Min_M15_1=ArrayMinimum(Low_1_15,0,96);
   int Min_M15_2=ArrayMinimum(Low_2_15,0,96);

Finalement, nous avons déterminé les coordonnées de la ligne de tendance suivantes :

1. Pour la ligne d’assistance :

MQL4MQL5
  1. Première coordonnée - LowestBarTime_2_m15;
  2. Coordonnée du premier prix - LowerPrice_2_m15[LowestPrice_2_m15];
  3. Coordonnées pour la deuxième fois - LowestBarTime_1_m15;
  4. Deuxième coordonnée de prix - LowerPrice_1_m15[LowestPrice_1_m15].
  1. Coordonnées pour la première fois - Low_2_15_time[Min_M15_2];
  2. Coordonnée du premier prix - Low_2_15[Min_M15_2];
  3. Coordonnées de la deuxième fois - Low_1_15_time[Min_M15_1];
  4. Deuxième coordonnée de prix - Low_1_15[Min_M15_1].

2. Pour la ligne de résistance :

MQL4MQL5
  1. Coordonnées pour la première fois - HighestBarTime_2_m15;
  2. Coordonnée du premier prix - UpperPrice_2_m15[HighestPrice_2_m15];
  3. Coordonnées de la deuxième - HighestBarTime_1_m15;
  4. Deuxième coordonnée de prix - UpperPrice_1_m15[HighestPrice_1_m15].
  1. Coordonnées pour la première fois - High_2_15_time[Max_M15_2];
  2. Coordonnée du premier prix - High_2_15[Max_M15_2];
  3. Coordonnées de la deuxième fois - High_1_15_time[Max_M15_1];
  4. Deuxième coordonnée de prix - High_1_15[Max_M15_1].


4. Création d’objets et modification de leurs propriétés. Redécoupage les lignes

Maintenant, lorsque nous connaissons les coordonnées de la ligne, il suffit de créer les objets graphiques:

MQL4
//--- creating the support line
   ObjectCreate(0,"TL_Support",OBJ_TREND,0,LowestBarTime_2_m15,LowerPrice_2_m15[LowestPrice_2_m15],
                LowestBarTime_1_m15,LowerPrice_1_m15[LowestPrice_1_m15]);
   ObjectSet("TL_Support",OBJPROP_COLOR,Support_Color);
   ObjectSet("TL_Support",OBJPROP_STYLE,Support_Style);
   ObjectSet("TL_Support",OBJPROP_WIDTH,Support_Width);
//--- creating the resistance line
   ObjectCreate(0,"TL_Resistance",OBJ_TREND,0,HighestBarTime_2_m15,UpperPrice_2_m15[HighestPrice_2_m15],
                HighestBarTime_1_m15,UpperPrice_1_m15[HighestPrice_1_m15]);
   ObjectSet("TL_Resistance",OBJPROP_COLOR,Resistance_Color);
   ObjectSet("TL_Resistance",OBJPROP_STYLE,Resistance_Style);
   ObjectSet("TL_Resistance",OBJPROP_WIDTH,Resistance_Width);
MQL5
//--- creating the support line
   ObjectCreate(0,"TL_Support",OBJ_TREND,0,Low_2_15_time[Min_M15_2],Low_2_15[Min_M15_2],Low_1_15_time[Min_M15_1],Low_1_15[Min_M15_1]);
   ObjectSetInteger(0,"TL_Support",OBJPROP_RAY_RIGHT,true);
   ObjectSetInteger(0,"TL_Support",OBJPROP_COLOR,Support_Color);
   ObjectSetInteger(0,"TL_Support",OBJPROP_STYLE,Support_Style);
   ObjectSetInteger(0,"TL_Support",OBJPROP_WIDTH,Support_Width);
//--- creating the resistance line
   ObjectCreate(0,"TL_Resistance",OBJ_TREND,0,High_2_15_time[Max_M15_2],High_2_15[Max_M15_2],High_1_15_time[Max_M15_1],High_1_15[Max_M15_1]);
   ObjectSetInteger(0,"TL_Resistance",OBJPROP_RAY_RIGHT,true);
   ObjectSetInteger(0,"TL_Resistance",OBJPROP_COLOR,Resistance_Color);
   ObjectSetInteger(0,"TL_Resistance",OBJPROP_STYLE,Resistance_Style);
   ObjectSetInteger(0,"TL_Resistance",OBJPROP_WIDTH,Resistance_Width);

J’ai donc créé les lignes nécessaires et spécifié leurs paramètres en fonction des paramètres d’entrée.

Nous devons maintenant remettre en œuvre un redécoupage des lignes de tendance.

Lorsque la situation du marché change, par exemple, lorsqu’un nouveau point extrême apparaît, nous pouvons simplement supprimer la ligne existante:

MQL4
//--- redrawing the support line
//--- writing the values of the support line time coordinates into the variables
   datetime TL_TimeLow2=ObjectGet("TL_Support",OBJPROP_TIME2);
   datetime TL_TimeLow1=ObjectGet("TL_Support",OBJPROP_TIME1);
//--- if the line coordinates don't match the current coordinates
   if(TL_TimeLow2!=LowestBarTime_1_m15 && TL_TimeLow1!=LowestBarTime_2_m15)
     {
      //--- remove the line
      ObjectDelete(0,"TL_Support");
     }
//--- redrawing the resistance line
//--- writing the values of the resistance line time coordinates into the variables
   datetime TL_TimeUp2=ObjectGet("TL_Resistance",OBJPROP_TIME2);
   datetime TL_TimeUp1=ObjectGet("TL_Resistance",OBJPROP_TIME1);
//--- if the line coordinates don't match the current coordinates
   if(TL_TimeUp2!=HighestBarTime_1_m15 && TL_TimeUp1!=HighestBarTime_2_m15)
     {
      //--- remove the line
      ObjectDelete(0,"TL_Resistance");
     }
MQL5
//--- redrawing the support line
//--- writing the values of the support line time coordinates into the variables
   datetime TL_TimeLow2=(datetime)ObjectGetInteger(0,"TL_Support",OBJPROP_TIME,0);
   datetime TL_TimeLow1=(datetime)ObjectGetInteger(0,"TL_Support",OBJPROP_TIME,1);
//--- if the line coordinates don't match the current coordinates
   if(TL_TimeLow2!=Low_2_15_time[Min_M15_2] && TL_TimeLow1!=Low_1_15_time[Min_M15_1])
     {
      //--- remove the line
      ObjectDelete(0,"TL_Support");
     }
//--- redrawing the resistance line
//--- writing the values of the resistance line time coordinates into the variables
   datetime TL_TimeUp2=(datetime)ObjectGetInteger(0,"TL_Resistance",OBJPROP_TIME,0);
   datetime TL_TimeUp1=(datetime)ObjectGetInteger(0,"TL_Resistance",OBJPROP_TIME,1);
//--- if the line coordinates don't match the current coordinates
   if(TL_TimeUp2!=High_2_15_time[Max_M15_2] && TL_TimeUp1!=High_1_15_time[Max_M15_1])
     {
      //--- remove the line
      ObjectDelete(0,"TL_Resistance");
     }


5. Vérification du chargement de l’historique des barres

Pendant les tests, je me suis rendu compte que les lignes ne dessinaient pas toujours correctement.

Au début, je pensais qu’il y avait un bug dans le code ou que ma solution ne fonctionnait pas du tout, mais ensuite j’ai réalisé que le problème était causé par un chargement insuffisant de l’historique de la barre sur une période plus courte, M15 dans mon cas. Pour avertir l’utilisateur de ces problèmes, j’ai décidé de faire en sorte que le programme vérifie en outre si une barre existe sur M15.

À cette fin, dans MQL4, j’ai utilisé les capacités de la fonction iBarShift() que j’ai utilisées à l’origine dans la section « Détermination des valeurs de prix et de temps des fractales ».

Si une barre est introuvable, la fonction iBarShift() renvoie -1. Par conséquent, nous pouvons sortir cet avertissement:

MQL4
//--- checking the bars history loading
//--- if at least one bar is not found on M15
   if(UpperFractal_1_m15==-1 || UpperFractal_2_m15==-1
      || LowerFractal_1_m15==-1 || LowerFractal_2_m15==-1)
     {
      Alert("The loaded history is insufficient for the correct work!");
     }

Dans MQL5, j’ai utilisé la fonction Bars() qui renvoie une valeur vide, si les données de séries chronologiques n’ont pas été générées dans le terminal :

 
//--- checking the bars history loading
//--- 1. determining the number of bars on a specified timeframe
   int High_M15_1=Bars(Symbol(),PERIOD_M15,UpFractalTime_1[0],UpFractalTime_1_15);
   int High_M15_2=Bars(Symbol(),PERIOD_M15,UpFractalTime_2[0],UpFractalTime_2_15);
   int Low_M15_1=Bars(Symbol(),PERIOD_M15,LowFractalTime_1[0],LowFractalTime_1_15);
   int Low_M15_2=Bars(Symbol(),PERIOD_M15,LowFractalTime_2[0],LowFractalTime_2_15);
//--- 2. check if the loaded history is insufficient for the correct line drawing
//--- if at least one bar is not found
   if(High_M15_1==0 || High_M15_2==0 || Low_M15_1==0 || Low_M15_2==0)
     {
      Alert("The loaded history is insufficient for the correct work!");
     }


6. Signaux de percées de lignes de tendance, notifications push

Pour compléter le tableau, j’ai décidé de mettre en œuvre un signal de la percée de la ligne de tendance. La ligne de tendance est tracée à travers les points extrêmes de la période du jour, mais pour identifier la percée plus tôt, la barre doit être fermée plus bas ou plus haut que la ligne de tendance sur H4.

En général, nous pouvons diviser le processus en trois étapes:

  1. Déterminer le prix de fermeture de la barre et le prix de la ligne de tendance;
  2. Déterminer les conditions dans lesquelles le prix franchit la ligne de tendance;
  3. Envoyez la notification push concernant la percée.
MQL4
// 1. Getting the price parameters of the trend line 
//--- determining the closing price of a bar with index 1
   double Price_Close_H4=iClose(NULL,240,1);
//--- determining the time of a bar with index 1
   datetime Time_Close_H4=iTime(NULL,240,1);
//--- determining the bar index on H4
   int Bar_Close_H4=iBarShift(NULL,240,Time_Close_H4);
//--- determining the price of the line on H4
   double Price_Resistance_H4=ObjectGetValueByShift("TL_Resistance",Bar_Close_H4);
//--- determining the price of the line on H4   
   double Price_Support_H4=ObjectGetValueByShift("TL_Support",Bar_Close_H4);
// 2. Conditions for trend line breakthroughs
//--- for breaking through the support line
   bool breakdown=(Price_Close_H4<Price_Support_H4);
//--- for braking through the resistance line
   bool breakup=(Price_Close_H4>Price_Resistance_H4);
// 3. Delivering the push notifications
   if(breakdown==true)
     {
      //--- send no more than one notification per 4 hours
      int SleepMinutes=240;
      static int LastTime=0;
      if(TimeCurrent()>LastTime+SleepMinutes*60)
        {
         LastTime=TimeCurrent();
         SendNotification(Symbol()+"The price has broken through the support line");
        }
     }
   if(breakup==true)
     {
      //--- send no more than one notification per 4 hours
      SleepMinutes=240;
      LastTime=0;
      if(TimeCurrent()>LastTime+SleepMinutes*60)
        {
         LastTime=TimeCurrent();
         SendNotification(Symbol()+"The price has broken through the resistance line");
        }
     }
MQL5
// 1. Getting the price parameters of the trend line
   double Close[];
   CopyClose(Symbol(),PERIOD_H4,TimeCurrent(),10,Close);
//--- setting the array indexing order
   ArraySetAsSeries(Close,true);
//---
   datetime Close_time[];
   CopyTime(Symbol(),PERIOD_H4,TimeCurrent(),10,Close_time);
//--- setting the array indexing order
   ArraySetAsSeries(Close_time,true);
//---
   double Price_Support_H4=ObjectGetValueByTime(0,"TL_Support",Close_time[1]);
   double Price_Resistance_H4=ObjectGetValueByTime(0,"TL_Resistance",Close_time[1]);
// 2. Conditions for trend line breakthroughs
   bool breakdown=(Close[1]<Price_Support_H4);
   bool breakup=(Close[1]>Price_Resistance_H4);
// 3. Delivering the push notifications
   if(breakdown==true)
     {
      //--- send no more than one notification per 4 hours
      int SleepMinutes=240;
      static int LastTime=0;
      if(TimeCurrent()>LastTime+SleepMinutes*60)
        {
         LastTime=(int)TimeCurrent();
         SendNotification(Symbol()+"The price has broken through the support line");
        }
     }
   if(breakup==true)
     {
      //--- send no more than one notification per 4 hours
      int SleepMinutes=240;
      static int LastTime=0;
      if(TimeCurrent()>LastTime+SleepMinutes*60)
        {
         LastTime=(int)TimeCurrent();
         SendNotification(Symbol()+"The price has broken through the resistance line");
        }
     }

Pour identifier une percée, j’ai utilisé la fonction ObjectGetValueByShift() dans MQL4 et la fonction ObjectGetValueByTime() dans MQL5.

Peut-être que je pourrais simplement définir 1 au lieu de Bar_Close_H4 comme paramètre pour ObjectGetValueByShift(), mais j’ai décidé de déterminer d’abord l’index sur H4. J’ai utilisé la solution pour limiter le nombre de messages envoyés publiés sur ce fil de discussion du forum, et je tiens à remercier beaucoup l’auteur.


7. Utilisation pratique des lignes de tendance dans le trading

Le moyen le plus simple: identifier une percée, attendre un repli et entrer sur le marché après.

Idéalement, vous devriez obtenir quelque chose comme ceci:

Fig. 3. Percée de la ligne de tendance

Fig. 3. Percée de la ligne de tendance

 Vous pouvez ensuite utiliser votre imagination et essayer d’identifier les formations, c’est-à-dire les modèles d’analyse technique, par exemple, un triangle:

Fig.4. Motif triangulaire

Fig.4. Motif triangulaire

Les lignes n’ont pas été clarifiées par un délai plus court sur les images ci-dessus.


Conclusion

Ceci conclut l’article, j’espère que vous le trouverez utile. L’article était destiné aux débutants en programmation, aux amateurs comme moi.

J’ai beaucoup appris en écrivant cet article: tout d’abord, j’ai commencé à faire des commentaires de code plus significatifs; deuxièmement, au début, j’avais une solution plus lourde et complexe pour la clarification des points extrêmes, mais j’ai ensuite trouvé une solution plus simple que j’ai démontrée ici.

Merci d’avoir lu, tout commentaire est apprécié.


Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/1201

Fichiers joints |
trendlines.mq4 (19.87 KB)
trendlines.mq5 (20.95 KB)
Graphique Liquide Graphique Liquide
Souhaitez-vous voir un graphique horaire avec des barres s'ouvrant à partir de la deuxième et de la cinquième minute de l'heure ? À quoi ressemble un graphique redessiné lorsque l'heure d'ouverture des bars change toutes les minutes ? Quels sont les avantages du trading sur de tels graphiques ? Vous trouverez des réponses à ces questions dans cet article.
Le MQL5 Cookbook : Manipulation BookEvent Le MQL5 Cookbook : Manipulation BookEvent
Cet article considère BookEvent - une profondeur d'événement du marché, et le principe de son traitement. Un programme MQL, gérant les états de Profondeur du marché comme exemple. Il est écrit en utilisant l'approche orientée objet. Les résultats de la manipulation sont affichés à l'écran sous forme de panneau et de niveaux de profondeur de marché.
Les bases de la programmation MQL5 : Variables globales du terminal Les bases de la programmation MQL5 : Variables globales du terminal
Cet article met en évidence les capacités orientées objet du langage MQL5 pour créer des objets facilitant le travail avec les variables globales du terminal. Comme exemple pratique, je considère un cas où des variables globales sont utilisées comme points de contrôle pour la mise en œuvre des étapes du programme.
Pourquoi l'hébergement virtuel sur MetaTrader 4 et MetaTrader 5 est meilleur que les VPS habituels Pourquoi l'hébergement virtuel sur MetaTrader 4 et MetaTrader 5 est meilleur que les VPS habituels
Le réseau Virtual Hosting Cloud a été développé spécialement pour MetaTrader 4 et MetaTrader 5 et présente tous les avantages d'une solution native. Bénéficiez de notre offre gratuite de 24 heures - testez un serveur virtuel dès maintenant.