English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Indicateur de construction d'un graphique à trois sauts de ligne

Indicateur de construction d'un graphique à trois sauts de ligne

MetaTrader 5Exemples | 13 janvier 2022, 14:29
706 0
Dmitriy Zabudskiy
Dmitriy Zabudskiy

Introduction

Les articles précédents ont examiné les graphiques Point, et Figure,Kagi et Renko. Poursuivant la série d’articles sur les graphiques du 20ème siècle, cette fois nous allons parler de la graphique à trois sauts de ligne ou, pour être précis, de son implémentation à travers un code de programme. Il y a très peu d’informations sur l’origine de ce graphique. Je suppose que cela a commencé au Japon. Aux États-Unis, ils l’ont appris http://www.amazon.com/Beyond-Candlesticks-Japanese-Charting-Techniques/dp/047100720X« Beyond Candlesticks » de Steve Nison publié en 1994.

De même que dans les graphiques mentionnés ci-dessus, la plage de temps n’est pas prise en compte lors de la construction du graphique à trois sauts de ligne. Il est basé sur des cours de fermeture nouvellement formés d’une certaine période, ce qui permet de filtrer les fluctuations mineures d’un prix par rapport au mouvement précédent.

Steve Nison dans son livre « Beyond Candlesticks » décrit onze principes pour tracer ce tableau (p. 185). Je les ai regroupés en trois.

  • Principe N°1: Pour la construction, sélectionnez un prix initial, puis, selon que le marché monte ou descend, tracez une ligne ascendante ou descendante. Il marquera un nouveau minimum ou maximum.
  • Principe N°2: Lorsqu’un nouveau prix tombe en dessous du minimum ou dépasse le maximum, nous pouvons tracer une ligne descendante ou ascendante.
  • Principe n°3: Pour tracer une ligne dans la direction opposée au mouvement précédent, le minimum ou le maximum doit être dépassé. En même temps, s’il y a plus d’une ligne identique, le minimum ou le maximum est calculé sur la base de deux (s’il y a deux lignes identiques consécutives) ou de trois (s’il y a trois lignes identiques consécutives ou plus) d’entre elles.

Examinons de plus près l’exemple d’une construction graphique classique basée sur des données historiques (fig. 1).

