English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Indicateur pour la cartographie Renko

Indicateur pour la cartographie Renko

MetaTrader 5Exemples | 13 janvier 2022, 13:42
431 0
Dmitriy Zabudskiy
Dmitriy Zabudskiy

Introduction

Les articles Indicateur pour les graphiques en points et figures et indicateur pour les graphiques Kagi décrivent les principes de graphique des indicateurs en points et «Kagi». Étudions l'une des méthodes de programmation pour créer un graphique Renko .

Le nom « Renko » est dérivé du mot japonais « renga », une brique. Le graphique Renko est construit à partir d'une série de briques dont la création est déterminée par les fluctuations de prix. Lorsqu'un prix augmente, une brique vers le haut est placée sur le graphique et, en cas de baisse de prix, une brique vers le bas est ajoutée. « Renko » signifie « rythme lent » en japonais. La carte Renko est apparue au Japon, probablement, quelque part au 19ème siècle. Les États-Unis et l'Europe en ont entendu parler pour la première fois après que Steeve Nison l'a publié en 1994, dans son livre Beyond Candlesticks : De nouvelles techniques de cartographie japonaises révélées.

Le graphique Renko comme les graphiques mentionnés ci-dessus ignore une chronologie et ne concerne que le mouvement des prix. Contrairement au graphique Point et Figure, le Renko place chaque «brique» dans une nouvelle colonne (dans un nouveau plan vertical), quant au reste, ils ont une méthode de création commune : la taille d'une «brique» («point», «figure») est fixe, l'analyse des prix et la doublure des chiffres sont faites de manière similaire.

Ainsi, le graphique Renko est un ensemble de barres verticales («briques»). Les briques blanches (creuses) sont utilisées lorsque la direction de la tendance est à la hausse, tandis que les briques noires (remplies) sont utilisées lorsque la tendance est à la baisse. La construction est réglée avec le comportement de prix. Le prix actuel de la période prise est comparé au minimum et au maximum de la brique précédente (blanche ou noire). Si l'action se ferme plus haut que son prix d'ouverture, une brique creuse (blanche) est dessinée avec le bas du corps représentant le prix d'ouverture et le haut du corps représentant le prix de fermeture. Si l'action se ferme en dessous de son prix d'ouverture, une brique remplie (noire) est dessinée avec le haut du corps représentant le prix d'ouverture et le bas du corps représentant le prix de fermeture.

La toute première brique du graphique est dessinée en fonction du comportement des prix, le prix d'ouverture de la barre est pris pour un maximum et un minimum de la brique précédente.

Un exemple de graphique Renko standard, Fig. 1 :

Fig. 1. Un exemple de graphique Renko standard

Fig. 1. Un exemple de graphique Renko standard

1. Exemple de graphique

Un graphique Renko standard est établi sur la base du cours de fermeture. Tout d'abord, sélectionnez la période et la taille de la boîte.

