Traçando linhas de tendência baseadas em fractais usando MQL4 e MQL5

10 junho 2015, 15:40
Almat Kaldybay
0
3 403

Índice


Introdução

Recentemente, eu estive pensando sobre o uso de linhas de tendência. Houve uma questão sobre a escolha do método para determinar os pontos para a plotagem das linhas, e também sobre a precisão da plotagem. Eu decidi usar os fractais como base.

Eu costumo analisar os mercados em meu trabalho principal, onde eu posso passar algum tempo nas negociações. Além disso, você não pode simplesmente desenhar as linhas em um período de tempo grande - a linha deve ser traçada pelos pontos extremos com uma precisão de até 15 minutos. A razão para isto é que o tempo do fractal em um período de tempo maior nem sempre coincide com o tempo do mesmo ponto extremo no M15. Em suma, isto é onde a automação vem para ajudar. Aconteceu que eu comecei a escrever o código usando MQL5 e, em seguida, eu mudei para MQL4, porque eu precisava este programa para o MetaTrader 4.

Neste artigo eu apresentei a minha solução do problema usando MQL4 e MQL5. O artigo fornece uma visão comparativa, mas seria inadequado comparar aqui a eficiência da MQL4 e MQL5. Além disso, eu entendo que provavelmente há outras soluções, mais eficaz do que a minha. O artigo pode ser útil para iniciantes que escrevem scripts usando tanto o MQL4 quanto o MQL5, especialmente para aqueles que planejam usar fractais e linhas de tendência.


1. Parâmetros de entrada, função DeInit() e a declaração inicial de variáveis

Eu usei as seguintes variáveis ​​como parâmetros de entrada:

input color Resistance_Color=Red;       // Definindo a cor da linha de resistência
input ENUM_LINE_STYLE Resistance_Style; // Definindo o estilo da linha de resistência
input int Resistance_Width=1;           // Definindo a largura da linha de resistência
input color Support_Color=Red;          // Definindo a cor da linha de suporte
input ENUM_LINE_STYLE Support_Style;    // Definindo o estilo da linha de suporte
input int Support_Width=1;              // Definindo a largura da linha de suporte

Esses parâmetros são os mesmos para MQL4 e MQL5.

Em MQL5 precisamos criar o indicador com antecedência:

//--- Manipulador do indicador iFractals 
int Fractal;
//+------------------------------------------------------------------+
//| Função de inicialização do Expert                                |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Recebendo o manipulador do indicador iFractals
   Fractal=iFractals(Symbol(),PERIOD_D1);
//---
   return(INIT_SUCCEEDED);
  }

Já que o programa irá desenhar objetos gráficos, faz sentido removê-los ao retirar o Expert Advisor do gráfico:

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

A plotagem de duas linhas (suporte e resistência) requerem quatro pontos. Para determinar o ponto da linha de passagem, precisamos saber o tempo e o preço.

As coordenadas são determinadas por esta ordem: em primeiro lugar, encontramos a barra extrema, conhecendo a barra extrema nós podemos determinar o preço e o tempo do ponto extremo.

Declarando as variáveis ​​na função OnTick():

MQL4
//--- Declaração das variáveis
int n,UpperFractal_1,UpperFractal_2,LowerFractal_1,LowerFractal_2;
MQL5
//--- Declaração das variáveis
int n,UpperFractal_1,UpperFractal_2,LowerFractal_1,LowerFractal_2;
//--- Declarando os arrays para escrever os valores do buffer do indicador iFractal
double FractalDown[],FractalUp[];
double UpFractal_1,UpFractal_2,LowFractal_1,LowFractal_2;

Primeiramente, eu declarei apenas aquelas variáveis ​​que armazenam os índices das barras com os fractais formados.

Em MQL4:

  1. n - a variável é necessária para encontrar o fractal mais próximo conhecido usando o operador de loop for;
  2. UpperFractal_1, UpperFractal_2, LowerFractal_1, LowerFractal_2 - essas variáveis ​​irão armazenar o índice de uma barra no primeiro e no segundo ponto extremo mais próximo com a máxima/mínima do preço (em termos de determinação dos fractais);

Em MQL5 nós introduzimos as variáveis ​​adicionais:

  1. FractalDown[], FractalUp[]; - Declarando arrays de valores do tipo double para armazenar os valores do buffer do indicador iFractals;
  2. Em seguida, as variáveis ​​tipo double: UpFractal_1, UpFractal_2, LowFractal_1, LowFractal_2. Eles irão armazenar os valores do preço dos pontos extremos.

2. Busca pelos fractais mais próximos

Para encontrar o índice de um barra com um fractal formado usamos o operador de loop for.

Vamos determinar os índices das duas primeiras barras que correspondem ao primeiro e ao segundo fractal superior:

MQL4
//--- Encontrando o índice da bar do primeiro fractal superior mais próximo
   for(n=0; n<(Bars-1);n++)
     {
      if(iFractals(NULL,1440,MODE_UPPER,n)!=NULL)
         break;
      UpperFractal_1=n+1;
     }
//--- Encontrando o índice da barra do segundo fractal superior mais próximo
   for(n=UpperFractal_1+1; n<(Bars-1);n++)
     {
      if(iFractals(NULL,1440,MODE_UPPER,n)!=NULL)
         break;
      UpperFractal_2=n+1;
     }
 MQL5
//--- Primeiro, nós precisamos escrever os valores do buffer do indicador Fractal nos arrays
//--- preenchendo os arrays com os valores do buffer
   CopyBuffer(Fractal,0,TimeCurrent(),Bars(Symbol(),PERIOD_D1),FractalUp);
   CopyBuffer(Fractal,1,TimeCurrent(),Bars(Symbol(),PERIOD_D1),FractalDown);
//--- Indexação como nas séries de tempo
   ArraySetAsSeries(FractalUp,true);
   ArraySetAsSeries(FractalDown,true);
//--- em seguida, usamos o operador de loop for para encontrar o primeiro fractal superior
   for(n=0; n<Bars(Symbol(),PERIOD_D1); n++)
     {
      //--- Se o valor não for vazio, quebra o loop
      if(FractalUp[n]!=EMPTY_VALUE)
         break;
     }
//--- Escrevendo o valor do preço do primeiro fractal para a variável
   UpFractal_1=FractalUp[n];
//--- Escrever o índice do primeiro fractal para a variável
   UpperFractal_1=n;
//--- Encontrando o segundo fractal superior 
   for(n=UpperFractal_1+1; n<Bars(Symbol(),PERIOD_D1); n++)
     {
      if(FractalUp[n]!=EMPTY_VALUE) // Se o valor não for vazio, quebra o loop
         break;
     }
//--- Escrevendo o valor do preço do segundo fractal para a variável
   UpFractal_2=FractalUp[n];
//--- Escrevendo o índice do segundo fractal para a variável
   UpperFractal_2=n;

Aqui eu claramente demonstrei uma das principais diferenças entre a MQL5 e MQL4 - usando as funções para acessar as séries de tempo.

Em MQL4, eu comecei imediatamente a encontrar o índice da barra com um fractal formado, mas em MQL5 eu especifiquei os arrays FractalUp[] e FractalDown[] para armazenar os valores do preço dos fractais superiores e inferiores, acessando o indicador iFractals com a função CopyBuffer(). Em seguida, eu defini a indexação desses arrays como nas séries de tempo usando a função ArraySetAsSeries().

Em MQL4 eu obtive apenas os índices das barras com os fractais conhecidos, mas em MQL5 eu usei a função CopyBuffer() para obter os índices das barras e os valores do preço dos fractais.

Da mesma forma, encontramos os primeiros dois fractais inferiores:

MQL4
//--- encontrando o índice da primeira barra mais próximo do fractal inferior
   for(n=0; n<(Bars-1);n++)
     {
      if(iFractals(NULL,1440,MODE_LOWER,n)!=NULL)
         break;
      LowerFractal_1=n+1;
     }
//--- encontrando o índice da segunda barra mais próximo do fractal inferior
   for(n=LowerFractal_1+1; n<(Bars-1);n++)
     {
      if(iFractals(NULL,1440,MODE_LOWER,n)!=NULL)
         break;
      LowerFractal_2=n+1;
     }
 MQL5
//--- encontrando os valores dos fractais inferiores
//--- encontrando o primeiro fractal inferior
   for(n=0; n<Bars(Symbol(),PERIOD_D1); n++)
     {
      //--- Se o valor não for vazio, quebra o loop
      if(FractalDown[n]!=EMPTY_VALUE)
         break;
     }
//--- Escrevendo o valor do preço do primeiro fractal para a variável
   LowFractal_1=FractalDown[n];
//--- Escrever o índice do primeiro fractal para a variável
   LowerFractal_1=n;
//--- encontrando o segundo fractal inferior 
   for(n=LowerFractal_1+1; n<Bars(Symbol(),PERIOD_D1); n++)
     {
      if(FractalDown[n]!=EMPTY_VALUE)
         break;
     }
//--- Escrevendo o valor do preço do segundo fractal para a variável
   LowFractal_2=FractalDown[n];
//--- Escrevendo o índice do segundo fractal para a variável
   LowerFractal_2=n;

Como você pode ver, o código é muito semelhante em MQL4 e MQL5. Há uma ligeira diferença na sintaxe.


3. Determinando os valores de preço e de tempo dos fractais