Fig.1 Exemple de construction d’un graphique à trois sauts de ligne (EURUSD

Fig.1 Exemple de construction d’un graphique à trois sauts de ligne (EURUSD H1 27.06.2014)

La Fig. 1 représente un graphique en chandelier sur le côté gauche et un graphique à trois sauts de ligne sur le côté droit. Ceci est un graphique de EURUSD, période H1. La date de début du graphique est le 27.06.2014 au prix 1.3613 (l’heure de fermeture de la chandelle est 00:00), puis la chandelle (01:00) ferme à 1.3614, formant la première ligne ascendante du graphique à trois sauts de ligne La bougie suivante de la direction baissière (02h00) forme une ligne ascendante, clôturant à 1,3612 (le prix de fermeture est inférieur au minimum précédent).

Ensuite, les chandeliers haussiers déplacent le prix vers la marque 1.3619 (03:00), formant un nouveau maximum et une ligne. La chandelle à 04h00 n’est pas tombée en dessous du minimum et cela n’a pas affecté la construction. La chandelle à 05:00 ferme à 1.3623, marquant un nouveau maximum (nouvelle ligne ascendante).

Maintenant, pour prolonger la tendance baissière, nous devons passer deux minimums (1,3613), mais les hausses ne vont pas abandonner leur position et former un nouveau maximum de 1,3626 (06:00). Ensuite, les haussiers tentent d’inverser la tendance haussière pendant deux heures, mais la même tendance se poursuit avec un nouveau maximum atteint à 1,3634 (09h00). Les haussiers sont en tête. Maintenant, pour tracer une ligne ascendante, trois minimums doivent être passés (1,3626; 1,3623 et 1,3619).

Comme nous pouvons le voir, dans les trois heures qui suivent, les ours s’emparent du marché, le descendant au point de 1,3612 (12h00). Elle se traduit par une nouvelle ligne ascendante. Cependant, les cinq heures suivantes montrent que les haussiers reconquirent leur position et ramènent le marché au point de 1,3641, dépassant le maximum précédent à 1,3626 et formant une nouvelle ligne ascendante à 17h00. Les ours ne parviennent pas à dépasser le minimum précédent à 18h00 et pendant les cinq heures suivantes, les taureaux amènent le marché au point de 1,3649, formant une nouvelle ligne ascendante toutes les heures.


Principes de base de la construction de graphiques

Avant d’arriver au code, nous allons parler de l’indicateur lui-même et déterminer ce qui le rend différent des autres et comment. Il est évident que le trois sauts de ligne, comme d’autres indicateurs, a été conçu pour faciliter une analyse efficace du marché et la recherche de nouvelles stratégies. Je suis sûr que vous voulez savoir s’il y a des nouveautés. En fait, il y en a quelques-uns. L’indicateur permet de changer le type de prix pour le calcul. Il couvre les quatre prix des bars standard. Le type classique est conçu pour construire des graphiques pour un seul type de prix lorsque le type modernisé prend en charge l’utilisation des quatre types de prix (ouvert, élevé, bas и fermer). Il modifie l’apparence de la construction classique du graphique en ajoutant des « ombres » aux lignes et en les faisant ressembler à des chandeliers japonais, ce qui ajoute à la perception visuelle du graphique.

La version modernisée propose également des paramètres permettant de synchroniser les données de prix à temps avec la substitution des prix manquants aux prix prioritaires.

Le type modernisé de construction de graphiques est présenté à la fig. 2:

Fig.2 Graphique modifié basé

Fig.2 Graphique modifié basé sur quatre types de prix

Comme la construction modernisée combine quatre graphiques à trois sauts de ligne de différents types de prix, il est naturel de trouver des écarts entre les prix. Pour l’éviter, la synchronisation des données à temps est nécessaire. La synchronisation des prix a été réalisée en deux variantes : complète (fig. 2 à droite) et partielle (fig. 2 à gauche). La synchronisation complète représente une synchronisation partielle filtrée, où toutes les données sont dessinées sur le graphique et les données manquantes sont remplacées par les prix de priorité spécifiés dans les paramètres. Dans le mode de synchronisation complète, les données manquantes sont simplement omises et seuls les chandeliers avec un ensemble complet de données sont dessinés.

Une autre innovation est un séparateur de période, introduit pour la commodité des signaux de fractionnement. Comme vous le savez bien, le séparateur de période peut être activé dans les paramètres du graphique. Dans l’indicateur, ils changent en fonction de la période, spécifiée dans les paramètres. Contrairement aux graphiques https://www.metatrader5.com/enMetaTrader 5, où les périodes sont séparées par une ligne pointillée verticale, dans cet indicateur, une nouvelle période est représentée en changeant une couleur de ligne (chandelles, fig. 3):

Fig.3 Séparateurs de

Fig.3 Séparateurs de période dans l’indicateur

Un autre ajout est la mise en œuvre d’un indicateur technique iMA, qui est construit sur la base des prix du graphique principal, mais est synchronisé avec les données de l’indicateur à temps. Ainsi, les données sont filtrées par la moyenne mobile (fig. 4) :

Fig.4 Moyenne

Fig.4 Moyenne mobile interne

L’indicateur dispose également d’une fonction permettant de définir un mouvement minimum en points pour tracer une ligne et le nombre de lignes requises pour une inversion. Il a également un rôle de filtre.


Code de l’indicateur

L’algorithme de l’indicateur est plutôt simple et comporte trois étapes : copie des données, calcul basé sur les données copiées et remplissage des tampons de l’indicateur (construction d’un graphique basé sur les données reçues). Le code est divisé en fonctions qui sont interconnectées entre elles ou avec les données d’entrée. Examinons de près le code.

1. Paramètres d'entrée du script

Le préambule de l’indicateur contient une déclaration de constructions graphiques. Il y en a deux dans l’indicateur: le graphique « ABCTB » (DRAW_COLOR_CANDLES) et la moyenne mobile supplémentaire « LINE_TLB » (DRAW_LINE). En conséquence, il y a six tampons. Suivent ensuite les données de type enum pour améliorer les paramètres de l’interface et les paramètres eux-mêmes:

  • magic_numb - Le nombre magique a le type long. C’est un nombre unique pour désigner l’indicateur. Si la nécessité s’en fait sentir, peut être converti en chaîne de type avec quelques modifications ;
  • time_frame - Plage de temps de calcul, type ENUM_TIMEFRAMES, est le paramètre principal (la période de l’indicateur) ;
  • time_redraw - Période de mise à jour du graphique, tapez ENUM_TIMEFRAMES. Il s’agit de la période pendant laquelle un nouveau calcul graphique a lieu. Pour un redécoupage rapide du graphique, appuyez sur la touche « R » du clavier - un contrôle intégré de l’indicateur;
  • first_date_start - Date de début, tapez datetime. C’est le paramètre principal qui est le point de départ de la copie des données et de la cartographie ;
  • chart_price - Type de prix pour le calcul (0-Close, 1-Ouvert, 2-Haut, 3-Bas). Pour une construction graphique classique, un type de prix doit être sélectionné. Comme déjà mentionné, ce paramètre est ignoré lorsque la construction modifiée est activée ;
  • step_min_f - Pas minimum pour une nouvelle colonne (>0, tapez int) ou un saut requis pour tracer une ligne ;
  • line_to_back_f - Nombre de lignes pour afficher une inversion (>0, tapez int). Le type classique suggère trois lignes pour montrer un renversement ;
  • chart_type - Type de construction de graphique (0-classique, 1-modifié), tapez sélectionner. Il s’agit d’un changement entre les types de construction ;
  • chart_color_period - Modification de la couleur lors du démarrage d’une nouvelle période (type booléen). Utilisé pour changer la couleur de la ligne au début d’une nouvelle période ;
  • chart_synchronization - Construction d’un graphique uniquement une fois la synchronisation terminée (tapezbooléen, si vrai, une synchronisation complète se produit avec la suppression de toutes les valeurs manquantes avant la construction d’un graphique) ;
  • chart_priority_close - Priorité du cours de fermeture (tapez sélectionner, a quatre variantes. Il pointe vers la priorité du cours de fermeture à la synchronisation partielle et est ignoré à la synchronisation complète ;
  • chart_priority_open - Priorité du prix d’ouverture. Il en va de même ici ;
  • chart_priority_high - Priorité du prix maximum. Il en va de même ici ;
  • chart_priority_low - Priorité du prix minimum. Il en va de même ici ;
  • ma_draw - Dessinez la moyenne (tapezbooléen, si vrai, puis dessinez la moyennemobile) ;
  • ma_price - Type de prix pour la construction de la moyenne, peut être l’un de ENUM_APPLIED_PRICE;
  • ma_method - Type de construction, peut être l’un de ENUM_MA_METHOD;
  • ma_period - Période de calcul de la moyennemobile ;

Ensuite, nous déclarons les tableaux tampons, les variables et les structures nécessaires au calcul.

//+------------------------------------------------------------------+
//|                                                        ABCTB.mq5 |
//|                                 "Azotskiy Aktiniy ICQ:695710750" |
//|                        "" |
//+------------------------------------------------------------------+
// ABCTB - Auto Build Chart Three Line Break
#property copyright "Azotskiy Aktiniy ICQ:695710750"
#property link      ""
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 6
#property indicator_plots   2
//--- plot ABCTB
#property indicator_label1  "ABCTB"
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrBlue,clrRed,clrGreenYellow
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot LINE_TLB
#property indicator_label2  "LINE_TLB"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- Price type for calculation
enum type_price
  {
   close=0, // Close
   open=1,  // Open
   high=2,  // Hight
   low=3,   // Low
  };
//--- type of chart construction
enum type_build
  {
   classic=0,  // Classic
   modified=1, // Modified
  };
//--- priority
enum priority
  {
   highest_t=4, // Highest
   high_t=3,    // High
   medium_t=2,  // Medium
   low_t=1,     // Low
  };
//--- input parameters
input long               magic_numb=65758473787389;                // Magic number
input ENUM_TIMEFRAMES    time_frame=PERIOD_CURRENT;                // Calculation time range
input ENUM_TIMEFRAMES    time_redraw=PERIOD_M1;                    // Period of chart updates
input datetime           first_date_start=D'2013.03.13 00:00:00';  // Start date
input type_price         chart_price=close;                        // Price type for calculation (0-Close, 1-Open, 2-High, 3-Low)
input int                step_min_f=4;                             // Minimum step for a new column (>0)
input int                line_to_back_f=3;                         // Number of lines to display a reversal(>0)
input type_build         chart_type=classic;                       // Type of chart construction (0-classic, 1-modified)
input bool               chart_color_period=true;                  // Changing color for a new period
input bool               chart_synchronization=true;               // Constructing a chart only upon complete synchronization
input priority           chart_priority_close=highest_t;           // Priority of the closing price
input priority           chart_priority_open=highest_t;            // Priority of the opening price
input priority           chart_priority_high=highest_t;            // Priority of the maximum price
input priority           chart_priority_low=highest_t;             // Priority of the minimum price
input bool               ma_draw=true;                             // Draw the average
input ENUM_APPLIED_PRICE ma_price=PRICE_CLOSE;                     // Price type for constructing the average
input ENUM_MA_METHOD     ma_method=MODE_EMA;                       // Construction type
input int                ma_period=14;                             // Averaging period
//--- indicator buffers
//--- buffer of the chart
double         ABCTBBuffer1[];
double         ABCTBBuffer2[];
double         ABCTBBuffer3[];
double         ABCTBBuffer4[];
double         ABCTBColors[];
//--- buffer of the average
double         LINE_TLBBuffer[];
//--- variables
MqlRates rates_array[];// bar data array for analysis
datetime date_stop;    // current date
datetime date_start;   // start date variable for calculation
//+------------------------------------------------------------------+
//| Struct Line Price                                                |
//+------------------------------------------------------------------+
struct line_price// structure for storing information about the past lines
  {
   double            up;  // value of the high price
   double            down;// value of the low price
  };
//+------------------------------------------------------------------+
//| Struct Line Information                                          |
//+------------------------------------------------------------------+
struct line_info// structure for storing information about the shared lines
  {
   double            up;
   double            down;
   char              type;
   datetime          time;
  };
line_info line_main_open[];  // data on the opening prices chart
line_info line_main_high[];  // data on the maximum prices chart
line_info line_main_low[];   // data on the minimum prices chart
line_info line_main_close[]; // data on the closing prices chart
//+------------------------------------------------------------------+
//| Struct Buffer Info                                               |
//+------------------------------------------------------------------+
struct buffer_info// structure for storing data for filling a buffer
  {
   double            open;
   double            high;
   double            low;
   double            close;
   char              type;
   datetime          time;
  };
buffer_info data_for_buffer[];// data for filling the modified construction buffer
datetime array_datetime[];    // array for storing information of the time for every line
int time_array[3];            // array for the function func_date_color
datetime time_variable;       // variable for the function func_date_color
bool latch=false;             // variable-latch for the function func_date_color
int handle;                   // handle of the indicator iMA
int step_min;                 // variable of the minimum step
int line_to_back;             // variable of the number of lines to display a reversal

2. Fonction OnInit 

Tous les tampons indicateurs sont déclarés dans la fonction OnInit et l’indication de tableau est configurée comme dans une série chronologique.

Ensuite, nous définissons les valeurs de l’indicateur qui ne seront pas reflétées sur le graphique, définissons le nom,, spécifions la précision et supprimons les valeurs actuelles car elles surchargent le graphique. Ici, nous définissons également la poignée de l’indicateur iMA et vérifions l’exactitude des données saisies. En cas d’erreur, un message approprié est imprimé et la valeur est modifiée au minimum.

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
//--- buffers for a chart
   SetIndexBuffer(0,ABCTBBuffer1,INDICATOR_DATA);
   ArraySetAsSeries(ABCTBBuffer1,true);
   SetIndexBuffer(1,ABCTBBuffer2,INDICATOR_DATA);
   ArraySetAsSeries(ABCTBBuffer2,true);
   SetIndexBuffer(2,ABCTBBuffer3,INDICATOR_DATA);
   ArraySetAsSeries(ABCTBBuffer3,true);
   SetIndexBuffer(3,ABCTBBuffer4,INDICATOR_DATA);
   ArraySetAsSeries(ABCTBBuffer4,true);
   SetIndexBuffer(4,ABCTBColors,INDICATOR_COLOR_INDEX);
   ArraySetAsSeries(ABCTBColors,true);
//--- buffer for constructing the average
   SetIndexBuffer(5,LINE_TLBBuffer,INDICATOR_DATA);
   ArraySetAsSeries(LINE_TLBBuffer,true);
//--- set the values that are not going to be reflected on the chart
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0); // for the chart
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0); // for the average
//--- set the indicator appearance
   IndicatorSetString(INDICATOR_SHORTNAME,"ABCTB "+IntegerToString(magic_numb)); // name of the indicator