Dans cet exemple, l'EURUSD (période H4) est utilisé, avec une taille de boîte de 30 points. Le résultat de la cartographie Renko du 03.01.2014 au 31.01.2014 (environ un mois) est montré sur la Fig. 2, à gauche, il y a une cartographie d'une période donnée (ici vous pouvez voir l'extension horizontale des briques), sur la droite, il y a un résultat de la cartographie Renko :


Fig.2. Le résultat du graphique Renko en EURUSD (H4, la case est de 30 points)  

Fig.2. Le résultat du graphique Renko en EURUSD (H4, la case est de 30 points)

Examinons de plus près le principe de la cartographie. Dans la Fig. 2 lignes horizontales rouges montrent la taille de chaque brique en fonction des changements de prix (30 points), la couleur bleue indique les dates les plus intéressantes.

Comme vous pouvez le voir sur le graphique à la fin du 01/03/2014, un chandelier se ferme en dessous de 1,3591 comme fourchettes de prix précédemment définies (lignes horizontales rouges) à 1,3589 (marqué avec le prix), ce qui crée une brique descendante sur le graphique.

Après cela, le prix est plat (il ne ferme pas en dessous de 1,3561 ou au-dessus de 1,3651), il est ouvert jusqu'à 20h00 le 10.01.2014 (le chandelier créé à 16h00 ferme) et se ferme (au-dessus de 1,3651 prix) à 1,3663 (marqué avec prix). Ensuite, le prix redevient plat à 20h00 le 14.01.2014 (le chandelier ouvert à 16h00 ferme), où il dépasse la fourchette de prix, crée une nouvelle brique et se ferme à 1,3684.

Ensuite, vous assistez à une baisse où le prix franchit quatre fois les fourchettes en baisse sur le graphique. A 12h00 le 23.01.2014 (le chandelier ouvert à 08:00 ferme) il y a une percée haussière de deux gammes de prix qui, à son tour, ouvre deux briques en clôturant à 1,3639. La première brique est clairement visible, la seconde est tirée en une longue ligne verticale (en raison de l'ouverture simultanée avec la première brique). La construction se poursuit sur les mêmes principes.


2. Principe de la cartographie Renko

Lors de l'élaboration de cet indicateur, toutes les fonctions ont été mises en œuvre de la manière la plus indépendante possible. L'un des principaux objectifs était de maximiser le potentiel de l'indicateur pour faciliter l'analyse du marché.

Les calculs ne sont pas effectués dans le délai actuel, c'est-à-dire que le délai est sélectionné dans les paramètres, et quel que soit le délai, où l'indicateur a été lancé, il affichera les données de configuration. Cela peut être réalisé en copiant les données de la période prise dans des tableaux de tampons séparés, des calculs ultérieurs sont effectués et l'indicateur de tampon de sortie est rempli.

Le graphique Renko standard est construit en fonction des prix de fermeture, cependant, les valeurs Ouvrir, Haut, Bas sont utilisées pour améliorer l'analyse.

Étant donné que les briques du graphique Renko sont de taille similaire, il est utile de connaître les points de marché les plus dynamiques entraînés par le comportement des prix fort (en quelques briques). A cet effet, il y a une indication (désactivée) représentée par une petite ombre verticale (comme dans Japanese Candlestick) d'une brique, qui monte ou descend sur le dernier niveau de brique du choix barre de temps.

La possibilité de construire des ZigZag sur le graphique principal élargit l'analyse graphique.

La figure 3 représente l'indicateur en pleine fonctionnalité :

Figure 3. L'indicateur du graphique EURUSD (Au quotidien, l'étape est de 25 points)

Figure 3. L'indicateur du graphique EURUSD (Tous les jours, le pas est de 25 points)


3. Code et algorithme de l'indicateur

Le code indicateur est assez volumineux car il est composé de 900 lignes. Comme mentionné précédemment, des fonctions séparées au maximum peuvent compliquer la compréhension de l'algorithme. Certaines fonctions de l'article précédent serviront de base. En cas de malentendu sur certains aspects, vous pouvez vous référer à l'indicateur de construction du graphique Kagi ou vous pouvez m'envoyer un email.

Chaque fonction du code sera expliquée dans l'article. Les fonctions seront décrites sur place.


3.1. Paramètres d'entrée de l'indicateur

Le graphique Renko est la gamme de briques haut et bas de différentes couleurs. Ce type de construction ne nécessite que cinq tampons combinés dans une construction graphique « Chandeliers colorés ». Les quatre tampons restants collectent les données nécessaires au calcul de l'indicateur.

Prenez les paramètres d'entrée (25), divisés en groupes.

  • étape - une taille de brique ou une étape ;
  • type_step - type d'étape, en points ou en pourcentage (ce dernier est calculé en fonction du prix actuel) ;
  • magic_numb - un nombre magique requis pour distinguer les objets graphiques et utilisé pour les supprimer du graphique ;
  • levels_number - niveaux (0-pas de niveaux) pour diviser les briques dans la fenêtre de l'indicateur ;
  • levels_color - couleur des niveaux dans la fenêtre de l'indicateur ;
  • time_frame - utilisé pour définir une période pour la construction du graphique (la période analysée) ;
  • time_redraw- heure de mise à jour du graphique ;
  • first_date_start - date de début de la cartographie ;
  • type_price - types de prix pour la construction : Fermeture - la méthode standard basée sur le cours de fermeture ; Ouvert - prix d'ouverture ; Haut - prix maximum et Bas - prix minimum ;
  • shadow_print - si vous définissez l'option vraie, les ombres représentent le prix maximum ou minimum causé l'ouverture de plusieurs briques ;
  • filter_number - valeur de briques utilisée pour l'inversion du graphique (une option supplémentaire responsable du nombre de briques nécessaires pour inverser le graphique) ;
  • zig_zag - utilisé pour dessiner des ZigZags sur le graphique principal (un dessin supplémentaire sur le graphique principal qui facilite une analyse ou utilisé pour la mise à jour du graphique) ;
  • zig_zag_shadow - utilisé pour dessiner des zigzags en fonction des prix maximum et minimum (utilise les prix maximum et minimum les plus proches pour construire des zigzags sur les points de terminaison) ;
  • zig_zag_width - Largeur de ligne en zigzag ;
  • zig_zag_color_up - Couleur de la ligne ascendante en zigzag ;
  • zig_zag_color_down - Couleur de la ligne descendante en zigzag ;
  • square_draw - utilisé pour dessiner des briques sur le graphique principal (dans ce mode, vous pouvez voir les mouvements de prix qui ouvrent les briques);
  • square_color_up - couleur de brique sur le graphique ascendant principal ;
  • square_color_down - couleur de brique sur le graphique descendant principal ;
  • square_fill- coloration des briques sur le graphique principal ;
  • square_width - largeur de ligne de brique sur le graphique principal ;
  • frame_draw - utilisé pour dessiner des cadres de briques (représente les bordures de briques, c'est une option supplémentaire qui est rarement utilisée);
  • frame_width - largeur de ligne de brique ;
  • frame_color_up - couleur des bordures des briques haut ;
  • frame_color_down - couleur des bordures de briques en duvet.

Ensuite, le code déclare des tampons : cinq tampons principaux sont utilisés pour le dessin graphique tandis que quatre sont utilisés pour stocker les données de conception et de calcul. Price[] - tampon pour stocker les prix copiés utilisés pour la construction, Date[] - tampon pour stocker les données copiées utilisées pour le dessin sur le graphique principal, Price_high[] et Price_low[] - tampons pour stocker les valeurs maximales et minimales appliquées dans les dessins ZigZags sur la carte principale.

Après ce calcul, les tableaux de tampons et les variables de fonctions auxiliaires sont déclarés : func_draw_renko, func_draw_zig_zag, func_draw_renko_main_chart. Ils seront expliqués plus tard.

//+------------------------------------------------------------------+
//|                                                         ABCR.mq5 |
//|                                   Azotskiy Aktiniy ICQ:695710750 |
//|                          https://www.mql5.com/ru/users/Aktiniy |
//+------------------------------------------------------------------+
//--- Auto Build Chart Renko
#property copyright "Azotskiy Aktiniy ICQ:695710750"
#property link      "https://www.mql5.com/ru/users/Aktiniy"
#property version   "1.00"
#property description "Auto Build Chart Renko"
#property description "   "
#property description "This indicator used to draw Renko chart in the indicator window, and in the main chart window"
#property indicator_separate_window
#property indicator_buffers 9
#property indicator_plots   1
//--- plot RENKO
#property indicator_label1  "RENKO"
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrRed,clrBlue,C'0,0,0',C'0,0,0',C'0,0,0',C'0,0,0',C'0,0,0',C'0,0,0'
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- construction method
enum type_step_renko
  {
   point=0,   // Point
   percent=1, // Percent
  };
//--- type of price
enum type_price_renko
  {
   close=0, // Close
   open=1,  // Open
   high=2,  // High
   low=3,   // Low
  };
//--- input parameters
input double           step=10;                                 // Step
input type_step_renko  type_step=point;                         // Type of step
input long             magic_numb=65758473787389;               // Magic number
input int              levels_number=1000;                      // Number of levels (0-no levels)
input color            levels_color=clrLavender;                // Color of levels
input ENUM_TIMEFRAMES  time_frame=PERIOD_CURRENT;               // Calculation period
input ENUM_TIMEFRAMES  time_redraw=PERIOD_M1;                   // Chart redraw period
input datetime         first_date_start=D'2013.09.13 00:00:00'; // Start date
input type_price_renko type_price=close;                        // Price for construction
input bool             shadow_print=true;                       // Show shadows
input int              filter_number=0;                         // Bricks number needed to reversal
input bool             zig_zag=true;                            // Whether ZigZag should be drawn on the main chart
input bool             zig_zag_shadow=true;                     // Draw ZigZag at highs and lows of the price
input int              zig_zag_width=2;                         // ZigZag line width
input color            zig_zag_color_up=clrBlue;                // ZigZag up line color
input color            zig_zag_color_down=clrRed;               // ZigZag down line color
input bool             square_draw=true;                        // Whether bricks should be drawn on the main chart
input color            square_color_up=clrBlue;                 // Up brick color on the main chart
input color            square_color_down=clrRed;                // Down brick color on the main chart
input bool             square_fill=true;                        // Brick filling on the main chart
input int              square_width=2;                          // Brick line width on the main chart
input bool             frame_draw=true;                         // Whether to draw frames of the bricks
input int              frame_width=2;                           // Brick frame line width
input color            frame_color_up=clrBlue;                  // Up brick frames color
input color            frame_color_down=clrRed;                 // Down brick frames color
//--- indicator buffers
double         RENKO_open[];
double         RENKO_high[];
double         RENKO_low[];
double         RENKO_close[];
double         RENKO_color[];

double         Price[];      // copy price data to the buffer
double         Date[];       // copy data to the buffer
double         Price_high[]; // copy high prices to the buffer
double         Price_low[];  // copy low prices to the buffer
//--- calculation buffer arrays
double         up_price[];    // up brick price
double         down_price[];  // down brick price
char           type_box[];    // brick type (up, down)
datetime       time_box[];    // brick copy time
double         shadow_up[];   // up high price
double         shadow_down[]; // down low price
int            number_id[];   // Index of Price_high and Price_low arrays
//--- calculation global variables
int obj=0;           //variable for storing number of graphics objects
int a=0;             // variable to count bricks
int bars;            // number of bars
datetime date_stop;  // current data
datetime date_start; // start date variable, for calculations
bool date_change;    // variable for storing details about time changes


3.2. Initialisation d'indicateur

Les tampons d'indicateurs sont liés à des tableaux dynamiques unidimensionnels, l'adressage, ainsi que dans les séries temporelles, défini dans les tampons INDICATOR_DATA et INDICATOR_COLOR_INDEX. L'adressage des autres tableaux dynamiques (Prix[], Date[], Price_high[], Price_low[]) est laissé sans modification, car ils ne sont utilisés que pour stocker des données.

Les valeurs qui ne sont pas affichées sur le graphique sont définies. Ensuite, le nom est attribué à l'indicateur, la précision d'affichage est réglée et l'affichage des valeurs numériques actuelles est interdit dans la fenêtre de l'indicateur.

Après cela, la valeur de la variable date_start (date de début des calculs) est affectée. La valeur de la variable est affectée, la valeur d'entrée n'est pas utilisée car le graphique peut être trop lourd pour le tampon de l'indicateur. La date de début est corrigée et la coutume est annoncée. La fonction de la date de début d'analyse ou «func_calc_date_start» effectue des corrections de temps.

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,RENKO_open,INDICATOR_DATA);
   ArraySetAsSeries(RENKO_open,true);
   SetIndexBuffer(1,RENKO_high,INDICATOR_DATA);
   ArraySetAsSeries(RENKO_high,true);
   SetIndexBuffer(2,RENKO_low,INDICATOR_DATA);
   ArraySetAsSeries(RENKO_low,true);
   SetIndexBuffer(3,RENKO_close,INDICATOR_DATA);
   ArraySetAsSeries(RENKO_close,true);
   SetIndexBuffer(4,RENKO_color,INDICATOR_COLOR_INDEX);
   ArraySetAsSeries(RENKO_color,true);
//---
   SetIndexBuffer(5,Price,INDICATOR_CALCULATIONS);      // initialize price buffer
   SetIndexBuffer(6,Date,INDICATOR_CALCULATIONS);       // initialize data buffer
   SetIndexBuffer(7,Price_high,INDICATOR_CALCULATIONS); // initialize high price
   SetIndexBuffer(8,Price_low,INDICATOR_CALCULATIONS);  // initialize low price
//--- set data which will not be drawn
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
//--- set the indicator appearance
   IndicatorSetString(INDICATOR_SHORTNAME,"ABCR "+IntegerToString(magic_numb)); // indicator name
//--- display accuracy
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- prohibit display of the results of the indicator current values
   PlotIndexSetInteger(0,PLOT_SHOW_DATA,false);
//--- assign start date variable value
   date_start=first_date_start;
//---
   return(INIT_SUCCEEDED);
  }