Para traçar a linha que precisamos para determinar o tempo e o preço de um fractal. Claro que, em MQL4 poderíamos simplesmente usar as séries de tempo predefinidas High[] e Alta Low[], e a função iTime(), no entanto, também precisamos obter as coordenadas de tempo com maior precisão para garantir a plotagem correta da linha de tendência.

Figo. 1-2 mostram a diferença entre os valores de tempo dos pontos de extremos nos períodos de tempo H4 e M15.

Fig.1. O valor de tempo do ponto extremo em H4

Fig.1. O valor de tempo do ponto extremo em H4

Fig.2. O valor de tempo do ponto extremo em M15

Fig.2. O valor de tempo do ponto extremo em M15

Eu cheguei a uma conclusão de que a precisão do ponto extremo de 15 minutos é suficiente para os meus propósitos.

Em geral, o princípio de clarificação do ponto extremo é quase o mesmo tanto para MQL4 quanto para MQL5, mas existem algumas diferenças em detalhes:

MQL4MQL5
  1. Determinar o valor de tempo do ponto extremo em um período de tempo maior;
  2. Usando o valor de tempo encontrado, determinar o índice da barra extrema sobre um período de tempo menor com a função iBarShift();
  3. Já que 24 horas pode ser representado como um array de 96 barras de 15 minutos, buscamos um ponto extremo (o maior/menor valor) entre estes 96 elementos usando as funções iHigh(),iLow(),iTime(), ArrayMaximum() e ArrayMinimum().
  1. Determinar o valor de tempo do ponto extremo em um período de tempo maior;
  2. Usando o valor de tempo encontrado, determinar o tempo de geração da barra do próximo dia. Nós precisamos desse valor para usar nas funções CopyHigh(), CopyLow() e CopyTime();
  3. Declarar e preencher os arrays para armazenar os valores de preço e horário para o período de 15 minutos;
  4. Usando as funções ArrayMaximum() e ArrayMinimum(), encontrar os valores mínimos e máximos de preço, e os valores de tempo dos pontos extremos esclarecidos. 

O código para cada passo é mostrado abaixo:

 MQL4
// Passo 1. Determinando o valor de tempo do ponto extremo em um período de tempo maior:
//--- Determinando o tempo dos fractais
   datetime UpFractalTime_1=iTime(NULL, 1440,UpperFractal_1);
   datetime UpFractalTime_2=iTime(NULL, 1440,UpperFractal_2);
   datetime LowFractalTime_1=iTime(NULL, 1440,LowerFractal_1);
   datetime LowFractalTime_2=iTime(NULL, 1440,LowerFractal_2);
// Passo 2. Determinando o índice da barra extrema em um período de tempo menor:   
//--- Encontrando o índice do fractal em M15
   int UpperFractal_1_m15=iBarShift(NULL, 15, UpFractalTime_1,true);
   int UpperFractal_2_m15=iBarShift(NULL, 15, UpFractalTime_2,true);
   int LowerFractal_1_m15=iBarShift(NULL, 15, LowFractalTime_1,true);
   int LowerFractal_2_m15=iBarShift(NULL, 15, LowFractalTime_2,true);
// Passo 3. Usando os arrays para encontrar os pontos de extremos esclarecidos sobre o М15:
//--- Usando os arrays para encontrar os pontos de extremos esclarecidos
//--- Introduzindo a variável i para usar no operador de loop for
   int i;
//--- 1. Em primeiro lugar, encontrar os pontos de extremo menores
//--- 3.1 Encontrando o primeiro ponto de extremo inferior
//--- Declarando o array para armazenar os valores de índice das barras
   int Lower_1_m15[96];
//--- Declararando o array para armazenar os valores de preços
   double LowerPrice_1_m15[96];
//--- Começando o loop for:
   for(i=0;i<=95;i++)
     {
      //--- Preenchendo o array com os valores do índice da barra
      Lower_1_m15[i]=LowerFractal_1_m15-i;
      //--- Preenchendo o array com os valores do preço
      LowerPrice_1_m15[i]=iLow(NULL,15,LowerFractal_1_m15-i);
     }
//--- Determinando o valor do preço mínimo no array
   int LowestPrice_1_m15=ArrayMinimum(LowerPrice_1_m15,WHOLE_ARRAY,0);
//--- Determinando a barra com o menor preço no array
   int LowestBar_1_m15=Lower_1_m15[LowestPrice_1_m15];
//--- Determinando o tempo do menor preço da barra
   datetime LowestBarTime_1_m15=iTime(NULL,15,Lower_1_m15[LowestPrice_1_m15]);

