English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Indicador para gráfico Renko

Indicador para gráfico Renko

MetaTrader 5Exemplos | 7 julho 2014, 12:22
24 445 14
Dmitriy Zabudskiy
Dmitriy Zabudskiy

Introdução

Os artigos Indicador para o gráfico de Ponto e Figura e Indicador para representação do gráfico Kagi descrevem o início dos indicadores gráficos Ponto e Figura e "Kagi". Vamos estudar uma das formas de programação para criar um gráfico Renko.

O nome "Renko" é derivado da palavra japonesa "renga", ou seja, tijolo. O gráfico Renko é construído a partir de uma série de tijolos determinados pelas flutuações no preço. Quando um preço aumenta, um tijolo é colocado acima no gráfico e com os preços em queda, um tijolo é adicionado abaixo. "Renko" significa um "ritmo lento" em japonês. O gráfico Renko nasceu no Japão, provavelmente em algum lugar no século 19. Os EUA e a Europa ouviram pela primeira vez sobre o assunto depois que Steeve Nison o publicou em 1994 no seu livro, Beyond Candlesticks: New Japanese Charting Techniques Revealed.

O gráfico Renko como mencionado acima ignora a linha do tempo e se preocupa apenas com o movimento dos preços. Ao contrário do gráfico ponto e figura, o Renko coloca cada "tijolo" em nova coluna (em novo plano vertical), de resto eles têm um método de criação comum: tamanho de um "tijolo" ("ponto", "figura ") é fixo, a análise dos preços e as figuras de revestimento são feitas de uma maneira semelhante.

Então, o gráfico Renko é um conjunto de barras verticais ("tijolos"). Tijolos brancos (ocos) são usados ​​com a direção da tendência para cima, enquanto tijolos pretos (cheios) são usados ​​na tendência para baixo. A construção é regulada com o comportamento dos preços. O preço tomado do período atual é comparado com a mínima e máxima do tijolo anterior (branco ou preto). Se os ativos fecham acima de seu preço de abertura, um tijolo oco (branco) é desenhado com a parte inferior do corpo representando o preço de abertura e a parte superior do corpo representando o preço de fechamento. Se os ativos fecham abaixo de seu preço de abertura, um tijolo oco (branco) é desenhado com a parte superior do corpo representando o preço de abertura e a parte inferior do corpo representando o preço de fechamento.

O primeiro tijolo do gráfico é desenhado dependendo do comportamento do preço, o preço de abertura da barra é levado para a máxima e a mínima do tijolo anterior.

Um exemplo padrão de gráfico Renko, Fig. 1:

Fig. 1. Um exemplo de gráfico Renko padrão

Fig. 1. Um exemplo de gráfico Renko padrão

1. Exemplo gráfico

Um gráfico Renko padrão é elaborado com base no preço de fechamento. Primeiro, selecione o timeframe e o tamanho da caixa.

Neste exemplo, o EURUSD (timeframe H4) é usado com um tamanho da caixa de 30 pontos. O resultado do gráfico Renko de 03.01.2014 a 31.01.2014 (cerca de um mês) é mostrado na fig. 2, à esquerda o gráfico normal com timeframe (na imagem pode ser vista a extensão horizontal dos tijolos renko), à direita é visto o resultado da criação do gráfico Renko:


Fig.2. O resultado do gráfico Renko no EURUSD (H4, a caixa é de 30 pontos) 

Fig.2. O resultado do gráfico Renko no EURUSD (H4, a caixa é de 30 pontos)

Vamos dar uma olhada no princípio da criação do gráfico. Na fig. 2, linhas horizontais vermelhas mostram o tamanho de cada tijolo de acordo com mudanças no preço (30 pontos), linhas de cor azul indicam as datas mais interessantes.

Como você pode ver no gráfico, no final de 03.01.2014, um candle fecha abaixo de 1.3591 com intervalos previamente definidos de preços (linhas horizontais vermelhas) a 1.3589 (preço assinalado), criando um tijolo de baixa no gráfico.