//--- accuracy of display
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- prohibit displaying the results of the indicator current value
   PlotIndexSetInteger(0,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(1,PLOT_SHOW_DATA,false);
//---
   handle=iMA(_Symbol,time_frame,ma_period,0,ma_method,ma_price);
   if(step_min_f<1)
     {
      step_min=1;
      Alert("Minimum step for a new column must be greater than zero");
     }
   else step_min=step_min_f;
//---
   if(line_to_back_f<1)
     {
      line_to_back=1;
      Alert("The number of lines to display a reversal must be greater than zero");
     }
   else line_to_back=line_to_back_f;
//---
   return(INIT_SUCCEEDED);
  }

3. Fonction de copie de données

Comme l’indicateur est conçu pour fonctionner avec les quatre types de prix, il est essentiel de copier toutes les données, y compris le temps. Dans MQL5, il existe une structure nommée MqlRates. Il est utilisé pour stocker des informations sur l’heure du début d’une session de trading, les prix, les volumes et la marge.

Les paramètres d’entrée de la fonction sont la date de début et de fin, la période et le tableau cible du type MqlRates. La fonction renvoie vrai si la copie réussit. Les données sont copiées dans un tableau intermédiaire. Les données manquantes calculées plus une session y sont copiées et les données sont renouvelées en permanence. Si la copie dans le tableau intermédiaire a réussi, les données sont copiées dans le tableau, transmises pour garantir le bon fonctionnement de la fonction.

//+------------------------------------------------------------------+
//| Func All Copy                                                    |
//+------------------------------------------------------------------+
bool func_all_copy(MqlRates &result_array[],// response array
                   ENUM_TIMEFRAMES period,  // timeframe
                   datetime data_start,     // start date
                   datetime data_stop)      // end date
  {
//--- declaration of auxiliary variables
   bool x=false;       // variable for the function response
   int result_copy=-1; // copied data count
//--- adding variables and arrays for calculation
   static MqlRates interim_array[]; // temporary dynamic array for storing copied data
   static int bars_to_copy;         // number of bars for copying
   static int bars_copied;          // number of copied bars since the start date
//--- find out the current number of bars in the time range
   bars_to_copy=Bars(_Symbol,period,data_start,data_stop);
//--- count the number of bars to be copied
   bars_to_copy-=bars_copied;
//--- if it is not the first time when data is being copied
   if(bars_copied>0)
     {
      bars_copied--;
      bars_to_copy++;
     }
//--- change the size of the receiving array
   ArrayResize(interim_array,bars_to_copy);
//--- copy data to a temporary array
   result_copy=CopyRates(_Symbol,period,0,bars_to_copy,interim_array);
//--- check the result of copying data
   if(result_copy!=-1) // if copying to the temporary array was successful
     {
      ArrayCopy(result_array,interim_array,bars_copied,0,WHOLE_ARRAY); // copy the data from the temporary array to the main one
      x=true;                   // assign the positive response to the function
      bars_copied+=result_copy; // increase the value of the copied data
     }
//---
   return(x);
  }

4. Fonction de calcul des données

Cette fonction est un prototype de calcul de données pour une construction classique du graphique à trois sauts de ligne. Comme déjà mentionné, la fonction calcule uniquement les données et les forme dans un tableau spécial du type de structure line_info, déclaré au début du code.

Cette fonction contient deux autres fonctions : func_regrouping (fonction de regroupement) et func_insert (fonction d’insertion). Pour commencer, nous allons les examiner :

4.1. Fonction de regroupement

Cette fonction regroupe des informations sur des lignes consécutives de la même direction. Il est limité par la taille du tableau qui y est passé ou, pour être précis, par le paramètre line_to_back_f (nombre de lignes pour afficher une inversion) des paramètres de l’indicateur. Ainsi, chaque fois que le contrôle est transféré à la fonction, toutes les données reçues sur des lignes identiques se déplacent d’un point vers le bas à la fin et l’index 0 est rempli par une nouvelle valeur.