3.3. La fonction de calcul de la date de début de l'analyse

La fonction est petite et se compose principalement d'une boucle. Il n'y a que deux paramètres d'entrée - la date de début initialement définie et la date de fin du calcul (la date actuelle). La date de début est modifiée dans la fonction et elle est affichée comme réponse.

Le corps de la fonction commence par mesurer le tableau de tampons de réception (tous les tampons ont la même taille qui est égale au nombre de barres de période sélectionnées). Ensuite, un certain nombre de barres est mesurée sur la période sélectionnée.

Le nombre de barres de la période choisie et la taille du tableau de tampons sont comparés dans la condition de boucle. Si vous avez plus de barres, c'est-à-dire qu'elles ne peuvent pas toutes être placées dans le tableau de tampons, le délai pris est raccourci à dix jours, ce qui signifie que dix jours sont ajoutés à la date de début de l'analyse. Cela continue jusqu'à ce que le tableau de tampons ne soit pas en mesure d'inclure toutes les données de barres. La fonction renvoie la date calculée.

//+------------------------------------------------------------------+
//| Func Calculate Date Start                                        |
//+------------------------------------------------------------------+
datetime func_calc_date_start(datetime input_data_start,// initially start date set
                              datetime data_stop)       // calculation end date (current date)
//---
  {
   int Array_Size=ArraySize(Price);
   int Bars_Size=Bars(_Symbol,time_frame,input_data_start,data_stop);
   for(;Bars_Size>Array_Size;input_data_start+=864000) // 864000 = 10 days
     {
      Bars_Size=Bars(_Symbol,time_frame,input_data_start,data_stop);
     }
   return(input_data_start);
//---
  }

3.4. La fonction de copie de données

Tout d'abord, les données sont copiées avec les fonctions de copie de données (func_copy_price et func_copy_date).

Considérons la fonction de copie de prix ou func_copy_price, qui vous permet de copier dans le tableau les prix Ouvrir, Fermer, Haut et Bas de la période et du délai définis. En cas de copie réussie, la fonction renvoie «vraie».

Au début de l'appel de fonction, la fausse valeur est initialisée, puis une variable de résultat des données copiées est initialisée et une valeur négative est affectée. Un tableau commun price_interim[] pour stocker les données copiées temporaires et la variable bars_to_copy sont déclarés pour empêcher la sauvegarde des données copiées.

De plus, la fonction réinitialise les variables déclarées précédemment pour stocker les données copiées, calcule le nombre de barres sur la période et, en fonction du prix choisi (0-Fermer, 1-Ouvrir, 2-Haut et 3-Bas) et un switch , attribue la valeur des données précédemment copiées sur les prix variables bars_copied. Ensuite, le nombre de données à copier est calculé. Si les données ont été copiées auparavant, les dernières informations de barre copiées sont supprimées pour empêcher les modifications sur le graphique.

Un switch copie les données de prix requises dans le tableau de temps price_interim[]. Après cela, le résultat de la copie est vérifié et un switch remplit les variables de données copiées.

//+------------------------------------------------------------------+
//| Func Copy Price                                                  |
//+------------------------------------------------------------------+
bool func_copy_price(double &result_array[],
                     ENUM_TIMEFRAMES period,// Timeframe
                     datetime data_start,
                     datetime data_stop,
                     char price_type) // 0-Close, 1-Open, 2-High, 3-Low
  {
//---
   int x=false;        // Variable for answering
   int result_copy=-1; // copied data number
//---
   static double price_interim[]; // Temporal dynamic array for storing copied data
   static int bars_to_copy;       // number of bars to copy
   static int bars_copied_0;      // number of copied bars from Close start date
   static int bars_copied_1;      // number of copied bars from Open start date
   static int bars_copied_2;      // number of copied bars from High start date
   static int bars_copied_3;      // number of copied bars from Low start date
   static int bars_copied;        // number of copied bars from the common variable start date
//--- variables reset due to changes in a start date
   if(date_change==true)
     {
      ZeroMemory(price_interim);
      ZeroMemory(bars_to_copy);
      ZeroMemory(bars_copied_0);
      ZeroMemory(bars_copied_1);
      ZeroMemory(bars_copied_2);
      ZeroMemory(bars_copied_3);
      ZeroMemory(bars_copied);
     }
//--- get an information about the current bars number on the timeframe
   bars_to_copy=Bars(_Symbol,period,data_start,data_stop);
//--- assign a copied function value to a common variable
   switch(price_type)
     {
      case 0:
         //--- Close
         bars_copied=bars_copied_0;
         break;
      case 1:
         //--- Open
         bars_copied=bars_copied_1;
         break;
      case 2:
         //--- High
         bars_copied=bars_copied_2;
         break;
      case 3:
         //--- Low
         bars_copied=bars_copied_3;
         break;
     }
//--- calculate number of bars required to be copied
   bars_to_copy-=bars_copied; 
//--- if it is not the first time the data has been copied
   if(bars_copied!=0) 
     {
      bars_copied--;
      bars_to_copy++;
     }
//--- change the size of the recieving array
   ArrayResize(price_interim,bars_to_copy); 
//--- copy data to the recieving array
   switch(price_type)
     {
      case 0:
         //--- Close
        {
         result_copy=CopyClose(_Symbol,period,0,bars_to_copy,price_interim);
        }
      break;
      case 1:
         //--- Open
        {
         result_copy=CopyOpen(_Symbol,period,0,bars_to_copy,price_interim);
        }
      break;
      case 2:
         //--- High
        {
         result_copy=CopyHigh(_Symbol,period,0,bars_to_copy,price_interim);
        }
      break;
      case 3:
         //--- Low
        {
         result_copy=CopyLow(_Symbol,period,0,bars_to_copy,price_interim);
        }
      break;
     }
//--- check the result of data copying
   if(result_copy!=-1) // if copying to the intermediate array is successful
     {
      ArrayCopy(result_array,price_interim,bars_copied,0,WHOLE_ARRAY); // copy the data from the temporary array to the main one
      x=true;                   // assign the positive answer to the function
      bars_copied+=result_copy; // increase the value of the processed data
     }
//--- return the information about the processed data with one of the copied variables
   switch(price_type)
     {
      case 0:
         //--- Close
         bars_copied_0=bars_copied;
         break;
      case 1:
         //--- Open
         bars_copied_1=bars_copied;
         break;
      case 2:
         //--- High
         bars_copied_2=bars_copied;
         break;
      case 3:
         //--- Low
         bars_copied_3=bars_copied;
         break;
     }
//---
   return(x);
  }

 «func_copy_date» ou la fonction de copie de date. Le code de la fonction est similaire à l'unité mentionnée ci-dessus, la différence réside dans le type des données copiées.