//--- 3.2 Encontrando o segundo ponto de extremo inferior
   int Lower_2_m15[96];
   double LowerPrice_2_m15[96];
   for(i=0;i<=95;i++)
     {
      //--- Preenchendo o array com os valores do índice da barra
      Lower_2_m15[i]=LowerFractal_2_m15-i;
      //--- Preenchendo o array com os valores do preço
      LowerPrice_2_m15[i]=iLow(NULL,15,LowerFractal_2_m15-i);
     }
//--- Determinando o valor do preço mínimo no array
   int LowestPrice_2_m15=ArrayMinimum(LowerPrice_2_m15,WHOLE_ARRAY,0);
//--- Determinando a barra com o menor preço no array
   int LowestBar_2_m15=Lower_2_m15[LowestPrice_2_m15];
//--- Determinando o tempo do menor preço da barra
   datetime LowestBarTime_2_m15=iTime(NULL,15,Lower_2_m15[LowestPrice_2_m15]);

//--- 3.3 Encontrando o primeiro ponto de extremo superior
   int Upper_1_m15[96];
   double UpperPrice_1_m15[96];
   for(i=0;i<=95;i++)
     {
      //--- Preenchendo o array com os valores do índice da barra
      Upper_1_m15[i]=UpperFractal_1_m15-i;
      //--- Preenchendo o array com os valores do preço
      UpperPrice_1_m15[i]=iHigh(NULL,15,UpperFractal_1_m15-i);
     }
//--- Determinando o valor do preço máximo no array
   int HighestPrice_1_m15=ArrayMaximum(UpperPrice_1_m15,WHOLE_ARRAY,0);
//--- Determinando a barra com a máxima do preço no array
   int HighestBar_1_m15=Upper_1_m15[HighestPrice_1_m15];
//--- Determinando o tempo da barra de preço mais alta
   datetime HighestBarTime_1_m15=iTime(NULL,15,Upper_1_m15[HighestPrice_1_m15]);

//--- 3.4 Encontrando o segundo ponto de extremo superior
   int Upper_2_m15[96];
   double UpperPrice_2_m15[96];
   for(i=0;i<=95;i++)
     {
      //--- Preenchendo o array com os valores do índice da barra
      Upper_2_m15[i]=UpperFractal_2_m15-i;
      //--- Preenchendo o array com os valores do preço
      UpperPrice_2_m15[i]=iHigh(NULL,15,UpperFractal_2_m15-i);
     }
 MQL5
// Passo 1. Determinando o valor de tempo do ponto extremo em um período de tempo maior:
//--- Declarando os arrays para armazenar os valores de tempo do índice da barra correspondente em um período de tempo maior
   datetime UpFractalTime_1[],LowFractalTime_1[],UpFractalTime_2[],LowFractalTime_2[];
//--- Determinando o tempo dos fractais em um período de tempo maior
   CopyTime(Symbol(),PERIOD_D1,UpperFractal_1,1,UpFractalTime_1);
   CopyTime(Symbol(),PERIOD_D1,LowerFractal_1,1,LowFractalTime_1);
   CopyTime(Symbol(),PERIOD_D1,UpperFractal_2,1,UpFractalTime_2);
   CopyTime(Symbol(),PERIOD_D1,LowerFractal_2,1,LowFractalTime_2);
// Passo 2. Determinar o tempo de geração da próxima barra do dia:
// --- Determinando o tempo de geração da próxima bara do dia (o tempo de parada para CopyHigh(), CopyLow() e CopyTime())
   datetime UpFractalTime_1_15=UpFractalTime_1[0]+86400;
   datetime UpFractalTime_2_15=UpFractalTime_2[0]+86400;
   datetime LowFractalTime_1_15=LowFractalTime_1[0]+86400;
   datetime LowFractalTime_2_15=LowFractalTime_2[0]+86400;
// Passo 3. Declarando e preeenchendo os arrays para armazenar os preços e valores de tempo para o período de 15 minutos:   
//--- Declarando os arrays para armazenar os valores máximos e mínimos do preço
   double High_1_15[],Low_1_15[],High_2_15[],Low_2_15[];
//--- Preenchendo os arrays com as funções CopyHigh() e CopyLow()
   CopyHigh(Symbol(),PERIOD_M15,UpFractalTime_1[0],UpFractalTime_1_15,High_1_15);
   CopyHigh(Symbol(),PERIOD_M15,UpFractalTime_2[0],UpFractalTime_2_15,High_2_15);
   CopyLow(Symbol(),PERIOD_M15,LowFractalTime_1[0],LowFractalTime_1_15,Low_1_15);
   CopyLow(Symbol(),PERIOD_M15,LowFractalTime_2[0],LowFractalTime_2_15,Low_2_15);
//--- Declarando os arrays para armazenar os valores de tempo correspondentes aos índices da barra de extremo  
   datetime High_1_15_time[],High_2_15_time[],Low_1_15_time[],Low_2_15_time[];