C’est ainsi que les informations sur les lignes requises pour une pause sont stockées (dans le cas d’une construction classique, la rupture comporte trois lignes).

//+------------------------------------------------------------------+
// Func Regrouping                                                   |
//+------------------------------------------------------------------+
void func_regrouping(line_price &input_array[],// array for regrouping
                     double new_price,         // new price value
                     char type)                // type of movement
  {
   int x=ArraySize(input_array);// find out the size of the array for regrouping
   for(x--; x>0; x--)           // regrouping loop
     {
      input_array[x].up=input_array[x-1].up;
      input_array[x].down=input_array[x-1].down;
     }
   if(type==1)
     {
      input_array[0].up=new_price;
      input_array[0].down=input_array[1].up;
     }
   if(type==-1)
     {
      input_array[0].down=new_price;
      input_array[0].up=input_array[1].down;
     }
  }

 4.2. Fonction d’insertion

 La fonction effectue l’insertion des valeurs dans le tableau de réponses. Le code est simple et ne nécessite pas d’explication détaillée. 

//+------------------------------------------------------------------+
// Func Insert                                                       |
//+------------------------------------------------------------------+
void func_insert(line_info &line_m[],  // target array
                 line_price &line_i[], // source array
                 int index,            // array element being inserted
                 char type,            // type of the target column
                 datetime time)        // date
  {
   line_m[index].up=line_i[0].up;
   line_m[index].down=line_i[0].down;
   line_m[index].type=type;
   line_m[index].time=time;
  }

La fonction de calcul des données était classiquement divisée en trois parties. La première partie copie les données en cours d’analyse sur un réseau intermédiaire à l’aide de la touchede l’opérateur. Seul le prix concerné est copié. La deuxième partie effectue une série de tests pour calculer l’espace requis dans le tableau de données. Ensuite, le tableau de données line_main_array[], initialement transmis à la fonction pour réponse, subit une modification. La troisième partie, à son tour, remplit le tableau de données ajusté.

//+------------------------------------------------------------------+
//| Func Build Three Line Break                                      |
//+------------------------------------------------------------------+
void func_build_three_line_break(MqlRates &input_array[],      // array for analysis
                                 char price_type,              // type of the price under analysis (0-Close, 1-Open, 2-High, 3-Low)
                                 int min_step,                 // minimum step for drawing a line
                                 int line_back,                // number of lines for a reversal
                                 line_info &line_main_array[]) // array for return (response) of the function
  {
//--- calculate the size of the array for analysis
   int array_size=ArraySize(input_array);
//--- extract data required for calculation to an intermediate array
   double interim_array[];// intermediate array
   ArrayResize(interim_array,array_size);// adjust the intermediate array to the size of the data
   switch(price_type)
     {
      case 0: // Close
        {
         for(int x=0; x<array_size; x++)
           {
            interim_array[x]=input_array[x].close;
           }
        }
      break;
      case 1: // Open
        {
         for(int x=0; x<array_size; x++)
           {
            interim_array[x]=input_array[x].open;
           }
        }
      break;
      case 2: // High
        {
         for(int x=0; x<array_size; x++)
           {
            interim_array[x]=input_array[x].high;
           }
        }
      break;
      case 3: // Low
        {
         for(int x=0; x<array_size; x++)
           {
            interim_array[x]=input_array[x].low;
           }
        }
      break;
     }
//--- enter the variables for storing information about current situation
   line_price passed_line[];// array for storing information about the latest prices of the lines (type structure line_price)
   ArrayResize(passed_line,line_back+1);
   int line_calc=0;// number of lines
   int line_up=0;// number of the last ascending lines
   int line_down=0;// number of the last descending lines
   double limit_up=0;// upper limit necessary to pass
   double limit_down=0;// lower limit necessary to pass
/* Fill variables informing of the current situation with the first values */
   passed_line[0].up=interim_array[0];
   passed_line[0].down=interim_array[0];
//--- start the first loop to calculate received data for filling a buffer for drawing
   for(int x=0; x<array_size; x++)
     {
      if(line_calc==0)// no lines have been drawn
        {
         limit_up=passed_line[0].up;
         limit_down=passed_line[0].down;
         if(interim_array[x]>=limit_up+min_step*_Point)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            line_calc++;// update the line counter
            line_up++;
           }
         if(interim_array[x]<=limit_down-min_step*_Point)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            line_calc++;// update the line counter
            line_down++;
           }
        }
      if(line_up>line_down)// last ascending line (lines)
        {
         limit_up=passed_line[0].up;
         limit_down=passed_line[(int)MathMin(line_up,line_back-1)].down;
         if(interim_array[x]>=limit_up+min_step*_Point)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            line_calc++;// update the line counter
            line_up++;
           }
         if(interim_array[x]<limit_down)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            line_calc++;// update the line counter
            line_up=0;
            line_down++;
           }
        }
      if(line_down>line_up)// last descending line (lines)
        {
         limit_up=passed_line[(int)MathMin(line_down,line_back-1)].up;
         limit_down=passed_line[0].down;
         if(interim_array[x]>limit_up)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            line_calc++;// update the line counter
            line_down=0;
            line_up++;
           }
         if(interim_array[x]<=limit_down-min_step*_Point)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            line_calc++;// update the line counter
            line_down++;
           }
        }
     }
   ArrayResize(line_main_array,line_calc);// change the size of the target array
//--- zeroise variables and fill with the the initial data
   line_calc=0;
   line_up=0;
   line_down=0;
   passed_line[0].up=interim_array[0];
   passed_line[0].down=interim_array[0];
//--- start the second loop to fill a buffer for drawing
   for(int x=0; x<array_size; x++)
     {
      if(line_calc==0)// no lines have been drawn
        {
         limit_up=passed_line[0].up;
         limit_down=passed_line[0].down;
         if(interim_array[x]>=limit_up+min_step*_Point)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            func_insert(line_main_array,passed_line,line_calc,1,input_array[x].time);
            line_calc++;// update the line counter
            line_up++;
           }
         if(interim_array[x]<=limit_down-min_step*_Point)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            func_insert(line_main_array,passed_line,line_calc,-1,input_array[x].time);
            line_calc++;// update the line counter
            line_down++;
           }
        }
      if(line_up>line_down)// last ascending line (lines)
        {
         limit_up=passed_line[0].up;
         limit_down=passed_line[(int)MathMin(line_up,line_back-1)].down;
         if(interim_array[x]>=limit_up+min_step*_Point)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            func_insert(line_main_array,passed_line,line_calc,1,input_array[x].time);
            line_calc++;// update the line counter
            line_up++;
           }
         if(interim_array[x]<limit_down)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            func_insert(line_main_array,passed_line,line_calc,-1,input_array[x].time);
            line_calc++;// update the line counter
            line_up=0;
            line_down++;
           }
        }
      if(line_down>line_up)// last descending line (lines)
        {
         limit_up=passed_line[(int)MathMin(line_down,line_back-1)].up;
         limit_down=passed_line[0].down;
         if(interim_array[x]>limit_up)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            func_insert(line_main_array,passed_line,line_calc,1,input_array[x].time);
            line_calc++;// update the line counter
            line_down=0;
            line_up++;
           }
         if(interim_array[x]<=limit_down-min_step*_Point)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            func_insert(line_main_array,passed_line,line_calc,-1,input_array[x].time);
            line_calc++;// update the line counter
            line_down++;
           }
        }
     }
  }