Depois que o preço anda lateralmente (não fecha abaixo ou acima de 1.3561), ele é aberto às 20:00 do dia 10.01.2014 (o candle criado fecha às 16:00) e fecha (acima de 1.3651) a 1.3663 (preço assinalado). Então o preço volta a andar lateralmente até às 20:00 do dia 14.01.2014 (o candle criado fecha às 16:00), onde supera a faixa de preço, criando um novo tijolo e fechando em 1.3684.

Então você testemunha um decremento (downtick) onde o preço rompe para baixo quatro vezes no gráfico. Às 12:00 do dia 23.01.2014 (o candle criado fecha às 08:00), há uma quebra para cima de duas variações de preços que por sua vez abrem dois tijolos, fechando no preço 1.3639. O primeiro tijolo é claramente visível, o segundo é puxado numa linha vertical de comprimento (devido à abertura simultânea com o primeiro tijolo). A construção continua com os mesmos princípios.


2. Princípio do gráfico Renko

Ao desenvolver este indicador todas as funções foram implementadas de forma tão independente quanto possível. Um dos objetivos principais foi maximizar o potencial do indicador para conduzir facilmente a análise de mercado.

Os cálculos não são feitos dentro do timeframe escolhido no terminal do cliente, ou seja, o prazo é selecionado nas configurações e independentemente do timeframe em que o indicador foi lançado, ele irá mostrar os dados inseridos nos parâmetros. Isso pode ser conseguido através da cópia dos dados do período chamado dentro dos arrays de buffer separados, cálculos posteriores são feitos e o buffer de saída do indicador é preenchido.

O gráfico Renko padrão é construído de acordo com o Fechamento (Close) dos preços, no entanto os valores da Abertura (Open), Máxima (High)e Minima (Low) são usados ​​para melhorar a análise.

Os tijolos no gráfico Renko são semelhantes em tamanho, é útil conhecer os pontos mais dinâmicos do mercado impulsionados pelo comportamento dos preços fortes (em alguns tijolos). Para este efeito, há uma indicação (desativada) representando uma pequena sombra vertical (como no Candle Japonês) de um tijolo que aumenta ou diminui no último nível do tijolo do timeframe da barra escolhida.

A possibilidade de construir um ZigZag no gráfico principal expande a análise gráfica.

Fig. 3 - Representa o indicador com funcionalidade completa:

Figura 3 O indicador para o gráfico EURUSD (Diário, o passo é de 25 pontos)

Figura 3 O indicador para o gráfico EURUSD (Diário, o passo é de 25 pontos)


3. Código e algoritmo do indicador

O código de indicador é bem grande, uma vez que é construído com 900 linhas. Como mencionado anteriormente, muitas funções separadas podem complicar a compreensão do algoritmo. Algumas das funções do artigo anterior serão usadas como base. Em caso de mal-entendido quanto a alguns aspectos, você pode verificar o artigo Indicador para representação de gráfico Kagi ou me enviar um e-mail.

Cada função do código vai ser explicado no artigo. As funções serão descritas no local.


3.1. Parâmetros de entrada do indicador:

O gráfico Renko é o intervalo de tijolos acima e abaixo de cores diferentes. Este tipo de construção requer apenas cinco buffers combinados com uma construção gráfica de "candles coloridos". Quatro buffers recolhem os dados necessários para o cálculo do indicador.