//--- Preenchendo os arrays
   CopyTime(Symbol(),PERIOD_M15,UpFractalTime_1[0],UpFractalTime_1_15,High_1_15_time);
   CopyTime(Symbol(),PERIOD_M15,UpFractalTime_2[0],UpFractalTime_2_15,High_2_15_time);
   CopyTime(Symbol(),PERIOD_M15,LowFractalTime_1[0],LowFractalTime_1_15,Low_1_15_time);
   CopyTime(Symbol(),PERIOD_M15,LowFractalTime_2[0],LowFractalTime_2_15,Low_2_15_time);
// Passo 4. Encontrando os valores mínimos e máximos do preço, e os valores de tempo dos pontos de extremos esclarecidos:
//--- Determinação dos valores da máxima e mínima do preço e tempo com as funções ArrayMaximum() e ArrayMinimum()
   int Max_M15_1=ArrayMaximum(High_1_15,0,96);
   int Max_M15_2=ArrayMaximum(High_2_15,0,96);
   int Min_M15_1=ArrayMinimum(Low_1_15,0,96);
   int Min_M15_2=ArrayMinimum(Low_2_15,0,96);

Eventualmente, nós determinamos as seguintes coordenadas da linha de tendência:

1. Para a linha de suporte:

MQL4MQL5
  1. Coordenada do primeiro horário - LowestBarTime_2_m15;
  2. Coordenada do primeiro preço - LowerPrice_2_m15[LowestPrice_2_m15];
  3. Coordenada do segundo horário - LowestBarTime_1_m15;
  4. Coordenada do segundo preço - LowerPrice_1_m15[LowestPrice_1_m15].
  1. Coordenada do primeiro horário - Low_2_15_time [Min_M15_2];
  2. Coordenada do primeiro preço - Low_2_15[Min_M15_2];
  3. Coordenada do segundo horário - Low_1_15_time[Min_M15_1];
  4. Coordenada do segundo preço - Low_1_15[Min_M15_1].

2. Para a linha de resistência:

MQL4MQL5
  1. Coordenada do primeiro horário -  HighestBarTime_2_m15;
  2. Coordenada do primeiro preço  - UpperPrice_2_m15[HighestPrice_2_m15];
  3. Coordenada do segundo horário - HighestBarTime_1_m15;
  4. Coordenada do segundo preço - UpperPrice_1_m15[HighestPrice_1_m15].
  1. Coordenada do primeiro horário - High_2_15_time[Max_M15_2];
  2. Coordenada do primeiro preço - High_2_15[Max_M15_2];
  3. Coordenada do segundo horário - High_1_15_time[Max_M15_1];
  4. Coordenada do segundo preço - High_1_15[Max_M15_1].


4. Criando objetos e editando suas propriedades. Redesenhando as linhas

Agora, que nós sabemos das coordenadas da linha, nós só precisamos criar os objetos gráficos:

MQL4
//--- Criação da linha de suporte
   ObjectCreate(0,"TL_Support",OBJ_TREND,0,LowestBarTime_2_m15,LowerPrice_2_m15[LowestPrice_2_m15],
                LowestBarTime_1_m15,LowerPrice_1_m15[LowestPrice_1_m15]);
   ObjectSet("TL_Support",OBJPROP_COLOR,Support_Color);
   ObjectSet("TL_Support",OBJPROP_STYLE,Support_Style);
   ObjectSet("TL_Support",OBJPROP_WIDTH,Support_Width);
//--- Criando a linha de resistência
   ObjectCreate(0,"TL_Resistance",OBJ_TREND,0,HighestBarTime_2_m15,UpperPrice_2_m15[HighestPrice_2_m15],
                HighestBarTime_1_m15,UpperPrice_1_m15[HighestPrice_1_m15]);
   ObjectSet("TL_Resistance",OBJPROP_COLOR,Resistance_Color);
   ObjectSet("TL_Resistance",OBJPROP_STYLE,Resistance_Style);
   ObjectSet("TL_Resistance",OBJPROP_WIDTH,Resistance_Width);
MQL5
//--- Criação da linha de suporte
   ObjectCreate(0,"TL_Support",OBJ_TREND,0,Low_2_15_time[Min_M15_2],Low_2_15[Min_M15_2],Low_1_15_time[Min_M15_1],Low_1_15[Min_M15_1]);
   ObjectSetInteger(0,"TL_Support",OBJPROP_RAY_RIGHT,true);
   ObjectSetInteger(0,"TL_Support",OBJPROP_COLOR,Support_Color);
   ObjectSetInteger(0,"TL_Support",OBJPROP_STYLE,Support_Style);
   ObjectSetInteger(0,"TL_Support",OBJPROP_WIDTH,Support_Width);