5. Fonction de construction de graphique

Le but de cette fonction est de calculer les données d’un graphique en fonction du paramètre de construction sélectionné (classique ou modifié) et de remplir le tampon de l’indicateur avec des données à afficher. En plus de la fonction précédente, la fonction de construction de graphiques a trois fonctions supplémentaires. Ce sont la fonction de couleur, la fonction de synchronisation et la fonction de la moyenne mobile. Discutons-en plus en détail.

5.1. Fonction de couleur

Cette fonction n’a qu’un seul paramètre d’entrée - le temps. La réponse de la fonction est une variable booléenne. Si les données transmises sont la bordure de la période, la fonction renvoie vraie. Comme les périodes dépendent de la période sélectionnée, la fonction a une séparation de période intégrée par l’opérateur conditionnel si. Une fois la période sélectionnée, elle fait l’objet d’une vérification si une nouvelle période a déjà commencé. Cela se fait en convertissant une date en structure MqlDateTime et en comparaison. Pour la période allant jusqu’à H2 inclus, les changements dans la valeur de la date indiquent le début d’une nouvelle période. Les périodes de H12 à D1 inclus indiquent les changements en mois et entre W1 et MN, nous vérifions le changement dans l’année.

Malheureusement, la structure MqlDateTime ne contient pas d’informations sur la semaine en cours. Ce problème a été résolu en créant un point initial représenté par la variable time_variable. Plus loin sur la ligne, un nombre de secondes dans une semaine est déduit de cette date.

//+------------------------------------------------------------------+
// Func Date Color                                                   |
//+------------------------------------------------------------------+
bool func_date_color(datetime date_time) // input date
  {
   bool x=false;// response variable
   int seconds=PeriodSeconds(time_frame);// find out the calculation time range
   MqlDateTime date;
   TimeToStruct(date_time,date);// convert data
   if(latch==false) // check the state of the latch
     {
      MqlDateTime date_0;
      date_0=date;
      date_0.hour=0;
      date_0.min=0;
      date_0.sec=0;
      int difference=date_0.day_of_week-1;
      datetime date_d=StructToTime(date_0);
      date_d=date_d-86400*difference;
      time_variable=date_d;
      latch=true;// lock the latch
     }
   if(seconds<=7200)// period is less than or equal to H2
     {
      if(time_array[0]!=date.day)
        {
         x=true;
         time_array[0]=date.day;
        }
     }
   if(seconds>7200 && seconds<=43200)// period is greater than H2 but less than or equal to H12
     {
      if(time_variable>=date_time)
        {
         x=true;
         time_variable=time_variable-604800;
        }
     }
   if(seconds>43200 && seconds<=86400)// period is greater than H12 but less than or equal to D1
     {
      if(time_array[1]!=date.mon)
        {
         x=true;
         time_array[1]=date.mon;
        }
     }
   if(seconds>86400)// period W1 or MN
     {
      if(time_array[2]!=date.year)
        {
         x=true;
         time_array[2]=date.year;
        }
     }
   return(x);
  }

5.2. Fonction de synchronisation

La fonction de synchronisation comporte six paramètres d’entrée : quatre d’entre eux sont la priorité des prix, le paramètre booléen de synchronisation complète ou partielle et le tableau en cours d’analyse lui-même. La fonction est divisée en deux parties : un cas de synchronisation complète et partielle.

La synchronisation complète s’effectue en trois étapes :

  1. Calcul des éléments du tableau, satisfaisant à la condition de contenir des données sur les quatre types de prix.
  2. Copie d’éléments dans un tableau intermédiaire dans les mêmes conditions.
  3. Copie du tableau intermédiaire vers celui transmis par les paramètres.

La synchronisation partielle est plus complexe.

Le tableau de structure unidimensionnelle passé est converti en un tableau bidimensionnel, où le premier indice indique l’ordre et le second - le type de prix. Ensuite, introduit est un tableau unidimensionnel avec quatre éléments. Les niveaux de priorité de prix sont copiés dans ce tableau, puis le tableau est trié pour identifier l’ordre de priorité. Après cela, nous effectuons la distribution en fonction des priorités en utilisant la boucle pour et l’opérateur conditionnel si. Dans le même temps, si les priorités sont égales, la séquence des prix est la suivante: fermer, ouvrir, haut, bas. Dès que l’opérateur trouve la première valeur hiérarchisée, la boucle remplace toutes les données nulles du tableau bidimensionnel créé précédemment par les données prioritaires, etc.

//+------------------------------------------------------------------+
// Func Synchronization                                              |
//+------------------------------------------------------------------+
void func_synchronization(buffer_info &info[],
                          bool synchronization,
                          char close,
                          char open,
                          char high,
                          char low)
  {
   if(synchronization==true)// carry out a complete synchronization
     {
      int calc=0;// count variable
      for(int x=0; x<ArraySize(info); x++)// count complete data
        {
         if(info[x].close!=0 && info[x].high!=0 && info[x].low!=0 && info[x].open!=0)calc++;
        }
      buffer_info i_info[];    // enter a temporary array for copying
      ArrayResize(i_info,calc);// change the size of the temporary array
      calc=0;
      for(int x=0; x<ArraySize(info); x++)// copy data into the temporary array
        {
         if(info[x].close!=0 && info[x].high!=0 && info[x].low!=0 && info[x].open!=0)
           {
            i_info[calc]=info[x];
            calc++;
           }
        }
      ZeroMemory(info);        // clear the target array
      ArrayResize(info,calc);  // change the size of the main array
      for(int x=0; x<calc; x++)// copy data from the temporary array to the main one
        {
         info[x]=i_info[x];
        }
     }
   if(synchronization==false)  // change zero values to priority ones
     {
      int size=ArraySize(info); // measure the size of the array
      double buffer[][4];       // create a temporary array for calculation
      ArrayResize(buffer,size); // change the size of the temporary array
      for(int x=0; x<size; x++) // copy data into the temporary array
        {
         buffer[x][0]=info[x].close;
         buffer[x][1]=info[x].open;
         buffer[x][2]=info[x].high;
         buffer[x][3]=info[x].low;
        }
      char p[4];// enter an array for sorting by the order
      p[0]=close; p[1]=open; p[2]=high; p[3]=low;// assign variables for further sorting
      ArraySort(p); // sort
      int z=0,v=0;  // initialize frequently used variables
      for(int x=0; x<4; x++)// taking into account the results of the sorting, look through all variables and substitute them according to the priority
        {
         if(p[x]==close)// priority is for the closing prices
           {
            for(z=0; z<size; z++)
              {
               for(v=1; v<4; v++)
                 {
                  if(buffer[z][v]==0)buffer[z][v]=buffer[z][0];
                 }
              }
           }
         if(p[x]==open)// priority is for the opening prices
           {
            for(z=0; z<size; z++)
              {
               for(v=0; v<4; v++)
                 {
                  if(v!=1 && buffer[z][v]==0)buffer[z][v]=buffer[z][1];
                 }
              }
           }
         if(p[x]==high)// priority is for the maximum prices
           {
            for(z=0; z<size; z++)
              {
               for(v=0; v<4; v++)
                 {
                  if(v!=2 && buffer[z][v]==0)buffer[z][v]=buffer[z][2];
                 }
              }
           }
         if(p[x]==low)// priority is for the minimum prices
           {
            for(z=0; z<size; z++)
              {
               for(v=0; v<3; v++)
                 {
                  if(buffer[z][v]==0)buffer[z][v]=buffer[z][3];
                 }
              }
           }
        }
      for(int x=0; x<size; x++)// copy data from the temporary array back
        {
         info[x].close=buffer[x][0];
         info[x].open=buffer[x][1];
         info[x].high=buffer[x][2];
         info[x].low=buffer[x][3];
        }
     }
  }