Veja os parâmetros de entrada (25), divididos em grupos.

  • step - o tamanho ou o passo do tijolo;
  • type_step - tipo de passo, em pontos ou em porcentagem (neste último o cálculo depende do preço atual);
  • magic_numb - um número mágico necessário para distinguir os objetos e para removê-los do gráfico;
  • levels_number - níveis (0 - Não níveis) para dividir tijolos na janela do indicador;
  • levels_color - cor dos níveis na janela do indicador;
  • time_frame - usado para definir o timeframe para a construção do gráfico;
  • time_redraw - tempo de atualização do gráfico;
  • first_date_start - data para começar a plotagem do gráfico;
  • type_price - tipos de preço para construção: Fechamento - O método padrão com base no fechamento do preço; Abertura - preço de abertura; Máxima - maior extremo do preço e Minima - menor extremo do preço;
  • shadow_print - Se você definir a opção como verdadeira (true), sombras representam a máxima ou mínima na abertura de vários tijolos;
  • filter_number - valor dos tijolos utilizado para reversão do gráfico (uma opção extra responsável pelo número de tijolos necessários para reverter o gráfico);
  • zig_zag - usada para desenhar ZigZags no gráfico principal (um desenho extra no gráfico principal que facilita uma análise ou usado para atualização do gráfico);
  • zig_zag_shadow - usada para desenhar ZigZags de acordo com as máxima e mínimas dos preços (usa as máximas e mínimas mais próximas dos preços para a construção dos pontos finais zigzags);
  • zig_zag_width - largura da linha ZigZag;
  • zig_zag_color_up - cor da linha ZigZag para cima;
  • zig_zag_color_down - cor da linha ZigZag para baixo;
  • square_draw - usada para desenhar os tijolos no gráfico principal (neste modo, você pode ver os movimentos dos preços com tijolos abertos);
  • square_color_up - cor de tijolo no gráfico principal para cima;
  • square_color_down - cor de tijolo no gráfico principal para baixo;
  • square_fill - preenchimento da cor no tijolo no gráfico principal;
  • square_width - largura da linha do tijolo no gráfico principal;
  • frame_draw - usado para desenhar os quadros de tijolos (representa as bordas dos tijolos, é uma opção extra raramente usada);
  • frame_width - largura da linha dos tijolos;
  • frame_color_up - cor das bordas superiores dos tijolos;
  • frame_color_down - cor das bordas inferiores dos tijolos;

Em seguida, o código declara os buffers: cinco buffers principais são usados ​​para o desenho gráfico, enquanto quatro são usados ​​para armazenamento do projeto e dados de cálculo. Price[] - buffer para armazenar a copia dos preços utilizados para a construção, Date[] - buffer para armazenar dados copiados e usado para desenhar no gráfico principal, Price_high[] e Price_low[] - buffers para armazenar os valores das máximas e mínimas aplicados nos desenhos ZigZags no gráfico principal.

Depois de calcular os arrays de buffers, as variáveis das funções auxiliares ​​são declaradas: func_draw_renko, func_draw_zig_zag, func_draw_renko_main_chart. Elas serão explicadas mais tarde.

//+------------------------------------------------------------------+
//|                                                         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. Inicializador do Indicator

Os Buffers do indicador são limitados pelos arrays dinâmicos unidimensionais, endereçando também as séries temporais, são definidos nos buffers INDICATOR_DATA e INDICATOR_COLOR_INDEX. Os endereçamentos dos arrays dinâmicos de intervalo (Price[] Data[], Price_high[], Price_low[]) são deixados sem alterações, uma vez que somente são usados ​​para armazenar dados.

Os valores que não são exibidos no gráfico são definidos. Então o nome é atribuído ao indicador, a precisão de exibição é definida e mostrado os valores numéricos vigentes na janela do indicador.

Depois disso o valor da variável date_start (data para iniciar cálculos) é atribuído. O valor de entrada não é usado, pois o gráfico pode ser demasiadamente pesado para o buffer do indicador. A data de início é corrigida e a customização é anunciada. A função da análise de data de início ou "func_calc_date_start" realiza as correções de tempo.

//+------------------------------------------------------------------+
//| 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. A análise do cálculo da função da data inicial

A função é pequena e constituída principalmente por um loop. São apenas dois parâmetros de entrada - inicializa a definição da data inicial e calcula o final da data (a data atual). A data inicial é alterada na função e apresentada como uma resposta.