//--- Criando a linha de resistência
   ObjectCreate(0,"TL_Resistance",OBJ_TREND,0,High_2_15_time[Max_M15_2],High_2_15[Max_M15_2],High_1_15_time[Max_M15_1],High_1_15[Max_M15_1]);
   ObjectSetInteger(0,"TL_Resistance",OBJPROP_RAY_RIGHT,true);
   ObjectSetInteger(0,"TL_Resistance",OBJPROP_COLOR,Resistance_Color);
   ObjectSetInteger(0,"TL_Resistance",OBJPROP_STYLE,Resistance_Style);
   ObjectSetInteger(0,"TL_Resistance",OBJPROP_WIDTH,Resistance_Width);

Então, eu criei as linhas necessárias e especifiquei seus parâmetros com base nos parâmetros de entrada.

Agora nós precisamos implementar o redesenho das linhas de tendência.

Quando a situação do mercado muda, por exemplo, quando um novo ponto de extremo aparece, podemos simplesmente remover a linha existente:

MQL4
//--- Redesenhando a linha de suporte
//--- Escrevendo os valores das coordenadas de tempo da linha de suporte para as variáveis
   datetime TL_TimeLow2=ObjectGet("TL_Support",OBJPROP_TIME2);
   datetime TL_TimeLow1=ObjectGet("TL_Support",OBJPROP_TIME1);
//--- Se as coordenadas da linha não corresponderem com às coordenadas atuais
   if(TL_TimeLow2!=LowestBarTime_1_m15 && TL_TimeLow1!=LowestBarTime_2_m15)
     {
      //--- remover a linha
      ObjectDelete(0,"TL_Support");
     }
//--- Redesenhando a linha de resistência
//--- Escrevendo os valores das coordenadas de tempo da linha de resistência para as variáveis
   datetime TL_TimeUp2=ObjectGet("TL_Resistance",OBJPROP_TIME2);
   datetime TL_TimeUp1=ObjectGet("TL_Resistance",OBJPROP_TIME1);
//--- Se as coordenadas da linha não corresponderem com às coordenadas atuais
   if(TL_TimeUp2!=HighestBarTime_1_m15 && TL_TimeUp1!=HighestBarTime_2_m15)
     {
      //--- remover a linha
      ObjectDelete(0,"TL_Resistance");
     }
MQL5
//--- Redesenhando a linha de suporte
//--- Escrevendo os valores das coordenadas de tempo da linha de suporte para as variáveis
   datetime TL_TimeLow2=(datetime)ObjectGetInteger(0,"TL_Support",OBJPROP_TIME,0);
   datetime TL_TimeLow1=(datetime)ObjectGetInteger(0,"TL_Support",OBJPROP_TIME,1);
//--- Se as coordenadas da linha não corresponderem com às coordenadas atuais
   if(TL_TimeLow2!=Low_2_15_time[Min_M15_2] && TL_TimeLow1!=Low_1_15_time[Min_M15_1])
     {
      //--- remover a linha
      ObjectDelete(0,"TL_Support");
     }
//--- Redesenhando a linha de resistência
//--- Escrevendo os valores das coordenadas de tempo da linha de resistência para as variáveis
   datetime TL_TimeUp2=(datetime)ObjectGetInteger(0,"TL_Resistance",OBJPROP_TIME,0);
   datetime TL_TimeUp1=(datetime)ObjectGetInteger(0,"TL_Resistance",OBJPROP_TIME,1);
//--- Se as coordenadas da linha não corresponderem com às coordenadas atuais
   if(TL_TimeUp2!=High_2_15_time[Max_M15_2] && TL_TimeUp1!=High_1_15_time[Max_M15_1])
     {
      //--- remover a linha
      ObjectDelete(0,"TL_Resistance");
     }


5. Verificando o carregamento do histórico de barras

Durante o teste, percebi que as linhas nem sempre desenham corretamente.

No início, eu pensei que havia um erro no código ou a minha solução não funcionava em tudo, mas então eu percebi que o problema foi causado pela carga insuficiente do histórico das barras em um período de tempo menor, o M15 no meu caso. Para avisar o usuário sobre estas questões, eu decidi fazer o programa, e adicionalmente, verificar se existe um barra no M15.

Para este efeito, em MQL4 eu usei a capacidade da função iBarShift() que eu originalmente usei ​​na seção "Determinando os valores de preço e de tempo dos fractais".

Se uma barra não for encontrada, a função iBarShift() retorna -1. Portanto, nós pode produzir o seguinte aviso:

MQL4
//--- Verificando o carregamento do histórico de barras
//--- Se pelo menos uma barra não foi encontrado em M15
   if(UpperFractal_1_m15==-1 || UpperFractal_2_m15==-1
      || LowerFractal_1_m15==-1 || LowerFractal_2_m15==-1)
     {
      Alert("O histórico carregado é insuficiente para o funcionamento correto!");
     }

Em MQL5 eu usei a função Bars() que retorna um valor vazio se os dados das séries temporais não fora gerados no terminal:

 
//--- Verificando o carregamento do histórico de barras
//--- 1. determinando o número de barras em um período de tempo especificado
   int High_M15_1=Bars(Symbol(),PERIOD_M15,UpFractalTime_1[0],UpFractalTime_1_15);
   int High_M15_2=Bars(Symbol(),PERIOD_M15,UpFractalTime_2[0],UpFractalTime_2_15);
   int Low_M15_1=Bars(Symbol(),PERIOD_M15,LowFractalTime_1[0],LowFractalTime_1_15);
   int Low_M15_2=Bars(Symbol(),PERIOD_M15,LowFractalTime_2[0],LowFractalTime_2_15);
//--- 2. verificar se a histórico carregado é insuficiente para o desenho da linha correta
//--- Se pelo menos uma barra não foi encontrada
   if(High_M15_1==0 || High_M15_2==0 || Low_M15_1==0 || Low_M15_2==0)
     {
      Alert("O histórico carregado é insuficiente para o funcionamento correto!");
     }


6. Sinais de rompimento de linhas de tendência, notificações push

Para completar o quadro, eu decidi implementar um sinal de rompimento da linha de tendência. A linha de tendência é traçada através dos pontos de extremo do período de tempo diário, mas para identificar o rompimento anterior, a barra deve ser fechada com um valor menor ou maior do que a linha de tendência em H4.

Em geral, pode-se dividir o processo em três passos:

  1. Determinar o preço de fechamento da barra e o preço da linha de tendência;
  2. Determinar as condições em que os preços rompem a linha de tendência;
  3. Enviar a notificação push sobre o rompimento.
MQL4
// 1. Obtendo os parâmetros de preços da linha de tendência 
//--- Determinando o preço de fechamento de um barra com índice 1
   double Price_Close_H4=iClose(NULL,240,1);
//--- Determinando o tempo de um barra com índice 1
   datetime Time_Close_H4=iTime(NULL,240,1);
//--- Determinação do índice da barra em H4
   int Bar_Close_H4=iBarShift(NULL,240,Time_Close_H4);
//--- Determinação do preço da linha em H4
   double Price_Resistance_H4=ObjectGetValueByShift("TL_Resistance",Bar_Close_H4);
//--- Determinação do preço da linha em H4   
   double Price_Support_H4=ObjectGetValueByShift("TL_Support",Bar_Close_H4);
// 2. Condições para o rompimento da linha de tendência
//--- Para romper a linha de suporte
   bool breakdown=(Price_Close_H4<Price_Support_H4);
//--- Para o rompimento da linha de resistência
   bool breakup=(Price_Close_H4>Price_Resistance_H4);
// 3. Entregando as notificações push
   if(breakdown==true)
     {
      //--- Enviar não mais do que uma notificação a cada 4 horas
      int SleepMinutes=240;
      static int LastTime=0;
      if(TimeCurrent()>LastTime+SleepMinutes*60)
        {
         LastTime=TimeCurrent();
         SendNotification(Symbol()+"O preço rompeu a linha de suporte");
        }
     }
   if(breakup==true)
     {
      //--- Enviar não mais do que uma notificação a cada 4 horas
      SleepMinutes=240;
      LastTime=0;
      if(TimeCurrent()>LastTime+SleepMinutes*60)
        {
         LastTime=TimeCurrent();
         SendNotification(Symbol()+"O preço rompeu a linha de resistência");
        }
     }
MQL5
// 1. Obtendo os parâmetros de preços da linha de tendência
   double Close[];
   CopyClose(Symbol(),PERIOD_H4,TimeCurrent(),10,Close);
//--- Definir a ordem de indexação do array
   ArraySetAsSeries(Close,true);
//---
   datetime Close_time[];
   CopyTime(Symbol(),PERIOD_H4,TimeCurrent(),10,Close_time);
//--- Definir a ordem de indexação do array
   ArraySetAsSeries(Close_time,true);
//---
   double Price_Support_H4=ObjectGetValueByTime(0,"TL_Support",Close_time[1]);
   double Price_Resistance_H4=ObjectGetValueByTime(0,"TL_Resistance",Close_time[1]);
// 2. Condições para o rompimento da linha de tendência
   bool breakdown=(Close[1]<Price_Support_H4);
   bool breakup=(Close[1]>Price_Resistance_H4);
