Traçando linhas de tendência baseadas em fractais usando MQL4 e MQL5
Almat Kaldybay | 10 junho, 2015
Índice
- Introdução
- 1. Parâmetros de entrada, função DeInit() e a declaração inicial de variáveis
- 2. Busca pelos fractais mais próximos
- 3. Determinando os valores de preço e de tempo dos fractais
- 4. Criando objetos e editando suas propriedades. Redesenhando as linhas
- 5. Verificando o carregamento do histórico de barras
- 6. Sinais de rompimento de linhas de tendência, notificações push
- 7. Uso prático das linhas de tendência na negociação
- Conclusão
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:
- n - a variável é necessária para encontrar o fractal mais próximo conhecido usando o operador de loop for;
- 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:
- FractalDown[], FractalUp[]; - Declarando arrays de valores do tipo double para armazenar os valores do buffer do indicador iFractals;
- 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.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:
MQL4 | MQL5 |
---|---|
|
|
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:
MQL4 | MQL5 |
---|---|
|
|
2. Para a linha de resistência:
MQL4 | MQL5 |
---|---|
|
|
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:
- Determinar o preço de fechamento da barra e o preço da linha de tendência;
- Determinar as condições em que os preços rompem a linha de tendência;
- 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
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
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.