O corpo da função começa a partir da medição do array de buffer recebedor (todos os buffers têm o mesmo tamanho que é igual ao número de barras do timeframe selecionado). Em seguida, uma série de barras é mensurada no timeframe selecionado.

Número de barras do timeframe escolhido e tamanho do array de buffer são comparados na condição de loop. Se você tem mais barras, ou seja, elas não podem ser colocadas todas no array de buffer, o timeframe é abreviado em 10 dias, significando que 10 dias são adicionados na análise da data inicial. Isto continua até que o array de buffer possa incluir todos os dados das barras. A função retorna a data calculada.

//+------------------------------------------------------------------+
//| 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. A função de cópia de dados

Em primeiro lugar, os dados são copiados com as funções de cópia de dados (func_copy_price e func_copy_date).

Vamos considerar a função de cópia do preço, func_copy_price, ela permite a cópia do array de Abertura, Fechamento, Máxima e Mínima do preço no período e timeframe definido. Em caso de uma cópia bem-sucedida a função retorna "verdadeira".

No início da chamada da função o valor falso é inicializado, então uma variável de desfecho dos dados copiados é inicializada e um valor negativo é atribuído. O price_interim[], um array comum para armazenar cópias de dados temporários e a variável bars_to_copy são declarados para evitar a economia dos dados copiados.

Além disso, a função redefine variáveis ​​anteriormente declaradas para armazenar os dados copiados, calcula o número de barras no timeframe de acordo com o preço escolhido (0-Fechamento, 1-Abertura, 2-Máxima e 3-Mínima) e uma declaração do operador switch atribui o valor dos dados previamente copiados nas variáveis de preços ​​bars_copied. Depois o número de dados a ser copiado é calculado. Se os dados foram copiados anteriormente, a última informação da barra copiada é excluída para evitar alterações no gráfico.

Uma cópia do switch dos dados de preços é necessário para o array de tempo price_interim[]. Após isso, o resultado da cópia é verificado e um switch preenche as cópias das variáveis ​​de dados.

//+------------------------------------------------------------------+
//| 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);
  }

 A função de cópia de dados ou "func_copy_date". O código de função é a semelhança da unidade acima mencionada, a diferença está no tipo dos dados copiados.

//+------------------------------------------------------------------+
//| 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. Cálculo dos tijolos

Verifica-se que partir dos parâmetros do indicador, um tamanho de tijolo pode ser definido tanto em pontos como em percentual sobre o preço vigente. Pontos é um valor fixo, mas como o cálculo percentual ocorre? Para esta finalidade, existe a função de cálculo dos tijolos chamada de "func_calc_dorstep".

Há três parâmetros de entrada: o preço vigente (para calcular o percentual sobre o preço, se o tamanho do tijolo for em percentual), o método de cálculo (pontos ou percentual) e o tamanho do passo (definida com um valor que pode ser em pontos ou percentual).

No início da função, a variável para a resposta é inicializada pelo tipo double e dependendo do método de cálculo escolhido pela declaração da condicional, if-else é atribuído em pontos. Então a variável resposta é convertida para o tipo int para manter o valor inteiro, mesmo que os cálculos resultem num valor não integral.

//+------------------------------------------------------------------+
//| 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. A função principal - ordenação do gráfico Renko

A principal função de ordenação do gráfico Renko - "func_draw_renko". Esta função é a responsável pelos buffers grafical (buffers de indicador) e preenchimento dos cálculos dos arrays de buffers. Cálculo de buffers para armazenar as informações de cada tijolo.

Os parâmetros de entrada da função são arrays de preços e dados de construção das barras. Aqui você encontra informações sobre o tipo de passo e seu parâmetro, o filtro inverso e o parâmetro de desenho das sombras.

A função pode ser dividido em duas partes: uma parte com o número de cálculo dos tijolos e outra para cálculo de preenchimento de buffers grafical.