5.3. Fonction de la moyenne mobile

C’est la fonction la plus simple. En utilisant la poignée d’indicateur, reçue dans la fonction OnInit, nous copions la valeur, correspondant à la date passée dans les paramètres de la fonction. Ensuite, cette valeur est renvoyée en réponse à cette fonction.

//+------------------------------------------------------------------+
// Func MA                                                           |
//+------------------------------------------------------------------+
double func_ma(datetime date)
  {
   double x[1];
   CopyBuffer(handle,0,date,1,x);
   return(x[0]);
  }

La fonction de traçage d’un graphique est classiquement divisée en deux parties: le tracé classique et le tracé modifié. La fonction a deux paramètres d’entrée: le type de prix pour la construction (ignoré lors de la construction modifiée) et le type de construction (classique et modifié).

Au tout début, les tampons indicateurs sont nettoyés puis, selon le type de construction, divisés en deux parties. La première partie (nous parlons de la construction modifiée) commence par appeler la fonction de calcul des quatre types de prix. Ensuite, nous créons un tableau de données commun où nous copions les données utilisées, reçues lors de l’appel de la fonction de calcul des données. Ensuite, le tableau de données reçues est trié et effacé des données répliquées. Après cela, le tableau data_for_buffer[], déclaré au niveau global, est rempli en fonction de dates consécutives avec la synchronisation des données suivante. Le remplissage des tampons indicateurs est la dernière étape de la construction modifiée.

La deuxième partie (construction classique) est beaucoup plus simple. Au début, la fonction de calcul des données est appelée, puis les tampons d’indicateurs sont remplis.

//+------------------------------------------------------------------+
//| Func Chart Build                                                 |
//+------------------------------------------------------------------+
void func_chart_build(char price, // price type for chart construction
                      char type)  // type of chart construction
  {
//--- Zeroise the buffers
   ZeroMemory(ABCTBBuffer1);
   ZeroMemory(ABCTBBuffer2);
   ZeroMemory(ABCTBBuffer3);
   ZeroMemory(ABCTBBuffer4);
   ZeroMemory(ABCTBColors);
   ZeroMemory(LINE_TLBBuffer);
   if(type==1)// construct a modified chart (based on all price types)
     {
      func_build_three_line_break(rates_array,0,step_min,line_to_back,line_main_close);// data on closing prices
      func_build_three_line_break(rates_array,1,step_min,line_to_back,line_main_open);// data on opening prices
      func_build_three_line_break(rates_array,2,step_min,line_to_back,line_main_high);// data on maximum prices
      func_build_three_line_break(rates_array,3,step_min,line_to_back,line_main_low);// data on minimum prices
      //--- calculate data arrays
      int line_main_calc[4];
      line_main_calc[0]=ArraySize(line_main_close);
      line_main_calc[1]=ArraySize(line_main_open);
      line_main_calc[2]=ArraySize(line_main_high);
      line_main_calc[3]=ArraySize(line_main_low);
      //--- gather the date array
      int all_elements=line_main_calc[0]+line_main_calc[1]+line_main_calc[2]+line_main_calc[3];// find out the number of all elements
      datetime datetime_array[];// enter the array for copying
      ArrayResize(datetime_array,all_elements);
      int y[4];
      ZeroMemory(y);
      for(int x=0;x<ArraySize(datetime_array);x++)// copy data into the array
        {
         if(x<line_main_calc[0])
           {
            datetime_array[x]=line_main_close[y[0]].time;
            y[0]++;
           }
         if(x<line_main_calc[0]+line_main_calc[1] && x>=line_main_calc[0])
           {
            datetime_array[x]=line_main_open[y[1]].time;
            y[1]++;
           }
         if(x<line_main_calc[0]+line_main_calc[1]+line_main_calc[2] && x>=line_main_calc[0]+line_main_calc[1])
           {
            datetime_array[x]=line_main_high[y[2]].time;
            y[2]++;
           }
         if(x>=line_main_calc[0]+line_main_calc[1]+line_main_calc[2])
           {
            datetime_array[x]=line_main_low[y[3]].time;
            y[3]++;
           }
        }
      ArraySort(datetime_array);// sort the array
      //--- delete replicated data from the array
      int good_info=1;
      for(int x=1;x<ArraySize(datetime_array);x++)// count useful information
        {
         if(datetime_array[x-1]!=datetime_array[x])good_info++;
        }
      ArrayResize(array_datetime,good_info);
      array_datetime[0]=datetime_array[0];// copy the first element as it is the pattern in the beginning of comparison
      good_info=1;
      for(int x=1;x<ArraySize(datetime_array);x++)// fill the new array with useful data
        {
         if(datetime_array[x-1]!=datetime_array[x])
           {
            array_datetime[good_info]=datetime_array[x];
            good_info++;
           }
        }
      //--- fill the buffer for drawing (colored candles)
      int end_of_calc[4];// variables of storing information about the last comparison
      ZeroMemory(end_of_calc);
      ZeroMemory(data_for_buffer);
      ArrayResize(data_for_buffer,ArraySize(array_datetime));// change the size of the declared global array for storing data before passing it to a buffer
      for(int x=0; x<ArraySize(array_datetime); x++)
        {
         data_for_buffer[x].time=array_datetime[x];
         for(int s=end_of_calc[0]; s<line_main_calc[0]; s++)
           {
            if(array_datetime[x]==line_main_close[s].time)
              {
               end_of_calc[0]=s;
               if(line_main_close[s].type==1)data_for_buffer[x].close=line_main_close[s].up;
               else data_for_buffer[x].close=line_main_close[s].down;
               break;
              }
           }
         for(int s=end_of_calc[1]; s<line_main_calc[1]; s++)
           {
            if(array_datetime[x]==line_main_open[s].time)
              {
               end_of_calc[1]=s;
               if(line_main_open[s].type==1)data_for_buffer[x].open=line_main_open[s].down;
               else data_for_buffer[x].open=line_main_open[s].up;
               break;
              }
           }
         for(int s=end_of_calc[2]; s<line_main_calc[2]; s++)
           {
            if(array_datetime[x]==line_main_high[s].time)
              {
               end_of_calc[2]=s;
               data_for_buffer[x].high=line_main_high[s].up;
               break;
              }
           }
         for(int s=end_of_calc[3]; s<line_main_calc[3]; s++)
           {
            if(array_datetime[x]==line_main_low[s].time)
              {
               end_of_calc[3]=s;
               data_for_buffer[x].low=line_main_low[s].down;
               break;
              }
           }
        }
      //--- start the function of synchronizing data
      func_synchronization(data_for_buffer,chart_synchronization,chart_priority_close,chart_priority_open,chart_priority_high,chart_priority_low);
      //--- preparatory actions before starting the function func_date_color
      ZeroMemory(time_array);
      time_variable=0;
      latch=false;
      //--- fill the buffer for drawing candles
      for(int x=ArraySize(data_for_buffer)-1,z=0; x>=0; x--)
        {
         ABCTBBuffer1[z]=data_for_buffer[x].open;
         ABCTBBuffer2[z]=data_for_buffer[x].high;
         ABCTBBuffer3[z]=data_for_buffer[x].low;
         ABCTBBuffer4[z]=data_for_buffer[x].close;
         if(ABCTBBuffer1[z]<=ABCTBBuffer4[z])ABCTBColors[z]=0;
         if(ABCTBBuffer1[z]>=ABCTBBuffer4[z])ABCTBColors[z]=1;
         if(func_date_color(data_for_buffer[x].time)==true && chart_color_period==true)ABCTBColors[z]=2;
         if(ma_draw==true)LINE_TLBBuffer[z]=func_ma(data_for_buffer[x].time);
         z++;
        }
     }
   else// construct a classic chart (based on one price type)
     {
      func_build_three_line_break(rates_array,price,step_min,line_to_back,line_main_close);// find data on selected prices
      ArrayResize(array_datetime,ArraySize(line_main_close));
      //--- preparatory actions before starting the function func_date_color
      ZeroMemory(time_array);
      time_variable=0;
      latch=false;
      //--- the buffer for drawing candles
      for(int x=ArraySize(line_main_close)-1,z=0; x>=0; x--)
        {
         ABCTBBuffer1[z]=line_main_close[x].up;
         ABCTBBuffer2[z]=line_main_close[x].up;
         ABCTBBuffer3[z]=line_main_close[x].down;
         ABCTBBuffer4[z]=line_main_close[x].down;
         if(line_main_close[x].type==1)ABCTBColors[z]=0;
         else ABCTBColors[z]=1;
         if(func_date_color(line_main_close[x].time)==true && chart_color_period==true)ABCTBColors[z]=2;
         if(ma_draw==true)LINE_TLBBuffer[z]=func_ma(line_main_close[x].time);
         z++;
        }
     }
  }