//+------------------------------------------------------------------+
//| Func Copy Date                                                   |
//+------------------------------------------------------------------+
bool func_copy_date(double &result_array[],
                    ENUM_TIMEFRAMES period,// timeframe
                    datetime data_start,
                    datetime data_stop)
  {
//---
   int x=false;                    // variable for answer
   int result_copy=-1;             // number of copied data
   static datetime time_interim[]; // temporaty dynamic array for storing the copied data
   static int bars_to_copy;        // bars number required to be copied
   static int bars_copied;         // copied bars with start date
//--- variables reset due to the start date change
   if(date_change==true)
     {
      ZeroMemory(time_interim);
      ZeroMemory(bars_to_copy);
      ZeroMemory(bars_copied);
     }
//---
   bars_to_copy=Bars(_Symbol,period,data_start,data_stop); // Find out the current number of bars on the time interval
   bars_to_copy-=bars_copied; // Calculate the number of bars to be copied
//---
   if(bars_copied!=0) // If it is not the first time the data has been copied
     {
      bars_copied--;
      bars_to_copy++;
     }
//---
   ArrayResize(time_interim,bars_to_copy); // Change the size of the receiving array
   result_copy=CopyTime(_Symbol,period,0,bars_to_copy,time_interim);
//---
   if(result_copy!=-1) // If copying to the intermediate array is successful
     {
      ArrayCopy(result_array,time_interim,bars_copied,0,WHOLE_ARRAY); // Copy the data from the temporary array to the main one
      x=true; // assign the positive answer to the function
      bars_copied+=result_copy; // Increase the value of the processed data
     }
//---
   return(x);
  }

3.5. Calcul des briques

Comme vous pouvez le voir dans les paramètres de l'indicateur, une taille de brique peut être définie à la fois en points et en pourcentage du prix actuel. Les points sont une valeur fixe mais comment se font les calculs en pourcentage ? A cet effet, il existe la fonction de calcul des briques «func_calc_dorstep».

Il y a trois paramètres d'entrée : le prix actuel (pour calculer le pourcentage du prix, si la taille de la brique est en pourcentage), la méthode de calcul (points ou pourcentage) et la taille du pas (définie avec une valeur qui peut être en pourcentage ou en points).

Au début de la fonction, la variable pour la réponse est initialisée par type double et selon la méthode de calcul sélectionnée par l'instruction conditionnelle, si-autrement est affectée en points. Ensuite, la variable de réponse est convertie en type int pour conserver la valeur entière même si les calculs ont abouti en valeur non entière.

//+------------------------------------------------------------------+
//| Func Calculate Doorstep                                          |
//+------------------------------------------------------------------+
int func_calc_dorstep(double price,      // price
                      char type_doorstep,// step type
                      double doorstep)   // step
  {
   double x=0;          // variable for answer

   if(type_doorstep==0) // If the calculation is to be performed in points
     {
      x=doorstep;
     }

   if(type_doorstep==1) // If the calculation is to be performed in percentage
     {
      x=price/_Point*doorstep/100;
     }

   return((int)x);
  }

3.6. La fonction principale - Graduation du graphique Renko

La fonction principale de la graduation du graphique Renko - «func_draw_renko». Cette fonction est responsable des tampons graphiques (indicateurs de tampons ) et du remplissage des tableaux de tampons de calcul. Les tampons de calcul stockent les informations de chaque brique.

Les paramètres d'entrée de la fonction sont des tableaux de données de prix et de dates de construction des barres. Ici vous pouvez trouver des informations sur le type d'étape et son paramètre, le filtre inversé et le paramètre de dessin des ombres.

La fonction peut être divisée en deux parties : la partie avec le numéro de calcul des briques et la partie avec le remplissage des tampons de calcul et graphiques.

Au début de la fonction, les tampons sont réinitialisés pour désactiver les boîtes vides. Des variables auxiliaires ultérieures sont saisies : la variable «doorstep_now» est utilisée pour le pas (utilisée pour changer sa taille au pas de pourcentage), «point_go» stocke des informations sur la distance depuis la dernière brique construite, la variable «a» est utilisée pour le calcul des briques, «up_price_calc» et «down_price_calc» - les derniers prix haut et bas analysés, «type_box_calc» - le dernier type de brique analysé (haut ou bas).

Les deux parties fonctionnelles consistent en une boucle, la deuxième partie complète la première. Analysez le processus en détail.

La première boucle est traitée à travers toutes les valeurs copiées, la valeur «barres» est responsable d'un certain nombre de données copiées (elle est calculée dans une fonction «func_concolidation», qui sera considérée plus loin). Plus loin dans la boucle, la fonction commence les calculs de la taille de la brique. Étant donné que chaque barre a un prix de fermeture différent, si le pas de pourcentage est utilisé, il doit être calculé pour chaque barre séparément.