No início da função os buffers são resetados pelo switch, deligando caixas vazias. Mais tarde variáveis ​​auxiliares são inseridas: variável "doorstep_now" é utilizada para o passo (usada para alterar o tamanho na etapa percentual), "point_go" armazena informações sobre a distância entre o último tijolo construído, variável "a" é utilizada para o cálculo dos tijolos, "up_price_calc" e "down_price_calc" - análise das últimas máximas e mínimas dos preços, "type_box_calc" - o último tipo de tijolo analisado ​​(acima ou abaixo).

Ambos partes da função consistem num loop, a segunda parte completa a primeira analisando o processo em detalhes.

O primeiro loop é processado através de todos os valores copiados, o valor das "barras" é responsável por um número de dados copiados (é calculado na função "func_concolidation", a ser considerada mais adiante). Outras informações sobre o loop da função começam nos cálculos do tamanho dos tijolos. Uma vez que cada barra tem um preço diferente de fechamento, se o passo percentual é usado, ele deve ser calculado para cada barra separadamente.

A condicional se declara verificando a direção dos preços, onde o preço tem que passar um ou mais passos distantes. Após o movimento do preço com a direção determinada, a condição do movimento anterior (o último tijolo) é conferida. Isto é feito porque os parâmetros do indicador incluem o parâmetro de filtro (número de tijolos necessários para a reversão). Depois que todas as condições são conferidas o loop é iniciado, ele é processado muitas vezes conforme os tijolos representam o movimento do preço corrente.

As barras sao calculadas, os cálculos dos arrays de buffers são alterados em tamanho e eles são resetados. Depois disso, nos primeiros (utilizado durante a primeira comparação) arrays de cálculo são atribuídos valores primários.

Se o número máximo possível de barras apresentado é menor do que o maior número possível de tijolos, tijolos extras são calculados e uma mensagem sobre o valor baixo é apresentada. Isto tem por objetivo impedir a exibição errado do gráfico.

A variável de cálculo do número de tijolos é resetada e inicia o loop principal. Ao contrário do ciclo anterior, o loop principal também é responsável pelo preenchimento de cálculo dos arrays de buffer e contra reposição dos tijolos.

No final da função, os buffers grafical são preenchidos.

//+------------------------------------------------------------------+
//| 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. Função para criar uma "linha de tendência" e objetos gráficos tipo "retângulo"

A função "func_create_trend_line" cria uma "linha de tendência" e a "func_create_square_or_rectangle" cria objetos gráficos tipo "retângulo", são baseadas na documentação referenciada OBJ_RECTANGLE e OBJ_TREND. São usadas ​​para criar objetos no gráfico "Renko" e para construir "ZigZag" no gráfico principal.

//+------------------------------------------------------------------+
//| 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. A construção "Renko" no gráfico principal

O uso de cálculos dos arrays do buffer comum para a função "func_draw_renko_main_chart" que desenha o gráfico Renko é muito compacto.

Os parâmetros de entrada incluídos são: tijolo acima e abaixo com os seus quadros, dois tipos de largura dos quadros (o primeiro é usado para o tijolo, o segundo - para o seu quadro), três opções de exibição (dos "tijolos", suas cores e quadros).

As variáveis ​​com nomes de objetos são declaradas, então o loop com o nome gerado de cada objeto é aberto e dependendo do tipo de tijolo anterior, as funções da "linha de tendência" e dos objetos gráficos tipo "retângulo" serão lançadas. Os parâmetros são extraídos dos cálculos dos arrays do buffer .

//+------------------------------------------------------------------+
//| 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. A construção "ZigZag" no gráfico principal

A função "func_draw_zig_zag" implementa o "ZigZag" no gráfico do indicador.

Os parâmetros de entrada: a forma de desenhar (na máxima ou na mínima dos preços ou sobre os pontos do gráfico), a espessura da linha, a cor da linha acima ou abaixo.

A alteração do parâmetro "zig_zag_shadow" pode ser visto na figura 4. Se for "verdade" (true), então o indicador desenha as linhas "ZigZag" sobre os pontos de sombra (máxima e mínima dos preços), na opção "falsa" (false), as linhas do "ZigZag" são desenhadas sobre a máxima e mínima dos pontos "Renko".