6. Fonction de consolidation

Cette fonction unit tous les éléments indicateurs de contrôle. Au début, la date actuelle est définie, puis la fonction de copie des données et la fonction de construction de graphique sont appelées.

//+------------------------------------------------------------------+
//| Func Consolidation                                               |
//+------------------------------------------------------------------+
void func_consolidation()
  {
//--- defining the current date
   date_stop=TimeCurrent();
//--- copying data for analysis
   func_all_copy(rates_array,time_frame,first_date_start,date_stop);
//--- basic construction of the chart
   func_chart_build(chart_price,chart_type);
   ChartRedraw();
  }

7. Fonction de construction contrôlée par clé et automatiquement

Ces fonctions sont conçues pour un redécoupage de l’indicateur en appuyant sur la touche « R » (OnChartEvent) du clavier ou en le faisant automatiquement en fonction de la plage de temps sélectionnée (OnCalculate). Cette dernière est analysée par la nouvelle fonction barre (func_new_bar) qui est une version simplifiée de la fonction décrite dans IsNewBar.

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//---
   if(func_new_bar(time_redraw)==true)
     {
      func_consolidation();
     };
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- event of a keystroke
   if(id==CHARTEVENT_KEYDOWN)
     {
      if(lparam==82) //--- the key "R" has been pressed
        {
         func_consolidation();
        }
     }
  }
//+------------------------------------------------------------------+
//| Func New Bar                                                     |
//+------------------------------------------------------------------+
bool func_new_bar(ENUM_TIMEFRAMES period_time)
  {
//---
   static datetime old_times; // variable of storing old values
   bool res=false;            // variable of the analysis result
   datetime new_time[1];      // time of a new bar
//---
   int copied=CopyTime(_Symbol,period_time,0,1,new_time); // copy the time of the last bar to the cell new_time
//---
   if(copied>0) // everything is ок. data copied
     {
      if(old_times!=new_time[0]) // if the old time of the bar is not equal to the new one
        {
         if(old_times!=0) res=true; // if it is not the first start, then new bar = true
         old_times=new_time[0];     // remember the time of the bar
        }
     }
//---
   return(res);
  }

À ce stade, nous allons terminer la description du code de l’indicateur et parler des façons de l’utiliser.


Exemples d’utilisation de l’indicateur et d’une stratégie de trading

Commençons par les principales stratégies d’analyse basées sur la construction graphique classique.

1. les lignes blanches et noires comme signaux d’achat et de vente

En gros, nous pouvons parler de deux règles:

  1. Règle N°1: Acheter, quand il y a trois lignes ascendantes consécutives et vendre, quand il y a trois lignes descendantes consécutives. Trois lignes consécutives indiquent une tendance à apparaître.
  2. Règle N°2: Vendre, lorsque la ligne d’inversion tombe en dessous de trois lignes ascendantes consécutives, acheter, lorsque la ligne d’inversion est supérieure à trois lignes descendantes consécutives.

Regardons la fig.6, représentant une construction classique pour EURUSD H1 en début de 2013 (la plage de temps analysée est illustrée à la fig.5).

Fig.5 Plage de temps analysée

Fig.5 Plage de temps analysée EURUSD H1

Fig.6 Construction classique du graphique à trois sauts de ligne pour EURUSD H1,

Fig.6 Construction classique du graphique à trois sauts de ligne pour EURUSD H1, début 2013, cours de fermeture

Sur le graphique (fig. 6), nous pouvons clairement voir le signal (règle N° 1) entre les points 1 et 2, qui est un point de départ pour la vente. Dans ce cas, le gain est supérieur à 200 points pour quatre chiffres décimaux. Le point 4 suivant indique une situation favorable à l’achat (comme dans la règle N° 2). À la fermeture au point 5, le bénéfice était de 40 points et nous sommes au seuil de rentabilité à la fermeture au point 6.

Au point 6, nous pouvons voir un signal de vente (règle N° 2). Nous obtenons 10 points de profit lors de la fermeture au point 7 et le seuil de rentabilité à la fermeture au point 8. Les points 8 et 9 ne peuvent être considérés comme des signaux car ils ne satisfont ni à la règle N° 1, ni à la règle N° 2. Nous pouvons acheter au point 10 (règle N° 1); nous pouvons également obtenir un bénéfice de 20 points à la clôture au point 11 ou au seuil de rentabilité au point 12. Tous les chiffres ont été arrondis.