L'instruction conditionnelle si vérifie la direction du prix, alors que le prix doit franchir un ou plusieurs étapes. Une fois que la direction du mouvement des prix a été déterminée, la condition du mouvement précédent (la dernière brique) est vérifiée. Ceci est fait parce que les paramètres de l'indicateur incluent le paramètre de filtre (nombre de briques nécessaires pour l'inversion). Une fois toutes les conditions vérifiées, la boucle est lancée, elle est traitée autant de fois que les briques représentent le mouvement de prix actuel.

Les barres d'affichage sont calculées, les tableaux de tampons de calcul sont modifiés en taille et ils sont réinitialisés. Après cela, les premiers tableaux de calcul (utilisés lors de la première comparaison) se voient attribuer des valeurs primaires.

Si le nombre maximum possible de barres affichées est inférieur au nombre possible de briques, des briques supplémentaires sont calculées et le message concernant la valeur basse s'affiche. Ceci est fait pour éviter un affichage erroné du graphique.

La variable de calcul du nombre de briques est réinitialisée et la boucle principale démarre. Contrairement à la boucle précédente, la boucle principale est également responsable du remplissage des tableaux de tampons de calcul et de la réinitialisation du compteur de briques.

A la fin de la fonction les tampons graphiques sont remplis.

//+------------------------------------------------------------------+
//| Func Draw Renko                                                  |
//+------------------------------------------------------------------+
void func_draw_renko(double &price[],   // prices array
                     double &date[],    // date array
                     int number_filter, // bricks number for reversal
                     bool draw_shadow,  // draw shadow
                     char type_doorstep,// step type
                     double doorstep)   // step
  {
//--- arrays reset
//--- drawing buffer arrays
   ZeroMemory(RENKO_close);
   ZeroMemory(RENKO_color);
   ZeroMemory(RENKO_high);
   ZeroMemory(RENKO_low);
   ZeroMemory(RENKO_open);
//--- additional variables
   int doorstep_now; // current step
   int point_go;     // passed points
//--- additional variables for bricks number calculating
   a=0;
   double up_price_calc=price[0];
   double down_price_calc=price[0];
   char type_box_calc=0;

   for(int z=0; z<bars; z++) //---> bricks calculating loop
     {
      //--- calculate step according to the current price
      doorstep_now=func_calc_dorstep(price[z],type_doorstep,doorstep);
      //--- if price rises
      if((price[z]-up_price_calc)/_Point>=doorstep_now)
        {
         //--- calculate points passed
         point_go=int((price[z]-up_price_calc)/_Point);
         //--- prices was rising or unknown price behavour
         if(type_box_calc==1 || type_box_calc==0)
           {
            for(int y=point_go; y>=doorstep_now; y-=doorstep_now)
              {
               //--- add the next brick 
               a++;
               //--- add value of the next brick low price
               down_price_calc=up_price_calc;
               //--- add value of the next brick up price
               up_price_calc=down_price_calc+(doorstep_now*_Point);
               //--- set the brick type (up)
               type_box_calc=1;
              }
           }
         //--- price went down
         if(type_box_calc==-1)
           {
            if((point_go/doorstep_now)>=number_filter)
              {
               for(int y=point_go; y>=doorstep_now; y-=doorstep_now)
                 {
                  //--- add the next brick
                  a++;
                  //--- set the next brick down price
                  down_price_calc=up_price_calc;
                  //--- set the next brick up price
                  up_price_calc=down_price_calc+(doorstep_now*_Point);
                  //--- set the brick type (up)
                  type_box_calc=1;
                 }
              }
           }
        }
      //--- if the price moves downwards
      if((down_price_calc-price[z])/_Point>=doorstep_now)
        {
         //--- calculate the points passed
         point_go=int((down_price_calc-price[z])/_Point);
         //--- if the price went downwards or the direction is unknown
         if(type_box_calc==-1 || type_box_calc==0)
           {
            for(int y=point_go; y>=doorstep_now; y-=doorstep_now)
              {
               //--- add the next brick
               a++;
               //--- set the next brick low price value
               up_price_calc=down_price_calc;
               //--- set the next brick up price value
               down_price_calc=up_price_calc-(doorstep_now*_Point);
               //--- set the britck type (up)
               type_box_calc=-1;
              }
           }
         //--- the price moved upwards
         if(type_box_calc==1)
           {
            if((point_go/doorstep_now)>=number_filter)
              {
               for(int y=point_go; y>=doorstep_now; y-=doorstep_now)
                 {
                  //--- add the next brick
                  a++;
                  //--- set the next brick down price value
                  up_price_calc=down_price_calc;
                  //--- set the next brick up price value
                  down_price_calc=up_price_calc-(doorstep_now*_Point);
                  //--- set the brick type (up)
                  type_box_calc=-1;
                 }
              }
           }
        }
     } //---< bricks calculate loop
//--- calculate the number of display bars
   int b=Bars(_Symbol,PERIOD_CURRENT);
//--- resize arrays
   ArrayResize(up_price,b);
   ArrayResize(down_price,b);
   ArrayResize(type_box,b);
   ArrayResize(time_box,b);
   ArrayResize(shadow_up,b);
   ArrayResize(shadow_down,b);
   ArrayResize(number_id,b);
//--- resize calculation buffers array
   ZeroMemory(up_price);
   ZeroMemory(down_price);
   ZeroMemory(type_box);
   ZeroMemory(time_box);
   ZeroMemory(shadow_up);
   ZeroMemory(shadow_down);
   ZeroMemory(number_id);
//--- fill arrays with the initial values
   up_price[0]=price[0];
   down_price[0]=price[0];
   type_box[0]=0;
//--- calculate odd bricks number
   int l=a-b;
   int turn_cycle=l/(b-1);
   int turn_rest=(int)MathMod(l,(b-1))+2;
   int turn_var=0;
//--- message of partially displayed bricks
   if(a>b)Alert("More bricks than can be placed on the chart, the step is small");

   a=0; //--- reset bricks claculating variable
   for(int z=0; z<bars; z++) //---> Main loop
     {
      //--- calculate the step according to the price
      doorstep_now=func_calc_dorstep(price[z],type_doorstep,doorstep);
      //---if the price moves upwards
      if((price[z]-up_price[a])/_Point>=doorstep_now)
        {
         //--- calculate the points passed
 point_go=int((price[z]-up_price[a])/_Point);
         //--- price moved upwards or its behavour is unknown
         if(type_box[a]==1 || type_box[a]==0)
           {
            for(int y=point_go; y>=doorstep_now; y-=doorstep_now)
              {
               a++; //--- add the next brick
               if((a==b && turn_var<turn_cycle) || (turn_var==turn_cycle && turn_rest==a))
                 {
                  up_price[0]=up_price[a-1];
                  a=1;        // bricks calculator reset
                  turn_var++; // calculator of loops reset
                 }
               //--- the next brick low price value
               down_price[a]=up_price[a-1];
               //--- set the brick up price 
               up_price[a]=down_price[a]+(doorstep_now*_Point);

               //--- set the up shadow value
               if(shadow_print==true) shadow_up[a]=price[z]; //to the upper price level
               else shadow_up[a]=up_price[a];                // to the up price level

               //--- set the low price value(to the brick price level)
               shadow_down[a]=down_price[a];
               //--- value of the brick closing time
               time_box[a]=(datetime)Date[z];
               //--- set the brick type (up)
               type_box[a]=1;
               //--- set the index
               number_id[a]=z;
              }
           }
         //--- the price moved downwards
         if(type_box[a]==-1)
           {
            if((point_go/doorstep_now)>=number_filter)
              {
               for(int y=point_go; y>=doorstep_now; y-=doorstep_now)
                 {
                  a++; //--- add the next brick

                  if((a==b && turn_var<turn_cycle) || (turn_var==turn_cycle && turn_rest==a))
                    {
                     up_price[0]=up_price[a-1];
                     a=1;        // bricks counter reset
                     turn_var++; // loops reset cycle
                    }
                  //--- set the next brick low price value
                  down_price[a]=up_price[a-1];
                  //--- set the next brick up price
                  up_price[a]=down_price[a]+(doorstep_now*_Point);

                  //--- set the up shadow value
                  if(shadow_print==true) shadow_up[a]=price[z]; // at the up price level
                  else shadow_up[a]=up_price[a];                // the brick up price level

                  //--- set of the down price value (the brick price level)
                  shadow_down[a]=down_price[a];
                  //--- set the close time
                  time_box[a]=(datetime)Date[z];
                  //--- set the up brick
                  type_box[a]=1;
                  //--- set index
                  number_id[a]=z;
                 }
              }
           }
        }

      //--- if price moves upwards
      if((down_price[a]-price[z])/_Point>=doorstep_now)
        {
         //--- calculate the points passed
         point_go=int((down_price[a]-price[z])/_Point);
         //--- price moved downwards or the direction is unknown
         if(type_box[a]==-1 || type_box[a]==0)
           {
            for(int y=point_go; y>=doorstep_now; y-=doorstep_now)
              {
               a++; //--- add the next brick
               if((a==b && turn_var<turn_cycle) || (turn_var==turn_cycle && turn_rest==a))
                 {
                  down_price[0]=down_price[a-1];
                  a=1;        // set the bricks counter to zero
                  turn_var++; // reset loop counter
                 }
               //--- set the next brick down price
               up_price[a]=down_price[a-1];
               //--- set the next brick up price
               down_price[a]=up_price[a]-(doorstep_now*_Point);

               //--- set the down shadow value 
               if(shadow_print==true) shadow_down[a]=price[z]; //--- the last lowest price level
               else shadow_down[a]=down_price[a];              //--- low price level

               //--- set the up price value
               shadow_up[a]=up_price[a];
               //--- set the brick close time
               time_box[a]=set the down shadow value];
               //--- set the brick type (down)
               type_box[a]=-1;
               //--- set index
               number_id[a]=z;
              }
           }
         //--- price moved upwards
         if(type_box[a]==1)
           {
            if((point_go/doorstep_now)>=number_filter)
              {
               for(int y=point_go; y>=doorstep_now; y-=doorstep_now)
                 {
                  a++; //--- add the next brick
                  if((a==b && turn_var<turn_cycle) || (turn_var==turn_cycle && turn_rest==a))
                    {
                     down_price[0]=down_price[a-1];
                     a=1;        // reset bricks counter
                     turn_var++; // reset loop counter
                    }

                  up_price[a]=down_price[a-1]; //--- set the next brick down price
                  down_price[a]=up_price[a]-(doorstep_now*_Point); //--- set the up price value

                  //--- set the down shadow value 
                  if(shadow_print==true) shadow_down[a]=price[z]; // at the lowest price level
                  else shadow_down[a]=down_price[a];              // at the down price level

                  //--- set the up price level
                  shadow_up[a]=up_price[a];
                  //--- set the brick close time
                  time_box[a]=(datetime)Date[z];
                  //--- set the brick type (down)
                  type_box[a]=-1;
                  //--- index set
                  number_id[a]=z;
                 }
              }
           }
        }
     } //---< Main loop

//--- fill the draw buffer
   int y=a;
   for(int z=0; z<a; z++)
     {
      if(type_box[y]==1)RENKO_color[z]=0;
      else RENKO_color[z]=1;
      RENKO_open[z]=down_price[y];
      RENKO_close[z]=up_price[y];
      RENKO_high[z]=shadow_up[y];
      RENKO_low[z]=shadow_down[y];
      y--;
     }
  }