Fig.4. O impacto do parâmetro "zig_zag_shadow" no EURUSD, H1, 10 pontos.

Fig.4. O impacto do parâmetro "zig_zag_shadow" no EURUSD, H1, 10 pontos.  

Para construir o objeto "linha de tendência" são necessários dois pontos (inicial e final), digite duas variáveis ​​para o parâmetro de preço e duas variáveis ​​para o parâmetro de datas. A condicional declarada define o primeiro ponto dependendo do tipo do tijolo inicial.

O loop constrói todos os objetos lançados. Como você pode ver, o loop inicia a partir da segunda análise do tijolo, pois o primeiro ponto já está definido. Em seguida, a condicional declarada verifica o tipo do tijolo (o comportamento dos preços). A variável do nome do objecto é preenchida e dependendo da alteração de movimento, o loop se divide. Por sua vez, o método de desenho pode ser dividido em duas variantes.

Se ele é exibido na mínimas e máxima dos preços, os arrays de dados Price_high[] e Price_low[] pesquisam as mínima e máxima dos pontos próximos. A pesquisa é restrita as barras próximas.

Se for ordenado nos pontos do gráfico, os dados são atribuídos a partir dos arrays dos buffers.

A função de construção da "linha de tendência" é chamada. A função termina a análise e plotagem do "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. Apagar objetos gráficos criados anteriormente

O número mágico é usado para determinar os objetos do indicador. Ele simplifica o lançamento de vários indicadores sobre o gráfico e processo de exclusão de objetos.

A função "func_delete_objects" é usada para excluir objetos. O nome (definido de acordo com os objetos: linha de tendência ou retângulo) e o número dos objetos são dois parâmetros de entrada. A função procura os objetos e os exclui com o nome já atribuído.

//+------------------------------------------------------------------+
//| 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);
     }
  }

A função consolida todas as funções para a exclusão de todos os objetos do indicador que foram criados.

//+------------------------------------------------------------------+
//| 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. Função para a criação de níveis

A função "func_create_levels" para a criação de nível simplifica a exibição gráfica na janela do indicador. Tem apenas dois parâmetros de entrada: número de níveis e a cor.

O corpo da função IndicatorSetInteger é usada para definir o número de níveis apresentados, em seguida o preço e a cor são definidos para cada nível.

//+------------------------------------------------------------------+
//| 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. A função de consolidação

A função "func_consolidation" foi criada para consolidar todas as funções.

A função chama todas as funções executadas.

//+------------------------------------------------------------------+
//| 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. Funções OnCalculate() e OnChartEvent()

Antes de prosseguir para a função OnCalculate(), vamos dar uma olhada na função "func_new_bar" que analisa a nova barra.

É a função simplificada descrita em 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);
  }

A função OnCalculate() inicia a consolidação de todas as funções se uma nova barra foi iniciada durante a atualização do gráfico.  

//+------------------------------------------------------------------+
//| 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);
  }

A função OnChartEvent() exclui todos os objetos gráficos com a tecla "C", com a tecla "R" é redesenhado o gráfico (a função de consolidação).

//+------------------------------------------------------------------+
//| 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. Função OnDeinit()

Finalmente, a função OnDeinit(). Esta função inicia a exclusão de todos os objetos gráficos do indicador.

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


4. Usando o gráfico Renko na prática

O gráfico Renko é construído de acordo com a estratégia de movimentos dos preços.

Vamos começar com a estratégia mais popular: vender quando o tijolo ascendente começa a se mover para baixo e comprar no caso oposto.

Isto é mostrado na Fig. 5:


Fig.5. Gráfico Renko Padrão (EURUSD H4, 20 points)

Fig.5. Gráfico Renko Padrão (EURUSD H4, 20 points)

A fig. 5 mostra seis pontos (A, B, C, D, E, F) da entrada no mercado.