// 3. Entregando as notificações push
   if(breakdown==true)
     {
      //--- Enviar não mais do que uma notificação a cada 4 horas
      int SleepMinutes=240;
      static int LastTime=0;
      if(TimeCurrent()>LastTime+SleepMinutes*60)
        {
         LastTime=(int)TimeCurrent();
         SendNotification(Symbol()+"O preço rompeu a linha de suporte");
        }
     }
   if(breakup==true)
     {
      //--- Enviar não mais do que uma notificação a cada 4 horas
      int SleepMinutes=240;
      static int LastTime=0;
      if(TimeCurrent()>LastTime+SleepMinutes*60)
        {
         LastTime=(int)TimeCurrent();
         SendNotification(Symbol()+"O preço rompeu a linha de resistência");
        }
     }

Para identificar um rompimento, eu usei a função ObjectGetValueByShift() em MQL4 e a função ObjectGetValueByTime() em MQL5.

Talvez, eu poderia apenas definir 1 em vez do Bar_Close_H4 como parâmetro para ObjectGetValueByShift(), mas eu decidi determinar o índice no primeiro H4. Eu utilizei a solução para limitar o número de mensagens enviadas publicadas neste tópico do fórum, e eu gostaria de agradecer muito ao autor.


7. Uso prático das linhas de tendência na negociação

A maneira mais simples: identificar um rompimento, esperar por um recuo e entrar no mercado depois.

Idealmente, você deve ter algo parecido com isto:

Fig. 3. Rompimento da linha de tendência

Fig.3. Rompimento da linha de tendência

 Você pode usar sua imaginação e tentar identificar as formações, ou seja, os padrões da análise técnica, por exemplo, um triângulo:

Fig.4. Padrão de triângulo

Fig.4. Padrão de triângulo

As linhas não foram esclarecidas por um período de tempo menor nas imagens acima.


Conclusão

Isto conclui o artigo, eu espero que você ache ele útil. O artigo foi destinado para iniciantes em programação, para amadores como eu.

Eu aprendi muito ao escrever este artigo: em primeiro lugar, eu comecei a fazer comentários de código mais significativos; segundo, no começo eu tinha uma solução mais trabalhosa e complexa para o esclarecimento do pontos de extremo, mas depois eu vim com uma solução mais simples, demonstrada aqui.

Obrigado pela leitura, qualquer feedback é apreciado.


Traduzido do russo pela MetaQuotes Software Corp.
Artigo original: https://www.mql5.com/ru/articles/1201

Arquivos anexados |
trendlines.mq4 (19.87 KB)
trendlines.mq5 (20.95 KB)
Construindo uma Aplicação Interativa para exibir feeds RSS no MetaTrader 5 Construindo uma Aplicação Interativa para exibir feeds RSS no MetaTrader 5

Neste artigo vamos ver a possibilidade de criar um aplicativo para a exibição de feeds RSS. O artigo irá mostrar como os aspectos da Biblioteca Padrão podem ser utilizados para a criação de programas interativos para o MetaTrader 5.

Freelance MQL5.com: Fonte de Renda dos Desenvolvedores (Infográfico) Freelance MQL5.com: Fonte de Renda dos Desenvolvedores (Infográfico)

Por ocasião do quarto aniversário do Serviço Freelance MQL5, nós preparamos uma infográfico demonstrando os resultados do serviço durante todo o tempo de sua existência. Os números falam por si mesmo: mais de 10.000 pedidos no valor total de 600 mil dólares foram executados até a presente data, enquanto que 3.000 clientes e 300 desenvolvedores já utilizaram o serviço.

Guia Prático MQL5: Ordens ОСО Guia Prático MQL5: Ordens ОСО

Qualquer atividade de negociação do trader envolve diversos mecanismos e inter-relações, incluindo as relações entre ordens. Este artigo sugere uma solução de processamento de ordens OCO. As classes da biblioteca padrão são amplamente envolvidas, bem como os novos tipos de dados que são criados aqui.

Negociação Bidirecional e de cobertura de posições no MetaTrader 5 Através do Painel de HedgeTerminal, Parte 1 Negociação Bidirecional e de cobertura de posições no MetaTrader 5 Através do Painel de HedgeTerminal, Parte 1

Este artigo descreve uma nova abordagem para cobertura de posições e desenha uma linha nos debates entre os usuários do MetaTrader 4 e MetaTrader 5 sobre esta matéria. Os algoritmos que fazem essa cobertura confiável são descritos em termos leigos e ilustrado com gráficos e diagramas simples. Este artigo é dedicado ao novo painel HedgeTerminal, que é essencialmente um terminal de negociação com todos os recursos dentro do MetaTrader 5. Usando HedgeTerminal e a virtualização das operações de negociação que ele oferece, posições podem ser gerenciados de forma semelhante ao MetaTrader 4.