3.7. Fonction de création des objets graphiques « ligne de tendance » et « rectangle »

La fonction de création d'objet graphique « ligne de tendance » ou « func_create_trend_line » et la fonction de création d'objet graphique « rectangle » ou « func_create_square_or_rectangle » sont basées sur les données mentionnées dans la référence à OBJ_RECTANGLE et OBJ_TREND. Ils sont utilisés pour créer des objets graphiques dans la carte «Renko» et pour construire des «ZigZag» sur la carte principale.

//+------------------------------------------------------------------+
//| Func Create Trend Line                                           |
//+------------------------------------------------------------------+
void func_create_trend_line(string name,
                            double price1,
                            double price2,
                            datetime time1,
                            datetime time2,
                            int width,
                            color color_line)
  {
   ObjectCreate(0,name,OBJ_TREND,0,time1,price1,time2,price2);
//--- set the line color
   ObjectSetInteger(0,name,OBJPROP_COLOR,color_line);
//--- set the line display style
   ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
//--- set the width of the line
   ObjectSetInteger(0,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or in the (true) background
   ObjectSetInteger(0,name,OBJPROP_BACK,false);
//--- enable (true) or disable (false) the mode of the left line display
   ObjectSetInteger(0,name,OBJPROP_RAY_LEFT,false);
//--- enable (true) or disable (false) the right line display
   ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,false);
  }
//+------------------------------------------------------------------+
//| Func Create Square or Rectangle                                  |
//+------------------------------------------------------------------+
void func_create_square_or_rectangle(string name,
                                     double price1,
                                     double price2,
                                     datetime time1,
                                     datetime time2,
                                     int width,
                                     color color_square,
                                     bool fill)
  {
//--- create rectangle according to the setpoints 
   ObjectCreate(0,name,OBJ_RECTANGLE,0,time1,price1,time2,price2);
//--- set the rectangle color
   ObjectSetInteger(0,name,OBJPROP_COLOR,color_square);
//--- set style of rectangle color
   ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
//--- set lines width
   ObjectSetInteger(0,name,OBJPROP_WIDTH,width);
//--- activate (true) or disactivate (false) mode of rectangle colouring
   ObjectSetInteger(0,name,OBJPROP_FILL,fill);
//--- display in the foreground (false) or in the background (true)
   ObjectSetInteger(0,name,OBJPROP_BACK,false);
  }


3.8. La construction «Renko» sur la carte principale

En raison de l'utilisation des tableaux de tampons communs de calcul, la fonction pour le graphique Renko ou le «func_draw_renko_main_chart» est plutôt compacte.

Les paramètres d'entrée comprennent : la brique montante et descendante avec leurs cadres, deux types de largeur de cadres (le premier est utilisé pour la brique, le second - pour son cadre), trois options d'affichage (des «briques», leurs couleurs et cadres) ).

Tout d'abord, des variables avec des noms d'objets sont déclarées, puis la boucle avec le nom généré de chaque objet est ouverte et selon le type de brique précédent la fonction des objets graphiques «ligne de tendance» et «rectangle» est lancée. Les paramètres sont extraits des tableaux de tampons de calcul.

//+------------------------------------------------------------------+
//| Func Draw Renko Main Chart                                       |
//+------------------------------------------------------------------+
void func_draw_renko_main_chart(color color_square_up,
                                color color_square_down,
                                color color_frame_up,
                                color color_frame_down,
                                int width_square,
                                int width_frame,
                                bool square,
                                bool fill,
                                bool frame)
  {
   string name_square;
   string name_frame;

   for(int z=2; z<=a; z++)
     {
      name_square=IntegerToString(magic_numb)+"_Square_"+IntegerToString(z);
      name_frame=IntegerToString(magic_numb)+"_Frame_"+IntegerToString(z);
      if(type_box[z]==1)
        {
         if(square==true)func_create_square_or_rectangle(name_square,up_price[z],down_price[z],time_box[z-1],time_box[z],width_square,color_square_up,fill);
         if(frame==true)func_create_square_or_rectangle(name_frame,up_price[z],down_price[z],time_box[z-1],time_box[z],width_frame,color_frame_up,false);
        }
      if(type_box[z]==-1)
        {
         if(square==true)func_create_square_or_rectangle(name_square,up_price[z],down_price[z],time_box[z-1],time_box[z],width_square,color_square_down,fill);
         if(frame==true)func_create_square_or_rectangle(name_frame,up_price[z],down_price[z],time_box[z-1],time_box[z],width_frame,color_frame_down,false);
        }
     }
  }

3.9. La construction «ZigZag» sur la carte principale

Le prochain type de complément à l'indicateur est la fonction graphique «ZigZag» ou «func_draw_zig_zag».

Les paramètres d'entrée : le mode de tracé (sur les prix maximum ou minimum, ou sur les points du graphique), la largeur du trait, la couleur du trait vers le haut ou vers le bas.

Le changement de paramètre «zig_zag_shadow» peut être vu dans l'image 4. Si «vrai» est activé, l'indicateur trace les lignes «ZigZag» sur les points d'ombre (prix minimum et maximum), dans l'option «faux», les lignes «ZigZag» sont dessinées sur les points maximum et minimum de «Renko» .


Fig.4. L'impact du paramètre «zig_zag_shadow» sur l'EURUSD, H1, 10 points.

Fig.4. L'impact du paramètre «zig_zag_shadow» sur l'EURUSD, H1, 10 points. 

Pour construire l'objet «ligne de tendance», deux points (début et fin) sont nécessaires, saisissez deux variables pour le paramètre prix et deux variables pour le paramètre date. Si les instructions conditionnelles définissent le premier point en fonction du type de brique initial.

La boucle qui construit tous les objets se lance. Comme vous pouvez le voir, la boucle démarre à partir de la deuxième analyse de brique, car le premier point est déjà défini. Ensuite, l'instruction conditionnelle si vérifie le type de brique (le comportement des prix). La variable du nom de l'objet est remplie et, en fonction du changement de mouvement, la boucle se divise. À son tour, selon la méthode de dessin, il est divisé en deux variantes.

S'il est affiché sur les prix minimum et maximum, les tableaux de données Price_high[] et Price_low[] recherchent les points minimum et maximum proches. La recherche est restreinte aux barres proches.

S'il est gradué sur les points du graphique, les données sont affectées à partir des tableaux de tampons.

La fonction de construction « ligne de tendance » est appelée. La fonction termine l'analyse et la cartographie du «ZigZag».