No ponto "A" ocorre mudanças do movimento de tijolos ascendentes para baixo.

Nos pontos (B, C, D) temos a reversão dos tijolos ocorrida com o movimento dos preços. No entanto, no ponto "E" dois tijolos foram criados com um movimento descendente e com as sombras abaixo no mesmo nível.

Neste caso, a entrada seria possível entre os pontos "E" e "F", porém não foi uma entrada bem sucedida, pois o preço moveu-se na direção oposta, a situação analógica ocorre no ponto "F": onde um movimento cria dois tijolos também com as sombras no mesmo nível. Embora com um movimento forte o preço não mudou sua direção.

A implicação é que a entrada mais favorável para o mercado é quando ocorre a reversão do tijolo (olhar para as sombras) num único movimento. Se dois tijolos são criados de uma vez, esta entrada pode ser insegura.

O "ZigZag" ordenado na fig.6 pode ser usado na análise gráfica, está mostrando alguns exemplos: temos as linhas de "suporte ", de "resistência" e a figura "cabeça e ombros" definindo o modelo.


Fig.6. Análise gráfica (GBPUSD H4, 20 points)

Fig.6. Análise gráfica (GBPUSD H4, 20 points)

A análise gráfica de "canal Eqüidistante" é mostrada na figura. 7.

O indicador está definido para analisar o timeframe H1 e o gráfico é exibido no timeframe H4.

Essas configurações permitem o acompanhamento de sinais nos vários intervalos de tempo simultaneamente, o que significa que o indicador pode ser usado por dois timeframe de valores diferentes.


Fig.7. Analise do "canal Eqüidistante", USDCHF H4 com configurações do H1, 20 pontos

Fig.7. Analise do "canal Eqüidistante", USDCHF H4 com configurações do H1, 20 pontos

Fig. 8 representa mais um exemplo de diferentes prazos no gráfico.

O tempo gráfico mostra as possíveis reversões no fechamento, o gráfico de quatro horas exclui sinais inúteis, o gráfico diário aprova a longa duração dos movimentos de tendências.


Fig.8. Indicador Renko no GBPUSD, H1, H4 and D1

Fig.8. Indicador Renko no GBPUSD, H1, H4 and D1

Mais um exemplo do indicador está na Figura 9. A regra diz: construir uma linha ascendente entre os tijolos na cor vermelha mais próximos com pelo menos um tijolo azul entre eles e vender depois que um tijolo é exibido abaixo da linha.

E o oposto: construir a linha descendente entre os tijolos na cor azul mais próximos com pelo menos um tijolo vermelho entre eles e comprar depois que um tijolo é exibido acima da linha.

As cores são mencionadas de acordo com a Fig. 9. Setas vermelhas e azuis marcam os locais de desenho da linha e as setas grandes marcam os sinais de compra e venda.

Fig.9. Um exemplo do GBPUSD, H4, indicador de 25 pontos

Fig.9. Um exemplo do GBPUSD, H4, indicador de 25 pontos

Conclusão

O gráfico Renko é interessante para os iniciantes e traders profissionais. Muitos anos se passaram e ele ainda é usado nos mercados.

Neste artigo eu quis chamar a sua atenção para este modelo e melhorar a análise do gráfico Renko. Tentei mostrar o método detalhado da construção do gráfico Renko.

Terei todo o prazer de considerar novas idéias e melhorias para o indicador e, talvez, implementá-las no futuro. Existem várias formas de implementação do indicador, você pode encontrar seus métodos de execução também.

Obrigado pelo seu interesse! Desejo-lhe sucesso nos negócios e nas novas implementações de estratégias de negociação.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/792

Arquivos anexados |
abcr.mq5 (77.52 KB)
Últimos Comentários | Ir para discussão (14)
AEJordao
AEJordao | 12 set 2017 em 16:02

O ABCR funciona perfeitamente no MT5. No momento estou utilizando com o mini índice WINV17.  A unica alteração que fiz foi recompilar alterando a data de inicio de 2013 para 2017, ai ele passou a carregar mais rápido.