Dans le meilleur des cas, en utilisant cette stratégie, nous pourrions générer un profit de 270 points, ce qui est impressionnant. Dans le même temps, dans la plage de temps spécifiée, il y a un mouvement intense qui affecte le profit. Dans le pire des cas, le trading peut entraîner un seuil de rentabilité, ce qui n’est pas mal non plus.

Il convient de mentionner que lorsqu’une situation répond à la règle N° 1 ou à la règle N° 2, nous devons attendre une confirmation d’inversion de tendance représentée par une ligne dans la même direction que la tendance.

2. Canal équidistant, support et lignes résistantes

Une autre stratégie de trading consiste à appliquer une analyse technique au graphique à trois sauts de ligne. Jetons un coup d’œil à la fig. 7:

Fig. 7 Canal équidistant, support et lignes résistantes, GBPUSD H1, plage de temps du 01.03.2014 au 01.05.2014

Fig. 7 Canal équidistant, support et lignes résistantes, GBPUSD H1, plage de temps du 01.03.2014 au 01.05.2014

Dans la Fig. 7, vous pouvez voir que le canal équidistant descendant est dessiné en lignes rouges, le canal ascendant est dessiné en bleu et les lignes de support et de résistance sont dessinées en noir. Il est clair que la première ligne de résistance se transforme en ligne de support.

3. Motifs de chandeliers

Un graphique modifié (deux sauts de ligne) sur la période M30 pour la paire USDCAD au début de 2013 semble plutôt intéressant.

On peut distinguer les motifs de chandeliers japonais qui justifiaient leurs signaux (fig. 8).

Fig. 8 Graphique à trois sauts de ligne modifié, USDCAD M30, début 2013, deux sauts de ligne

Fig. 8 Graphique à trois sauts de ligne modifié, USDCAD M30, début 2013, deux sauts de ligne

Au début du graphique, nous pouvons voir un modèle d’inversion de « Engloutissement » sous le N° 1. Il se compose de deux chandelles: rouge et la précédente bleue. Après la ligne de tendance à la hausse, le marché descend au numéro 2 qui est un motif d’inversion à une chandelle « Marteau ». À ce stade, le marché change de direction. La même chose se produit dans le modèle No3 (« La toupie »). Le motif d’inversion suivant « Kharami » (No4) est représenté par le chandelier 4 et le grand ascendant à côté. Le motif No6 se compose également de deux chandeliers (motif « Engulfing ») mais contrairement au premier modèle similaire, il fait tourner le marché dans la direction opposée.

Ainsi, on peut conclure que l’utilisation de l’indicateur dans ce type d’analyse est acceptable, mais qu’elle présente des inconvénients tels que l’apparition rare de signaux et la possibilité d’un retrait significatif. Cette stratégie doit certainement être approfondie.

4. Moyenne mobile

Une modification partielle, comme l’ajout d’une moyenne mobile uniquement aux lignes tracées, offre de nouvelles possibilités d’analyse.

Regardons la fig. 9:

Fig.9 Analyse de la moyenne mobile, EURUSD H4, graphique des trois sauts de ligne, construction classique, du 01.01.2014 au 01.07.2014

Fig.9 Analyse de la moyenne mobile, EURUSD H4, le graphique à trois sauts de ligne, construction classique, du 01.01.2014 au 01.07.2014

La partie supérieure de la fig. 9 illustre une construction classique basée sur les prix élevés avec une moyenne mobile (la période de moyenne est de 90, le prix bas, la moyenne lissée). La partie inférieure montre une construction classique basée sur des prix bas avec une moyenne mobile (la période moyenne est de 90, le prix élevé, la moyenne lissée).

Ainsi, dans la partie supérieure de la fig. 9, la moyenne mobile peut être considérée comme une ligne de support et dans la partie inférieure, au contraire, une ligne de résistance. Si le prix sur les deux graphiques tombe en dessous de la moyenne, il y a une tendance à la baisse sur le marché et il est préférable de vendre. Lorsque le prix dépasse la moyenne, il est temps d’acheter. Un inconvénient de cette stratégie est qu’elle est destinée à un trading à long terme.


Conclusion

En conclusion, je peux dire que le trois sauts de ligne donne constamment de bons signaux ou, dans le pire des cas, conduit à l’équilibre. La pratique montre qu’il est préférable de l’appliquer dans une tendance à long terme et, par conséquent, je ne recommande pas d’utiliser ce graphique pour un trading à court terme. Si quelqu’un a de nouvelles idées sur la façon de l’utiliser dans le trading, je serais heureux d’en discuter.

Comme d’habitude, j’ai essayé d’explorer le code en détail. Encore une fois, s’il y a des idées sur la façon de l’étendre, de le retravailler ou de l’optimiser, veuillez écrire dans les commentaires de l’article.


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

Fichiers joints |
abctb.mq5 (68.78 KB)
Récits de Robots de Trading : Est-ce moins plus que ca ? Récits de Robots de Trading : Est-ce moins plus que ca ?
Il y a deux ans, dans « La Dernière Croisade », nous avons passé en revue une méthode intéressante mais actuellement peu utilisée pour afficher des informations sur le marché - des graphiques de points et de figures. Maintenant, je vous suggère d’essayer d’écrire un robot de trading basé sur les modèles détectés sur le graphique de points et de figures.
SQL et MQL5 : Travailler avec la base de données SQLite SQL et MQL5 : Travailler avec la base de données SQLite
Cet article est destiné aux développeurs qui seraient intéressés par l'utilisation de SQL dans leurs projets. Il explique les fonctionnalités et les avantages de SQLite. L'article ne nécessite pas de connaissance particulière des fonctions SQLite, mais une compréhension minimale de SQL serait bénéfique.
Construire une start-up de technologie sociale, Première partie Envoyez des Tweets sur vos signaux MetaTrader 5 Construire une start-up de technologie sociale, Première partie Envoyez des Tweets sur vos signaux MetaTrader 5
Aujourd’hui, nous allons apprendre à lier un terminal MetaTrader 5 à Twitter afin de pouvoir tweeter les signaux de trading de vos EA. Nous développons un système d’aide à la décision sociale en PHP basé sur un service Web RESTful. Cette idée vient exceptionnellement d’une conception du trading automatique appelée trading assisté par ordinateur. Nous voulons que les capacités cognitives des traders humains filtrent les signaux de trading qui, autrement, seraient automatiquement mis sur le marché par les Experts Advisors.
Réseau neuronal bon marché et joyeux - Lier NeuroPro avec MetaTrader 5 Réseau neuronal bon marché et joyeux - Lier NeuroPro avec MetaTrader 5
Si des programmes de réseau neuronal spécifiques au trading vous semblent coûteux et complexes ou, au contraire, trop simples, essayez NeuroPro. Il est gratuit et contient l'ensemble optimal de fonctionnalités pour les amateurs. Cet article vous expliquera comment l'utiliser en conjonction avec MetaTrader 5.