//+------------------------------------------------------------------+
//| Func Draw Zig Zag                                                |
//+------------------------------------------------------------------+
void func_draw_zig_zag(bool price_shadow,
                       int line_width,
                       color line_color_up,
                       color line_color_down)
  {
   double price_1=0;
   double price_2=0;
   datetime date_1=0;
   datetime date_2=0;

   if(type_box[1]==1)price_1=down_price[1];
   if(type_box[1]==-1)price_1=up_price[1];
   date_1=time_box[1];
   int id=0; //  Low & High array storing variable
   int n=0;  // variable for name forming

   string name_line; //--- variable responsible for the "trend line" name

   for(int z=2; z<=a; z++)
     {
      if(type_box[z]!=type_box[z-1])
        {
         n++;
         name_line=IntegerToString(magic_numb)+"_Line_"+IntegerToString(n);
         if(type_box[z]==1)
           {
            if(price_shadow==true)
              {
               id=number_id[z-1];
               if((id-1)>0 && Price_low[id-1]<Price_low[id])id--;
               if(Price_low[id+1]<Price_low[id])id++;
               price_2=Price_low[id];
               date_2=(datetime)Date[id];
              }
            else
              {
               price_2=down_price[z-1];
               date_2=time_box[z-1];
              }
            func_create_trend_line(name_line,price_1,price_2,date_1,date_2,line_width,line_color_down);
            price_1=price_2;
            date_1=date_2;
           }
         if(type_box[z]==-1)
           {
            if(price_shadow==true)
              {
               id=number_id[z-1];
               if((id-1)>0 && Price_high[id-1]>Price_high[id])id--;
               if(Price_high[id+1]>Price_high[id])id++;
               price_2=Price_high[id];
               date_2=(datetime)Date[id];
              }
            else
              {
               price_2=up_price[z-1];
               date_2=time_box[z-1];
              }
            func_create_trend_line(name_line,price_1,price_2,date_1,date_2,line_width,line_color_up);
            price_1=price_2;
            date_1=date_2;
           }
        }
     }
  }

3.10. Supprimer des objets graphiques créés précédemment

Le nombre magique est utilisé pour déterminer les objets de l'indicateur. Il simplifie le lancement de plusieurs indicateurs sur un même graphique et le processus de suppression d'objets.

La fonction suivante est la fonction de suppression d'objets ou les «func_delete_objects». Le nom (défini en fonction des objets : courbe de tendance ou rectangle) et le nombre d'objets sont deux paramètres d'entrée. La fonction choisit les objets et supprime les objets avec le nom déjà attribué.

//+------------------------------------------------------------------+
//| Func Delete Objects                                              |
//+------------------------------------------------------------------+
void func_delete_objects(string name,
                         int number)
  {
   string name_del;
   for(int x=0; x<=number; x++)
     {
      name_del=name+IntegerToString(x);
      ObjectDelete(0,name_del);
     }
  }

La fonction de consolidation de toutes les fonctions de suppression de tous les objets indicateurs a été créée.

//+------------------------------------------------------------------+
//| Func All Delete                                                  |
//+------------------------------------------------------------------+
void func_all_delete()
  {
//--- the graphical objects calculating
   obj=ObjectsTotal(0,-1,-1);
//--- all indicator graphical objects deleting
   func_delete_objects(IntegerToString(magic_numb)+"_Line_",obj);
   func_delete_objects(IntegerToString(magic_numb)+"_Square_",obj);
   func_delete_objects(IntegerToString(magic_numb)+"_Frame_",obj);
//--- the chart redrawing
   ChartRedraw(0);
  }


3.11. Fonction de création de niveaux

La fonction «func_create_levels» pour la création de niveau simplifie l'affichage du graphique dans la fenêtre d'indicateur. Il n'a que deux paramètres d'entrée : le nombre de niveaux créés et leur couleur.

Dans le corps de la fonction, IndicatorSetInteger est utilisé pour définir le nombre de niveaux affichés, puis le prix et la couleur sont définis pour chaque niveau.

//+------------------------------------------------------------------+
//| Func Create Levels                                               |
//+------------------------------------------------------------------+
void func_create_levels(int level_number,
                        color level_color)
  {
//--- set the number of levels in the indicator window
   IndicatorSetInteger(INDICATOR_LEVELS,level_number);
 which brick is taken to draw levels
   int k=0;
   if(a>level_number)k=a-level_number;
//--- set levels prices
   for(int z=0;(z<=level_number && k<=a); z++,k++)
     {
      IndicatorSetDouble(INDICATOR_LEVELVALUE,z,up_price[k]);
      IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,level_color);
     }
  }

3.12. La fonction de consolidation

La fonction «func_consolidation» a été créée pour consolider toutes les fonctions.

La fonction appelle toutes les fonctions exécutées.

//+------------------------------------------------------------------+
//| Func Consolidation                                               |
//+------------------------------------------------------------------+
void func_concolidation()
  {
//--- deleting all the graphical objects of the indicator
   func_all_delete();
//--- the current date
   date_stop=TimeCurrent();
//--- the initial date changing due to the restricted buffer size
   if((bars=Bars(_Symbol,time_frame,date_start,date_stop))>ArraySize(Price))
     {
      date_start=func_calc_date_start(date_start,date_stop);
      Alert("The initial date was changed due to the lack of the chart size");
      date_change=true;
      //--- calculation of bars on the taken timeframe
      bars=Bars(_Symbol,time_frame,date_start,date_stop);
     }
//---
   bool result_copy_price=func_copy_price(Price,time_frame,date_start,date_stop,type_price);
   bool result_copy_date=func_copy_date(Date,time_frame,date_start,date_stop);
//--- change the date parameter
   if(result_copy_price=true && result_copy_date==true)date_change=false;
//---
   if(zig_zag_shadow==true)
     {
      func_copy_price(Price_high,time_frame,date_start,date_stop,2);
      func_copy_price(Price_low,time_frame,date_start,date_stop,3);
     }
//---
   func_draw_renko(Price,Date,filter_number,shadow_print,type_step,step);
   if(zig_zag==true)func_draw_zig_zag(zig_zag_shadow,zig_zag_width,zig_zag_color_up,zig_zag_color_down);
//---
   func_draw_renko_main_chart(square_color_up,square_color_down,frame_color_up,frame_color_down,square_width,frame_width,square_draw,square_fill,frame_draw);
   func_create_levels(levels_number,levels_color);
//--- redraw the chart
   ChartRedraw(0);
  }

3.13. Fonctions OnCalculate() et OnChartEvent()

Avant de passer à la fonction OnCalculate(), examinons la fonction «func_new_bar» qui analyse la nouvelle barre.

C'est la fonction simplifiée décrite dans IsNewBar.

//+------------------------------------------------------------------+
//| Func New Bar                                                     |
//+------------------------------------------------------------------+
bool func_new_bar(ENUM_TIMEFRAMES period_time)
  {
//---
   static datetime old_times; // array for storing old values
   bool res=false;            // analysis result variable 
   datetime new_time[1];      // new bar time
//---
   int copied=CopyTime(_Symbol,period_time,0,1,new_time); // copy the time of the new bar into the new_time box 
//---
   if(copied>0) // все ок. data have been copied
     {
      if(old_times!=new_time[0])    // if the bar's old time is not equal to new one
        {
         if(old_times!=0) res=true; // if it is not the first launch, true = new bar
         old_times=new_time[0];     // store the bar's time
        }
     }
//---
   return(res);
  }

La fonction OnCalculate() lance la consolidation de toutes les fonctions si une nouvelle barre est créée lors de la mise à jour du graphe. 

//+------------------------------------------------------------------+
//| 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_concolidation();
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

La fonction OnChartEvent() supprime tous les objets graphiques en appuyant sur « C », un appui sur « R » lance le redécoupage du graphique (la fonction consolidation).