cesarbellaver
cesarbellaver | 13 set 2017 em 20:07

O indicador está funcionando perfeitamente. Mas não consigo mudar a cor dos níveis para None (clrNONE / -1), mesmo alterando direto no código. Acho que a função seria essa:

      IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,level_color);

hugolemos
hugolemos | 12 dez 2017 em 15:10

Boa tarde. Uma dica para quem não visualiza o gráfico renko quando arrasta o indicador para a janela gráfica. Tente apertar a tecla "R" do teclado. No meu funcionou. Abraços.

gustavocarvalho
gustavocarvalho | 15 abr 2018 em 01:14
cesarbellaver:

O indicador está funcionando perfeitamente. Mas não consigo mudar a cor dos níveis para None (clrNONE / -1), mesmo alterando direto no código. Acho que a função seria essa:

      IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,level_color)

Altera na linha 41 para uma das cores do link https://www.mql5.com/pt/docs/constants/objectconstants/webcolors. 

284954
284954 | 20 jun 2021 em 03:31
hugolemos:

Boa tarde. Uma dica para quem não visualiza o gráfico renko quando arrasta o indicador para a janela gráfica. Tente apertar a tecla "R" do teclado. No meu funcionou. Abraços.

Valeu, amigo! Funcionou aqui, obrigado!

Trabalhando com modem GSM a partir de um Expert Advisor MQL5 Trabalhando com modem GSM a partir de um Expert Advisor MQL5
Atualmente há um número razoável de meios para uma monitorização remota confortável de uma conta de negociação: terminais móveis, notificações push, trabalhando com o ICQ. Mas tudo requer conexão com a Internet. Este artigo descreve o processo de criação de um Expert Advisor que lhe permitirá ficar em contato com o terminal de negociação, mesmo quando a Internet móvel não estiver disponível, através de chamadas e mensagens de texto.
Guia prático MQL5: Desenvolvimento de um Indicador de Símbolos Múltiplos para Análise de Divergência de Preço Guia prático MQL5: Desenvolvimento de um Indicador de Símbolos Múltiplos para Análise de Divergência de Preço
Neste artigo, vamos considerar o desenvolvimento de um indicador de símbolos múltiplos para análise de divergência de preço dentro de um período de tempo determinado. Os temas centrais já foram discutidas no artigo anterior sobre programação de indicadores de múltiplas moedas: "Guia prático do MQL5: Desenvolvimento de um Indicador de Símbolos Múltiplos em MQL5". Então, desta vez vamos focar apenas nas novas características e funções que foram alteradas drasticamente. Se você é novo em programação de indicadores de múltiplas moedas, primeiro eu recomendo a leitura do artigo anterior.
Contratos futuros contínuos em MetaTrader 5 Contratos futuros contínuos em MetaTrader 5
O curto período dos contratos futuros complica sua análise técnica, é tecnicamente difícil de analisar este tipo de ativo. Por exemplo, o número de barras no gráfico diário do contrato futuro do índice de Ações Ucraniana UX-9.13 é maior do que 100, portanto o trader cria longos contratos futuros sintéticos. Este artigo explica como emendar contratos futuros com datas diferentes no terminal MetaTrader 5.
Os Traders Necessitam de Serviços de Desenvolvedores? Os Traders Necessitam de Serviços de Desenvolvedores?
Os sistemas de negociação algorítmica se tornam mais populares e necessários, o que naturalmente levou a uma demanda por algoritmos exóticos e tarefas incomuns. Até certo ponto, esses aplicativos complexos estão disponíveis na Base de Código ou no Mercado. Embora os traders tenham acesso simples para os aplicativos em poucos cliques, esses aplicativos podem não satisfazer integralmente todas as necessidades. Neste caso, os traders procuram por desenvolvedores que podem escrever o aplicativo desejado na seção MQL5 Freelance e colocam uma encomenda.