//+------------------------------------------------------------------+
//| OnChartEvent                                                     |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         // event ID 
                  const long& lparam,   // long type event parameter
                  const double& dparam, // double type event parameter
                  const string& sparam) // string type event parameter
  {
//--- Keyboard button pressing event
   if(id==CHARTEVENT_KEYDOWN)
     {
      if(lparam==82) //--- "R" key has been pressed
        {
         //--- call of the consolidation function
         func_concolidation();
        }
      if(lparam==67) //--- "C" key has been pressed
        {
         //--- deletion of all objects of the indicator
         func_all_delete();
        }
     }
  }


3.14. Fonction OnDeinit()

Et, enfin, la fonction OnDeinit(). Cette fonction lance la fonction de suppression de tous les objets graphiques de l'indicateur.

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+ 
void OnDeinit(const int reason)
  {
//--- delete all graphical objects of the indicator
   func_all_delete();
  }


4. Utilisation du graphique Renko dans la pratique

Le graphique Renko est construit selon la stratégie des mouvements de prix.

Commençons par la stratégie la plus populaire : vendre lorsque la brique montante commence à descendre et acheter dans le cas contraire.

Ceci est montré dans la Fig. 5:


Fig.5. Graphique Renko standard (EURUSD H4, 20 points)

Fig.5. Graphique Renko standard (EURUSD H4, 20 points)

La Fig. 5 montre six points (A,B,C,D,E,F) de l'entrée du marché.

Au point «A», la brique vers le haut se transforme en brique vers le bas.

La brique inversée comme dans les points (B,C,D) est créée en un seul mouvement. Cependant, sur le point «E», deux briques ont été créées d'un seul mouvement quant aux ombres du bas sont créées au même niveau.

Dans ce cas, l'entrée est possible entre les points «E» et «F». Ce n'est pas une entrée réussie, car le prix évolue dans une direction opposée, la situation analogique est sur le point «F»: où un mouvement crée également deux briques. Les ombres du haut sont au même niveau. Bien qu'avec un mouvement fort, le prix ne change pas de direction.

L'implication est que l'entrée la plus favorable sur le marché est lorsqu'une brique d'inversion (regardez les ombres) est créée en un seul mouvement. Si nous créons deux briques à la fois, cette entrée peut être dangereuse.

Le «ZigZag» gradué sur ce graphique peut être utilisé pour l'analyse graphique. La Fig. 6 montre quelques exemples : les lignes «support» et «résistance», le réglage du modèle «tête et épaules».


Fig.6. L'analyse graphique (GBPUSD H4, 20 points)

Fig.6. L'analyse graphique (GBPUSD H4, 20 points)

L'analyse graphique « Canal équidistant » est illustrée à la Fig. 7.

L'indicateur est réglé pour analyser la période et la graduation est affichée sur la période de quatre heures.

De tels paramètres permettent aux signaux personnalisés de suivre simultanément plusieurs périodes, ce qui signifie qu'un indicateur peut être utilisé sur une période et l'autre sur la seconde.


Fig.7. Analyse du «Canal équidistant» USDCHF, H4, réglages sur H1, 20 points.

Fig.7. Analyse du «Canal équidistant» USDCHF, H4, réglages sur H1, 20 points.

La figure 8 représente un autre exemple de différentes périodes sur un graphique.

Le graphique temporel montre les inversions de fermeture possibles, le graphique à quatre heures supprime les signaux inutiles, le graphique journalier approuve la longue durée des mouvements de tendances.


Fig.8. L'indicateur Renko sur GBPUSD, H1, H4 et D1

Fig.8. L'indicateur Renko sur GBPUSD, H1, H4 et D1

Un autre exemple d'indicateur est dans la Fig. 9. La règle dit : construisez la ligne ascendante entre les briques rouges les plus proches avec au moins une brique bleue entre elles et vendez une fois la brique créée sous la ligne.

Et l'inverse : construisez la ligne descendante entre les briques bleues les plus proches avec au moins une brique rouge entre elles et vendez après la création de la brique au-dessus de la ligne.

Les couleurs sont mentionnées selon la Fig. 9. Fig. 9. Les flèches bleues et rouges marquent les emplacements de dessin et les grandes flèches marquent les signaux de vente et d'achat.

Fig.9. Un exemple de GBPUSD, H4, indicateur de 25 points

Fig.9. Un exemple de GBPUSD, H4, indicateur 25 points

Conclusion

Le graphique Renko est intéressant pour les débutants et les traders professionnels. De nombreuses années ont passé, cependant, il est toujours utilisé sur les marchés.

Dans cet article, je voulais attirer votre attention sur le graphique et améliorer l'analyse du graphique Renko. J'ai essayé de montrer la méthode détaillée de la construction du graphique Renko.

Je serai heureux d'envisager de nouvelles idées et améliorations pour l'indicateur et, peut-être, de les mettre en œuvre à l'avenir. Il existe plusieurs façons de mettre en œuvre un indicateur, vous pouvez également trouver vos méthodes de mise en œuvre.

Merci pour votre intérêt! Je vous souhaite un trading réussi et une nouvelle mise en œuvre de la stratégie de trade.


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

Fichiers joints |
abcr.mq5 (77.52 KB)
Travailler avec le modem GSM d'un Expert Advisors de MQL5 Travailler avec le modem GSM d'un Expert Advisors de MQL5
Il existe actuellement de nombreux moyens pour un bon suivi à distance d'un compte de trading : terminaux mobiles, notifications push, fonctionnement avec ICQ. Mais tout cela nécessite une connexion Internet. Cet article décrit le processus de création d'un Expert Advisor qui vous permettra de rester en contact avec votre terminal de trading même lorsque l'Internet mobile n'est pas disponible, par le biais d'appels et de SMS.
Livre de recettes MQL5 - Expert Advisor multi-devises et utilisation des commandes en attente dans MQL5 Livre de recettes MQL5 - Expert Advisor multi-devises et utilisation des commandes en attente dans MQL5
Cette fois, nous allons créer un Expert Advisor multi-devises avec un algorithme de trading basé sur le travail avec les ordres en attente Buy Stop et Sell Stop. Cet article aborde les questions suivantes : négocier dans une plage de temps spécifiée, passer/modifier/supprimer des ordres en attente, vérifier si la dernière position a été fermée au Take profit ou au Stop Loss et contrôler l'historique des transactions pour chaque symbole.
Contrats à terme continus dans MetaTrader 5 Contrats à terme continus dans MetaTrader 5
La courte durée de vie des contrats à terme complique leur analyse technique. Il est difficile d'analyser techniquement des graphiques courts. Par exemple, le nombre de barres sur le graphique journalier du futur indice boursier ukrainien UX-9.13 est supérieur à 100. Par conséquent, le trader crée des contrats à terme synthétiques longs. Cet article explique comment assembler des contrats à terme avec des dates différentes dans le terminal MetaTrader 5.
Le MQL5 Cookbook : Développement d'un indicateur multi-symboles pour analyser la divergence des prix Le MQL5 Cookbook : Développement d'un indicateur multi-symboles pour analyser la divergence des prix
Dans cet article, nous examinerons le développement d'un indicateur multi-symboles pour analyser la divergence des prix dans une période de temps spécifiée. Les sujets de base ont déjà été abordés dans l'article précédent sur la programmation d'indicateurs multi-devises «livre de recettes MQL5k: Développement d'un indicateur de volatilité multi-symboles dans MQL5». Cette fois, nous nous attarderons donc uniquement sur les nouvelles fonctionnalités et fonctions qui ont été radicalement modifiées. Si vous débutez dans la programmation d'indicateurs multi-devises, je vous recommande de lire dans un premier temps l'article précédent.