English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
20 sinais de negociação no MQL5

20 sinais de negociação no MQL5

MetaTrader 5Exemplos | 26 dezembro 2013, 15:32
6 843 0
Sergey Gritsay
Sergey Gritsay

Introdução

Os negociantes tentam encontrar regularidades no comportamento dos preços, se esforçam para criar regras e usam aquelas as quais eles terão uma boa chance para determinar um momento favorável de compra ou venda. Para criar um sistema totalmente automático, você precisa aprender como se informar sobre a chegada de tais momentos - os sinais de negociação.

Os sinais informam os negociantes sobre os pontos potenciais de entrada em uma posição, porém nem todos eles são obrigados a executar. Um critério adicional pode filtrar até mesmo a maioria dos sinais, mas não é significativo para nós. O tema do artigo é como programar os sinais de negociação mais populares no MQL5.


1. Quais sinais nós conhecemos?

Todos os métodos de determinação dos momentos de entrada no mercado podem ser divididos em vários tipos:

  • Interseção das médias móveis;
  • Ruptura de uma variação;
  • Saída da zona de sobrecompra/sobrevenda na base das taxas estocásticas;
  • Salto das bordas de um canal;
  • Ruptura das bordas de um canal;
  • Mudança de uma tendência.


2. Como codificá-lo melhor?

Existem várias maneiras de escrever um código; ele pode ser escrito dentro da OnStart(), OnTick() e as outras funções. Você pode encontrar informações mais detalhadas sobre elas na documentação neste site ou no guia do usuário inserido no MetaEditor; porém, este método não é eficaz e, às vezes, você precisa escrever as mesmas partes do código várias vezes. Por isso tomaremos um outro caminho - usaremos funções personalizadas que podem ser ativadas de qualquer parte do código do nosso programa.

Pela conveniência de usar as funções criadas, vamos combiná-las em um grupo separado como um arquivo de inclusão externo com o nome SignalTrade; ele será armazenado na pasta ...\MQL5\Include. Isso irá permitir uma fácil conexão deste módulo a quaisquer programas.

Apesar de todos os sinais parecerem diferentes, eles têm muita coisa em comum. Existem três variantes que podem ser recebidas a partir de uma função que gera os sinais:

  • sinal de compra;
  • sinal de venda;
  • sem sinal.

Então vamos criar uma enumeração que corresponde a esses sinais.

  • 1 - sinal de compra;
  • -1 - sinal de venda;
  • 0 - sem sinal.

Vamos escrever o protótipo da função que retorna um sinal. Divida nossa função em várias partes onde uma ou outra operação pode ser efetuada. As variáveis necessárias para o armazenamento dos dados são definidas e inicializadas no início da função. O carregamento e a verificação da informação necessária a partir do indicador criado será efetuada mais adiante. A verificação da informação é essencial para evitar consequências inesperadas do trabalho com dados e do programa inteiro.

Uma vez que a informação foi carregada e verificada, vá para a formação do sinal. Assim que o sinal for formado, saia da função e retorne o sinal obtido a ela como um dos valores mencionados acima.

int TradeSignal()
  {
   //--- zero means absence of signal
   int sig=0;
   
   //--- check the handles of indicators

   //--- if all the handles are invalid, create them

   //--- if the handles are valid, copy the values from indicators

   //--- check the copied data

   //--- in case of an error of copying, exit from the function

   //--- perform the indexation of the array as a timeseries

   //--- in case of an indexation error, exit from the function

   //--- check conditions and set the value for sig
 
   //--- return the trade signal
   return(sig);
  }


3. Exemplos dos 20 sinais de negociação

Usaremos diferentes indicadores para obter os sinais de negociação. No MQL5 os indicadores são ativados usando as funções especiais, por exemplo iMA, iAC, iMACD, iIchimoku, etc.; eles criam uma cópia do indicador técnico correspondente no cache global da plataforma do cliente. Se uma cópia do indicador com os mesmos parâmetros já existe, uma nova cópia não é criada, mas o contador de links para as cópias existentes aumenta.

Essas funções retornam o identificador da cópia correspondente do indicador. Além disso, usando esse identificador, você pode obter os dados calculados pelo indicador correspondente. Os dados da memória de armazenamento (buffer) correspondente (os indicadores técnicos contém os dados calculados em suas memórias de armazenamento (buffers) internas; o número deles pode variar de 1 a 5, dependendo do tipo do indicador) podem ser copiados para o programa MQL5 usando a função CopyBuffer().

Não é possível usar os dados de um indicador logo após sua criação, já que algum tempo é necessário para calcular os valores do indicador; então a melhor maneira é criar os identificadores dentro da OnInit(). A função iCustom() cria um indicador personalizado correspondente; e se a criação for bem sucedida, ela retorna o identificador do indicador. Os indicadores personalizados podem conter cerca de 512 memórias de armazenamento (buffers) do indicador cujo conteúdo pode também ser obtido usando a função CopyBuffer() e o identificador obtido.

Para cada sinal vamos criar uma função de acordo como nosso protótipo TradeSignal() e numerá-las na seguinte ordem: TradeSignal_01() - TradeSignal_20(). Vamos dar uma olhada detalhada na estrutura da função para formar um sinal usando o exemplo de um sinal baseado na intersecção de médias móveis; então iremos escrever as funções para os outros sinais de forma similar.

3.1. Interseção das médias móveis

Figura 1. A interseção de duas médias móveis

Figura 1. A interseção de duas médias móveis

Usando a função TradeSignal_01(), obteremos um sinal sobre a interseção de duas Médias Móveis (MM): a rápida com período 8 e a lenta com período 16.

Em nossa função fixaremos apenas o fato da interseção e retornaremos o valor do sinal correspondente para a função. De acordo com nossas regras e protótipo, a função será a seguinte:

int TradeSignal_01()
  {
//--- zero means that there is no signal
   int sig=0;

//--- check the handles of indicators
   if(h_ma1==INVALID_HANDLE)//--- if the handle is invalid
     {
      //--- create is again                                                      
      h_ma1=iMA(Symbol(),Period(),8,0,MODE_SMA,PRICE_CLOSE);
      //--- exit from the function
      return(0);
     }
   else //--- if the handle is valid
     {
      //--- copy value of the indicator to the array
      if(CopyBuffer(h_ma1,0,0,3,ma1_buffer)<3) //--- if the array of data is less than required
         //--- exit from the function
         return(0);
      //--- set the indexation in the array as in a timeseries                                   
      if(!ArraySetAsSeries(ma1_buffer,true))
         //--- in case of an indexation error, exit from the function
         return(0);
     }

   if(h_ma2==INVALID_HANDLE)//--- if the handle is invalid
     {
      //--- create it again                                                      
      h_ma2=iMA(Symbol(),Period(),16,0,MODE_SMA,PRICE_CLOSE);
      //--- exit from the function
      return(0);
     }
   else //--- if the handle is valid 
     {
      //--- copy values of the indicator to the array
      if(CopyBuffer(h_ma2,0,0,2,ma2_buffer)<2) //--- if there is less data than required
         //--- exit from the function
         return(0);
      //--- set the indexation in the array as in a timeseries                                   
      if(!ArraySetAsSeries(ma1_buffer,true))
         //--- in case of an indexation error, exit from the function
         return(0);
     }

//--- check the condition and set a value for the sig
   if(ma1_buffer[2]<ma2_buffer[1] && ma1_buffer[1]>ma2_buffer[1])
      sig=1;
   else if(ma1_buffer[2]>ma2_buffer[1] && ma1_buffer[1]<ma2_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

Agora, vamos olhar mais detalhadamente cada parte do código. Ao início da função definimos uma variável local que irá armazenar o tipo de sinal, e iniciá-lo com zero o que significa a ausência de sinal.

int sig=0;

Além disso, checaremos a validade do identificador; se o identificador é inválido então iremos criá-lo e sair da função, pois o cálculo do indicador leva algum tempo. Ele é implementado para evitar o erro de copiar dados da memória de armazenamento (buffer) do indicador.

   if(h_ma1==INVALID_HANDLE)//--- if the handle is invalid
     {
      //--- create it again                                                      
      h_ma1=iMA(Symbol(),Period(),8,0,MODE_SMA,PRICE_CLOSE);
      //--- exit from the function
      return(0);
     }

Se o identificador for válido, copie os dados do arranjo. Para analisar a situação, basta copiar os dados das últimas três barras da MM rápida e duas barras da lenta. Use a seguinte função para esta finalidade:

int  CopyBuffer(
   int       indicator_handle,     // handle of an indicator
   int       buffer_num,           // number of buffer of an indicator
   int       start_pos,            // where to start from 
   int       count,                // amount to be copied
   double    buffer[]              // an array to copy data to
   );

Verifique: se existe menos dados que o desejado, isso significa que ocorreu um erro de cópia; e a referência ao arranjo onde os dados deveriam ter sido armazenados irá gerar um erro. Para evitá-lo, saímos da função. Também precisamos configurar a indexação no arranjo como em uma série temporal; a seguinte função é destinada a ela:

bool  ArraySetAsSeries(
   void  array[],     // array by a link
   bool  set          // true means that the indexation order is reversed
   );

Se um erro ocorreu durante a indexação do arranjo, saia da função, caso contrário podemos obter resultados incorretos.

else //--- if the handle is valid 
     {
      //--- copy values of the indicator to the array
      if(CopyBuffer(h_ma1,0,0,3,ma1_buffer)<3) //--- if there is less data than required
         //--- exit from the function
         return(0);
      //--- set the indexation in the array like in a timeseries                                   
      if(!ArraySetAsSeries(ma1_buffer,true))
         //--- in case of an indexation error, exit from the function
         return(0);
     }

Agora, enquanto os indicadores são criados e toda a informação necessária é obtida, vamos proceder ao estágio principal - a formação de um sinal.

Para eliminar a oscilação do sinal na barra atual, analise apenas as barras fechadas 1 e 2.

Forme o sinal para compra. Para essa finalidade, pegue o valor da MM rápida na segunda barra e o compare ao valor da MM lenta na primeira barra; e compare o valor da MM rápida na primeira barra com o valor da MM lenta na segunda barra. Se o valor da MM rápida na segunda barra for menos que o valor da MM lenta na primeira barra, e o valor da MM rápida na primeira barra for maior que o valor da MM lenta na primeira barra, isso significa que a MM rápida cruzou a lenta de forma ascendente; esse é o nosso sinal para compra. Se nossa condição for verdadeira, então escreva 1 para a variável sig.

O sinal para venda é formado de modo semelhante. Se a MM rápida na segunda barra for maior que a MM lenta na primeira barra, e se a MM rápida na primeira barra for menor que MM lenta na primeira barra, isso significa um cruzamento descendente da MM lenta pela MM rápida. Se nossa condição for verdadeira, então escreva -1 para a variável sig. Se ambas as condições forem falsas significa que não existe sinal, então escrevemos o valor 0 para a variável sig. Agora que o sinais estão formados, retorne o tipo do sinal obtido para nossa função TradeSignal_01()

//--- check the condition and set a value for the sig
   if(ma1_buffer[2]<ma2_buffer[1] && ma1_buffer[1]>ma2_buffer[1])
      sig=1;
   else if(ma1_buffer[2]>ma2_buffer[1] && ma1_buffer[1]<ma2_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);

3.2. Interseção da linha principal e da linha de sinal do MACD

Figura 2. Interseção da linha principal e da linha de sinal do indicador MACD

Na função TradeSignal_02() obteremos o sinal sobre a interseção do sinal e da linha principal do MACD. Se a linha de sinal cruzar a linha principal de cima para baixo, esse é o sinal para compra. Se a linha de sinal cruzar a linha principal de baixo para cima, esse é o sinal para venda. Outros casos serão considerados como ausência de sinal.

int TradeSignal_02()
  {
   int sig=0;

   if(h_macd==INVALID_HANDLE)
     {
      h_macd=iMACD(Symbol(),Period(),12,26,9,PRICE_CLOSE);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_macd,0,0,2,macd1_buffer)<2)
         return(0);
      if(CopyBuffer(h_macd,1,0,3,macd2_buffer)<3)
         return(0);
      if(!ArraySetAsSeries(macd1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(macd2_buffer,true))
         return(0);
     }

//--- check the condition and set a value for sig
   if(macd2_buffer[2]>macd1_buffer[1] && macd2_buffer[1]<macd1_buffer[1])
      sig=1;
   else if(macd2_buffer[2]<macd1_buffer[1] && macd2_buffer[1]>macd1_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.3. Ruptura da variação do Canal de Preço

Figura 3. Ruptura das bordas inferior e superior do Canal de Preço

Na função TradeSignal_03() receberemos o sinal sobre uma ruptura das bordas inferior e superior do Canal de Preço.

Se o preço trespassar a borda superior do Canal de Preço e o preço for fixado sobre a borda, esse é o sinal para comprar. Se o preço ultrapassar a borda inferior do Canal de Preço e o preço for fixado sob esta borda, então esse é o sinal para vender. Outros casos serão considerados como ausência de sinal.

Diferente das duas funções anteriores, aqui precisamos de um arranjo para armazenar os preços de fechamento. Use a seguinte função para para obtê-los:

int  CopyClose(
   string           symbol_name,       // symbol name
   ENUM_TIMEFRAMES  timeframe,          // period
   int              start_pos,         // where to start from 
   int              count,             // amount to be copied
   double           close_array[]      // array for copying close prices to
   );
int TradeSignal_03()
  {
   int sig=0;

   if(h_pc==INVALID_HANDLE)
     {
      h_pc=iCustom(Symbol(),Period(),"Price Channel",22);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_pc,0,0,3,pc1_buffer)<3)
         return(0);
      if(CopyBuffer(h_pc,1,0,3,pc2_buffer)<3)
         return(0);
      if(CopyClose(Symbol(),Period(),0,2,Close)<2)
         return(0);
      if(!ArraySetAsSeries(pc1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(pc2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the conditions and set a value for sig
   if(Close[1]>pc1_buffer[2])
      sig=1;
   else if(Close[1]<pc2_buffer[2])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.4. Ruptura da variação do canal adaptativo ADX

Figura 4. A ruptura das bordas superior e inferior do canal adaptativo ADX

Usando a função TradeSignal_04() obteremos o sinal sobre uma ruptura das bordas inferior e superior do canal adaptativo ADX.

Se o preço trespassar a borda superior do canal adaptativo ADX e o preço de fechamento for fixado sobre a borda, esse é um sinal de compra. Se o preço trespassar a borda inferior do canal adaptativo ADX e o preço de fechamento for fixado sob a borda, então esse é um sinal de venda. Outros casos serão considerados como ausência de sinal.

int TradeSignal_04()
  {
   int sig=0;

   if(h_acadx==INVALID_HANDLE)
     {
      h_acadx=iCustom(Symbol(),Period(),"AdaptiveChannelADX",14);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_acadx,0,0,2,acadx1_buffer)<2)
         return(0);
      if(CopyBuffer(h_acadx,1,0,2,acadx2_buffer)<2)
         return(0);
      if(CopyClose(Symbol(),Period(),0,2,Close)<2)
         return(0);
      if(!ArraySetAsSeries(acadx1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(acadx2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for the sig
   if(Close[1]>acadx1_buffer[1])
      sig=1;
   else if(Close[1]<acadx2_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.5. Saída das zonas estocásticas de sobrecompra/sobrevenda

Figura 5. Cruzando os níveis de sobrecompra/sobrevenda pelo estocástico

Usando o TradeSignal_05() obteremos o sinal sobre a saída do estocástico das zonas de sobrecompra/sobrevenda; os níveis dessas zonas serão níveis com valores 80 e 20.

Compramos, enquanto o oscilador (%K ou %D) cai abaixo de um certo nível (normalmente, ele é 20) e então sobe sobre ele. Vendemos, enquanto o oscilador sobe acima de um certo nível (normalmente, ele é 80) e então cai abaixo dele.

int TradeSignal_05()
  {
   int sig=0;

   if(h_stoh==INVALID_HANDLE)
     {
      h_stoh=iStochastic(Symbol(),Period(),5,3,3,MODE_SMA,STO_LOWHIGH);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_stoh,0,0,3,stoh_buffer)<3)
         return(0);

      if(!ArraySetAsSeries(stoh_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(stoh_buffer[2]<20 && stoh_buffer[1]>20)
      sig=1;
   else if(stoh_buffer[2]>80 && stoh_buffer[1]<80)
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.6. Saída das zonas de sobrecompra/sobrevenda de RSI

Figura 6. Cruzando os níveis de sobrecompra e sobrevenda pelo indicador RSI

Usando o TradeSignal_06() obteremos o sinal sobre a saída do indicador RSI das zonas de sobrecompra/sobrevenda; os níveis para essas zonas são níveis com valores 70 e 30.

Compramos, enquanto RSI cai abaixo de um certo nível (normalmente, ele é 30) e então sobe acima dele. Vendemos, enquanto RSI sobe acima de um certo nível (normalmente, ele é 70) e então cai abaixo dele.

int TradeSignal_06()
  {
   int sig=0;

   if(h_rsi==INVALID_HANDLE)
     {
      h_rsi=iRSI(Symbol(),Period(),14,PRICE_CLOSE);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_rsi,0,0,3,rsi_buffer)<3)
         return(0);

      if(!ArraySetAsSeries(rsi_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(rsi_buffer[2]<30 && rsi_buffer[1]>30)
      sig=1;
   else if(rsi_buffer[2]>70 && rsi_buffer[1]<70)
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
 
3.7. Saída das zonas de sobrecompra/sobrevenda de CCI

Figura 7. Cruzando os níveis de sobrecompra e sobrevenda pelo indicador CCI

Usando o TradeSignal_07() obteremos o sinal sobre a saída do indicador CCI das zonas de sobrecompra/sobrevenda; os níveis para essas zonas são níveis com valores 100 e -100.

Compramos, enquanto CCI cai abaixo do nível -100 e então sobe acima dele. Vendemos, enquanto CCI sobe acima do nível 100 e então cai abaixo dele.

int TradeSignal_07()
  {
   int sig=0;

   if(h_cci==INVALID_HANDLE)
     {
      h_cci=iCCI(Symbol(),Period(),14,PRICE_TYPICAL);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_cci,0,0,3,cci_buffer)<3)
         return(0);

      if(!ArraySetAsSeries(cci_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(cci_buffer[2]<-100 && cci_buffer[1]>-100)
      sig=1;
   else if(cci_buffer[2]>100 && cci_buffer[1]<100)
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.8. Saída das zonas de sobrecompra/sobrevenda de Williams %

Figura 8. Cruzando os níveis de sobrecompra e sobrevenda pelo Williams % indicador

Usando a função TradeSignal_08() obteremos o sinal sobre a saída do indicador Williams % das zonas de sobrecompra/sobrevenda; os níveis para essas zonas são níveis com valores -20 e -80.

Compramos, enquanto Williams % cai abaixo do nível -80 e então sobe acima dele. Vendemos, enquanto Williams % sobe acima do nível -20 e então cai abaixo dele.

int TradeSignal_08()
  {
   int sig=0;

   if(h_wpr==INVALID_HANDLE)
     {
      h_wpr=iWPR(Symbol(),Period(),14);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_wpr,0,0,3,wpr_buffer)<3)
         return(0);

      if(!ArraySetAsSeries(wpr_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(wpr_buffer[2]<-80 && wpr_buffer[1]>-80)
      sig=1;
   else if(wpr_buffer[2]>-20 && wpr_buffer[1]<-20)
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }
3.9. Salto das bordas do Canal Bollinger

Figura 9. Salto do preço da borda do Canal Bollinger

Usando a função TradeSignal_09() obteremos o sinal quando o preço saltar das bordas do Canal Bollinger.

Se o preço trespassar ou tocar a borda superior do Bollinger e então retornar, esse é o sinal de venda. Se o preço trespassar ou tocar a borda inferior do Bollinger, então esse é o sinal de venda.

int TradeSignal_09()
  {
   int sig=0;

   if(h_bb==INVALID_HANDLE)
     {
      h_bb=iBands(Symbol(),Period(),20,0,2,PRICE_CLOSE);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_bb,1,0,2,bb1_buffer)<2)
         return(0);
      if(CopyBuffer(h_bb,2,0,2,bb2_buffer)<2)
         return(0);
      if(CopyClose(Symbol(),Period(),0,3,Close)<3)
         return(0);
      if(!ArraySetAsSeries(bb1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(bb2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[2]<=bb2_buffer[1] && Close[1]>bb2_buffer[1])
      sig=1;
   else if(Close[2]>=bb1_buffer[1] && Close[1]<bb1_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.10. Salto das bordas do canal de desvio padrão

Figura 10. Salto do preço das bordas do canal de desvio padrão

Usando a função TradeSignal_10() obteremos o sinal se o preço saltar das bordas do canal de desvio padrão.

Se o preço trespassar ou tocar a borda superior do canal de desvio padrão e então retornar, esse é o sinal de venda. Se o preço trespassar ou tocar a borda inferior do canal de desvio padrão, então esse é o sinal de venda.

int TradeSignal_10()
  {
   int sig=0;

   if(h_sdc==INVALID_HANDLE)
     {
      h_sdc=iCustom(Symbol(),Period(),"StandardDeviationChannel",14,0,MODE_SMA,PRICE_CLOSE,2.0);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_sdc,0,0,2,sdc1_buffer)<2)
         return(0);
      if(CopyBuffer(h_sdc,1,0,2,sdc2_buffer)<2)
         return(0);
      if(CopyClose(Symbol(),Period(),0,3,Close)<3)
         return(0);
      if(!ArraySetAsSeries(sdc1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(sdc2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[2]<=sdc2_buffer[1] && Close[1]>sdc2_buffer[1])
      sig=1;
   else if(Close[2]>=sdc1_buffer[1] && Close[1]<sdc1_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.11. Salto das bordas do canal de preço

Figura 11. O salto do preço das bordas do canal de preço

Usando a função TradeSignal_11() obteremos o sinal se o preço saltar das bordas do canal de preço.

Se o preço trespassar ou tocar a borda superior do canal de preço e então retornar, esse é o sinal de venda. Se o preço trespassar ou tocar a borda inferior do canal de preço, então esse é o sinal de compra.

int TradeSignal_11()
  {
   int sig=0;

   if(h_pc==INVALID_HANDLE)
     {
      h_pc=iCustom(Symbol(),Period(),"Price Channel",22);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_pc,0,0,4,pc1_buffer)<4)
         return(0);
      if(CopyBuffer(h_pc,1,0,4,pc2_buffer)<4)
         return(0);
      if(CopyClose(Symbol(),Period(),0,3,Close)<3)
         return(0);
      if(!ArraySetAsSeries(pc1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(pc2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[1]>pc2_buffer[2] && Close[2]<=pc2_buffer[3])
      sig=1;
   else if(Close[1]<pc1_buffer[2] && Close[2]>=pc1_buffer[3])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.12. Salto das bordas do canal de envelope

Figura 12. O salto do preço das bordas do canal de envelope

Usando a função TradeSignal_12() obteremos o sinal se o preço saltar das bordas do canal de envelope.

Se o preço trespassar ou tocar a borda superior do canal de envelope e então retornar, esse é o sinal de venda. Se o preço trespassar ou tocar a borda inferior do canal de envelope, então esse é o sinal de compra.

int TradeSignal_12()
  {
   int sig=0;

   if(h_env==INVALID_HANDLE)
     {
      h_env=iEnvelopes(Symbol(),Period(),28,0,MODE_SMA,PRICE_CLOSE,0.1);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_env,0,0,2,env1_buffer)<2)
         return(0);
      if(CopyBuffer(h_env,1,0,2,env2_buffer)<2)
         return(0);
      if(CopyClose(Symbol(),Period(),0,3,Close)<3)
         return(0);
      if(!ArraySetAsSeries(env1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(env2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[2]<=env2_buffer[1] && Close[1]>env2_buffer[1])
      sig=1;
   else if(Close[2]>=env1_buffer[1] && Close[1]<env1_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.13. Ruptura do Canal Donchian

Figura 13. Ruptura das bordas do Canal Donchian

Na função TradeSignal_13() obteremos o sinal quando o preço trespassar as bordas do Canal Donchian.

Se o preço trespassar a borda superior do Canal Donchian e o preço de fechamento for fixado acima da borda, esse é o sinal de compra. Se o preço trespassar a borda inferior do Canal Donchian e o preço de fechamento for fixado abaixo da borda, esse é o sinal de venda.

int TradeSignal_13()
  {
   int sig=0;

   if(h_dc==INVALID_HANDLE)
     {
      h_dc=iCustom(Symbol(),Period(),"Donchian Channels",24,3,-2);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_dc,0,0,3,dc1_buffer)<3)
         return(0);
      if(CopyBuffer(h_dc,1,0,3,dc2_buffer)<3)
         return(0);
      if(CopyClose(Symbol(),Period(),0,2,Close)<2)
         return(0);
      if(!ArraySetAsSeries(dc1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(dc2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[1]>dc1_buffer[2])
      sig=1;
   else if(Close[1]<dc2_buffer[2])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.14. Ruptura do Silver-Channel

Figura 14. Ruptura das bordas do Silver-Channel

Na função TradeSignal_14() obteremos o sinal quando o preço trespassar as bordas do Silver-Channel. O indicador Silver-Channel traça 8 bordas que podem também servir como níveis de suporte e resistência. Para obter o sinal usaremos 2 bordas médias.

Se o preço trespassar a borda superior do Silver-Channel e o preço de fechamento for fixado acima da borda, esse é o sinal de compra. Se o preço trespassar a borda inferior do Silver-Channel e o preço de fechamento for fixado abaixo da borda, esse é o sinal de venda.

int TradeSignal_14()
  {
   int sig=0;

   if(h_sc==INVALID_HANDLE)
     {
      h_sc=iCustom(Symbol(),Period(),"Silver-channels",26,38.2,23.6,0,61.8);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_sc,0,0,2,sc1_buffer)<2)
         return(0);
      if(CopyBuffer(h_sc,1,0,2,sc2_buffer)<2)
         return(0);
      if(CopyClose(Symbol(),Period(),0,3,Close)<3)
         return(0);
      if(!ArraySetAsSeries(sc1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(sc2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[2]<sc1_buffer[1] && Close[1]>sc1_buffer[1])
      sig=1;
   else if(Close[2]>sc2_buffer[1] && Close[1]<sc2_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.15. Ruptura do Canal Gallagher

Figura 15. Ruptura das bordas do Canal Gallagher

No canal TradeSignal_15() obteremos o sinal quando o preço trespassar as bordas do Canal Gallagher. O indicador do Canal Gallagher é desenhado pelos máximos e mínimos por 10 dias.

Se o preço trespassar a borda superior do Canal Gallagher e o preço de fechamento for fixado acima da borda, esse é o sinal de compra. Se o preço trespassar a borda inferior do Canal Gallagher e o preço de fechamento for fixado abaixo da borda, esse é o sinal de venda.

int TradeSignal_15()
  {
   int sig=0;

   if(h_gc==INVALID_HANDLE)
     {
      h_gc=iCustom(Symbol(),Period(),"PriceChannelGalaher");
      return(0);
     }
   else
     {
      if(CopyBuffer(h_gc,0,0,3,gc1_buffer)<3)
         return(0);
      if(CopyBuffer(h_gc,1,0,3,gc2_buffer)<3)
         return(0);
      if(CopyClose(Symbol(),Period(),0,2,Close)<2)
         return(0);
      if(!ArraySetAsSeries(gc1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(gc2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[1]>gc1_buffer[2])
      sig=1;
   else if(Close[1]<gc2_buffer[2])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.16. Mudança de tendência pelo NRTR

Figura 16. A identificação de uma mudança de tendência usando o indicador NRTR

Na função TradeSignal_16() obteremos o sinal quando a tendência NRTR mudar.

Se o indicador NRTR mostrar uma tendência crescente, esse é o sinal de compra. Se o NRTR mostrar uma tendência decrescente, esse é o sinal de venda.

int TradeSignal_16()
  {
   int sig=0;

   if(h_nrtr==INVALID_HANDLE)
     {
      h_nrtr=iCustom(Symbol(),Period(),"NRTR",40,2.0);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_nrtr,0,0,2,nrtr1_buffer)<2)
         return(0);
      if(CopyBuffer(h_nrtr,1,0,2,nrtr2_buffer)<2)
         return(0);
      if(!ArraySetAsSeries(nrtr1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(nrtr2_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(nrtr1_buffer[1]>0)
      sig=1;
   else if(nrtr2_buffer[1]>0)
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.17. Mudança de tendência pelo Alligator

Figura 17. Mudança de tendência pelo Alligator

Na função TradeSignal_17() obteremos o sinal quando a tendência Alligator mudar.

Se a mandíbula, os dentes e os lábios estiverem fechados e retorcidos, o Alligator dormirá ou já está dormindo. Quando ele dorme, sua fome aumenta; e quanto mais ele dorme, mais faminto ele fica quando acorda. A primeira coisa que ele faz quando acorda é abrir sua boca e bocejar. Então ele começa a farejar a comida - carne de um touro ou de um urso, e então ele começa a caçar. Assim que o Alligator comeu o bastante, ele perde seu interesse pelo preço dos alimentos (as linhas de balanço convergem); é hora de fixar a margem de lucro.

int TradeSignal_17()
  {
   int sig=0;

   if(h_al==INVALID_HANDLE)
     {
      h_al=iAlligator(Symbol(),Period(),13,0,8,0,5,0,MODE_SMMA,PRICE_MEDIAN);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_al,0,0,2,al1_buffer)<2)
         return(0);
      if(CopyBuffer(h_al,1,0,2,al2_buffer)<2)
         return(0);
      if(CopyBuffer(h_al,2,0,2,al3_buffer)<2)
         return(0);
      if(!ArraySetAsSeries(al1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(al2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(al3_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(al3_buffer[1]>al2_buffer[1] && al2_buffer[1]>al1_buffer[1])
      sig=1;
   else if(al3_buffer[1]<al2_buffer[1] && al2_buffer[1]<al1_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.18. Mudança de tendência pelo AMA

Figura 18. Mudança de tendência pelo AMA

Na função TradeSignal_18() obteremos o sinal quando a tendência AMA mudar.

Se o indicador AMA estiver direcionado para cima, esse é o sinal de compra. Se o AMA estiver direcionado para baixo, então esse é o sinal de venda.

int TradeSignal_18()
  {
   int sig=0;

   if(h_ama==INVALID_HANDLE)
     {
      h_ama=iAMA(Symbol(),Period(),9,2,30,0,PRICE_CLOSE);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_ama,0,0,3,ama_buffer)<3)
         return(0);
      if(!ArraySetAsSeries(ama_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(ama_buffer[2]<ama_buffer[1])
      sig=1;
   else if(ama_buffer[2]>ama_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.19. Mudança de cor do Oscilador Maravilhoso (Awesome Oscillator ou Oscilador de Bill Williams)

Figura 19. A identificação de uma mudança de tendência usando o indicador Awesome Oscillator

Na função TradeSignal_19() obteremos o sinal quando o a cor do histograma Awesome Oscillator mudar.

Uma das características do MQL5 é a possibilidade de criar memória de armazenamento (buffer) para os indicadores, onde se pode armazenar os índices das cores das linhas configurados nas propriedades #property indicator_colorN. Quando a cor do histograma Awesome Oscillator está verde, esse é o sinal de compra. Se a cor mudar para vermelho, esse o sinal de venda.

int TradeSignal_19()
  {
   int sig=0;

   if(h_ao==INVALID_HANDLE)
     {
      h_ao=iAO(Symbol(),Period());
      return(0);
     }
   else
     {
      if(CopyBuffer(h_ao,1,0,20,ao_buffer)<20)
         return(0);
      if(!ArraySetAsSeries(ao_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(ao_buffer[1]==0)
      sig=1;
   else if(ao_buffer[1]==1)
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.20. Mudança de tendência pelo Ichimoku

Figura 20. A identificação de uma mudança de tendência usando o indicador Ichimoku

Na função TradeSignal_20() obteremos o sinal quando a tendência Ichimoku mudar. Para essa finalidade iremos analisar a interseção das linhas Tenkan-sen e Kijun-sen.

O sinal de compra é gerado quando a linha Tenkan-sen cruza a Kijun-sen de baixo para cima. O cruzamento de cima para baixo é o sinal de venda.

int TradeSignal_20()
  {
   int sig=0;

   if(h_ich==INVALID_HANDLE)
     {
      h_ich=iIchimoku(Symbol(),Period(),9,26,52);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_ich,0,0,2,ich1_buffer)<2)
         return(0);
      if(CopyBuffer(h_ich,1,0,2,ich2_buffer)<2)
         return(0);
      if(!ArraySetAsSeries(ich1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(ich2_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(ich1_buffer[1]>ich2_buffer[1])
      sig=1;
   else if(ich1_buffer[1]<ich2_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }


4. Faça como um indicador

Agora, como já temos os blocos dos indicadores prontos, podemos começar a escrever um indicador que mostre os sinais na base de todos os métodos selecionados. Usando o modelo criado podemos implementar o recebimento de sinal de qualquer indicador; basta formular corretamente uma condição de sinal e adicioná-la ao código.

Vamos escrever um indicador com parâmetros embutidos inflexivelmente. Os sinais dos indicadores serão desenhados na forma de setas (seta para cima - compra, seta para baixo - venda, uma cruz - sem sinal) na parte direita do gráfico. Vamos pegar a fonte padrão Wingdings para desenhar as setas. Também precisamos criar várias outras funções para exibir a informação sobre os sinais no gráfico de um símbolo. Iremos combiná-las em um bloco separado como uma biblioteca que pode ser usada para escrever seus próprios programas através da adição de novas funções a ela. Vamos nomear a biblioteca LibFunctions.

No cabeçalho de nosso futuro indicador, escreva a conexão do arquivo com funções para gerar sinal, e a função importar que são necessárias para exibição gráfica de sinal, também declare variáveis no escape global que irão armazenar o tipo de sinal recebido do indicador.

//--- Connect necessary libraries of functions
#include 
//--- Import of functions from the LibFunctions library
#import "LibFunctions.ex5"
void SetLabel(string nm,string tx,ENUM_BASE_CORNER cn,ENUM_ANCHOR_POINT cr,int xd,int yd,string fn,int fs,double yg,color ct);
string arrow(int sig);
color Colorarrow(int sig);
#import
//+------------------------------------------------------------------+
//| Declare variables for storing signals of indicators              |
//+------------------------------------------------------------------+
int SignalMA;
int SignalMACD;
int SignalPC;
int SignalACADX;
int SignalST;
int SignalRSI;
int SignalCCI;
int SignalWPR;
int SignalBB;
int SignalSDC;
int SignalPC2;
int SignalENV;
int SignalDC;
int SignalSC;
int SignalGC;
int SignalNRTR;
int SignalAL;
int SignalAMA;
int SignalAO;
int SignalICH;

Como previamente mencionado, os indicadores são carregados para a plataforma apenas uma vez e os ponteiros (identificadores) para esses indicadores são criados; por essa razão vamos implementar sua criação na função OnInit() já que essa função é operada apenas uma vez no início do programa.

int OnInit()
  {
//--- create indicator handles
   h_ma1=iMA(Symbol(),Period(),8,0,MODE_SMA,PRICE_CLOSE);
   h_ma2=iMA(Symbol(),Period(),16,0,MODE_SMA,PRICE_CLOSE);
   h_macd=iMACD(Symbol(),Period(),12,26,9,PRICE_CLOSE);
   h_pc=iCustom(Symbol(),Period(),"Price Channel",22);
   h_acadx=iCustom(Symbol(),Period(),"AdaptiveChannelADX",14);
   h_stoh=iStochastic(Symbol(),Period(),5,3,3,MODE_SMA,STO_LOWHIGH);
   h_rsi=iRSI(Symbol(),Period(),14,PRICE_CLOSE);
   h_cci=iCCI(Symbol(),Period(),14,PRICE_TYPICAL);
   h_wpr=iWPR(Symbol(),Period(),14);
   h_bb=iBands(Symbol(),Period(),20,0,2,PRICE_CLOSE);
   h_sdc=iCustom(Symbol(),Period(),"StandardDeviationChannel",14,0,MODE_SMA,PRICE_CLOSE,2.0);
   h_env=iEnvelopes(Symbol(),Period(),28,0,MODE_SMA,PRICE_CLOSE,0.1);
   h_dc=iCustom(Symbol(),Period(),"Donchian Channels",24,3,-2);
   h_sc=iCustom(Symbol(),Period(),"Silver-channels",26,38.2,23.6,0,61.8);
   h_gc=iCustom(Symbol(),Period(),"PriceChannelGalaher");
   h_nrtr=iCustom(Symbol(),Period(),"NRTR",40,2.0);
   h_al=iAlligator(Symbol(),Period(),13,0,8,0,5,0,MODE_SMMA,PRICE_MEDIAN);
   h_ama=iAMA(Symbol(),Period(),9,2,30,0,PRICE_CLOSE);
   h_ao=iAO(Symbol(),Period());
   h_ich=iIchimoku(Symbol(),Period(),9,26,52);
   return(0);
  }

Todos os cálculos principais são efetuados na função OnCalculate(); lá colocaremos o restante do código do indicador.

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---assign the signal value to the variable
   SignalMA    = TradeSignal_01();
   SignalMACD  = TradeSignal_02();
   SignalPC    = TradeSignal_03();
   SignalACADX = TradeSignal_04();
   SignalST    = TradeSignal_05();
   SignalRSI   = TradeSignal_06();
   SignalCCI   = TradeSignal_07();
   SignalWPR   = TradeSignal_08();
   SignalBB    = TradeSignal_09();
   SignalSDC   = TradeSignal_10();
   SignalPC2   = TradeSignal_11();
   SignalENV   = TradeSignal_12();
   SignalDC    = TradeSignal_13();
   SignalSC    = TradeSignal_14();
   SignalGC    = TradeSignal_15();
   SignalNRTR  = TradeSignal_16();
   SignalAL    = TradeSignal_17();
   SignalAMA   = TradeSignal_18();
   SignalAO    = TradeSignal_19();
   SignalICH   = TradeSignal_20();

//--- draw graphical objects on the chart in the upper left corner
   int size=((int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS)/22);
   int i=0;
   int x=10;
   int y=0;
   int fz=size-4;

   y+=size;
   SetLabel("arrow"+(string)i,arrow(SignalMA),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalMA));
   x+=size;
   SetLabel("label"+(string)i,"Moving Average",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalMACD),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalMACD));
   x+=size;
   SetLabel("label"+(string)i,"MACD",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalPC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalPC));
   x+=size;
   SetLabel("label"+(string)i,"Price Channell",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalACADX),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalACADX));
   x+=size;
   SetLabel("label"+(string)i,"Adaptive Channel ADX",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalST),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalST));
   x+=size;
   SetLabel("label"+(string)i,"Stochastic Oscillator",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalRSI),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalRSI));
   x+=size;
   SetLabel("label"+(string)i,"RSI",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalCCI),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalCCI));
   x+=size;
   SetLabel("label"+(string)i,"CCI",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalWPR),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalWPR));
   x+=size;
   SetLabel("label"+(string)i,"WPR",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalBB),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalBB));
   x+=size;
   SetLabel("label"+(string)i,"Bollinger Bands",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalSDC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalSDC));
   x+=size;
   SetLabel("label"+(string)i,"StDevChannel",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalPC2),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalPC2));
   x+=size;
   SetLabel("label"+(string)i,"Price Channell 2",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalENV),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalENV));
   x+=size;
   SetLabel("label"+(string)i,"Envelopes",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalDC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalDC));
   x+=size;
   SetLabel("label"+(string)i,"Donchian Channels",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalSC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalSC));
   x+=size;
   SetLabel("label"+(string)i,"Silver-channels",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalGC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalGC));
   x+=size;
   SetLabel("label"+(string)i,"Galaher Channel",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalNRTR),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalNRTR));
   x+=size;
   SetLabel("label"+(string)i,"NRTR",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalAL),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalAL));
   x+=size;
   SetLabel("label"+(string)i,"Alligator",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalAMA),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalAMA));
   x+=size;
   SetLabel("label"+(string)i,"AMA",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalAO),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalAO));
   x+=size;
   SetLabel("label"+(string)i,"Awesome oscillator",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalICH),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalICH));
   x+=size;
   SetLabel("label"+(string)i,"Ichimoku Kinko Hyo",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);

   return(rates_total);
  }

Bem, nosso indicador está pronto. Ao final temos a seguinte figura no gráfico.



5. Faça como um Expert Advisor

De maneira similar podemos escrever um Expert Advisor que mostre o sinal do indicador no gráfico. Vamos implementar um sistema informativo com os elementos de controle gráfico. É possível escolher um indicador necessário e configurar seus parâmetros através da interface gráfica.


Não discutiremos a implementação da interface gráfica; você pode encontrar informação sobre ela no artigo Creating Active Control Panels in MQL5 for Trading.

Para mudar as configurações dos indicadores através de nossa interface gráfica, vamos aprimorar nossa biblioteca SignalTrade.mqh e nomeá-la SignalTradeExp.mqh.

Primeiramente, precisamos de variáveis adicionais para armazenar as configurações dos indicadores.

//--- input parameters Moving Average
int                periodma1=8;
int                periodma2=16;
ENUM_MA_METHOD     MAmethod=MODE_SMA;
ENUM_APPLIED_PRICE MAprice=PRICE_CLOSE;
//--- input parameters MACD
int                FastMACD=12;
int                SlowMACD=26;
int                MACDSMA=9;
ENUM_APPLIED_PRICE MACDprice=PRICE_CLOSE;
//--- input parameters Price Channel
int                PCPeriod=22;
//--- input parameters Adaptive Channel ADX
int                ADXPeriod=14;
//--- input parameters Stochastic Oscillator
int                SOPeriodK=5;
int                SOPeriodD=3;
int                SOslowing=3;
ENUM_MA_METHOD     SOmethod=MODE_SMA;
ENUM_STO_PRICE     SOpricefield=STO_LOWHIGH;
//--- input parameters RSI
int                RSIPeriod=14;
ENUM_APPLIED_PRICE RSIprice=PRICE_CLOSE;
//--- input parameters CCI
int                CCIPeriod=14;
ENUM_APPLIED_PRICE CCIprice=PRICE_TYPICAL;
//--- input parameters WPR
int                WPRPeriod=14;
//--- input parameters Bollinger Bands
int                BBPeriod=20;
double             BBdeviation=2.0;
ENUM_APPLIED_PRICE BBprice=PRICE_CLOSE;
//--- input parameters Standard Deviation Channel
int                SDCPeriod=14;
double             SDCdeviation=2.0;
ENUM_APPLIED_PRICE SDCprice=PRICE_CLOSE;
ENUM_MA_METHOD     SDCmethod=MODE_SMA;
//--- input parameters Price Channel 2
int                PC2Period=22;
//--- input parameters Envelopes
int                ENVPeriod=14;
double             ENVdeviation=0.1;
ENUM_APPLIED_PRICE ENVprice=PRICE_CLOSE;
ENUM_MA_METHOD     ENVmethod=MODE_SMA;
//--- input parameters Donchian Channels
int                DCPeriod=24;
int                DCExtremes=3;
int                DCMargins=-2;
//--- input parameters Silver-channels
int                SCPeriod=26;
double             SCSilvCh=38.2;
double             SCSkyCh=23.6;
double             SCFutCh=61.8;
//--- input parameters NRTR
int                NRTRPeriod   =  40;
double             NRTRK        =  2.0;
//--- input parameters Alligator
int                ALjawperiod=13;
int                ALteethperiod=8;
int                ALlipsperiod=5;
ENUM_MA_METHOD     ALmethod=MODE_SMMA;
ENUM_APPLIED_PRICE ALprice=PRICE_MEDIAN;
//--- input parameters AMA
int                AMAperiod=9;
int                AMAfastperiod=2;
int                AMAslowperiod=30;
ENUM_APPLIED_PRICE AMAprice=PRICE_CLOSE;
//--- input parameters Ichimoku Kinko Hyo
int                IKHtenkansen=9;
int                IKHkijunsen=26;
int                IKHsenkouspanb=52;

Substitua os valores constantes dos indicadores com as variáveis. O restante deve permanecer inalterado.

h_ma1=iMA(Symbol(),Period(),periodma1,0,MAmethod,MAprice);

Um ponto significativo é o uso econômico da memória do computador; quando mudar as configurações é necessário descarregar a cópia do indicador com as configurações antigas e carregar uma nova. Isso pode ser feito usando a seguinte função:

bool  IndicatorRelease(
   int       indicator_handle,     // indicator handle
   );
   if(id==CHARTEVENT_OBJECT_ENDEDIT && sparam=="PIPSetEditMA2")
     {
      periodma2=(int)ObjectGetString(0,"PIPSetEditMA2",OBJPROP_TEXT);
      ObjectSetString(0,"PIPSetEditMA2",OBJPROP_TEXT,(string)periodma2);
      //--- unload old copy of the indicator
      IndicatorRelease(h_ma2);
      //--- create new copy of the indicator
      h_ma2=iMA(Symbol(),Period(),periodma2,0,MAmethod,MAprice);
      ChartRedraw();
     }

Conclusão

Assim, aprendemos como ler as informações dos indicadores e como passá-las ao Expert Advisor. De tal maneira, você pode obter sinais de qualquer indicator.

Nota:

  • O arquivo dos indicadores SignalTrade.mq5, AdaptiveChannelADX.mq5, Donchian Channels.mq5, NRTR.mq5, Price Channel.mq5, PriceChannelGalaher.mq5, Silver-channels.mq5, StandardDeviationChannel.mq5 deverão ser copiados para a pasta ...\MQL5\Indicators.
  • O SignalTrade.mqh e SignalTradeExp.mqh incluem arquivos que deverão ser copiados para a pasta ...\MQL5\Include.
  • A biblioteca de funções LibFunctions.mq5 deverá ser copiada para a pasta ...\MQL5\Libraries.
  • O Expert Advisor ExpSignalTrade.mq5 deverá ser copiado para a pasta ...\MQL5\Experts.

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

Arquivos anexados |
indicators.zip (8.9 KB)
signaltrade.mqh (20.16 KB)
signaltradeexp.mqh (23.26 KB)
expsignaltrade.mq5 (165.84 KB)
signaltrade.mq5 (10.57 KB)
O protótipo do robô de negócio O protótipo do robô de negócio
Este artigo resume e sintetiza os princípios da criação de algoritmos e elementos dos sistemas de negócio. O artigo considera o planejamento do algoritmo de especialista. Como um exemplo, a classe CExpertAdvisor é considerada, o que pode ser usado para facilmente e rapidamente desenvolver sistemas de negócio.
Como escrever um indicador na base de um outro indicador Como escrever um indicador na base de um outro indicador
No MQL5 você pode escrever um indicador tanto do zero como baseado em outro indicador já existente, embutido no terminal do cliente ou um personalizado. E aqui você também tem dois modos - melhorar um indicador adicionando novos cálculos e estilos gráficos a ele, ou utilizar um indicador no terminal do cliente embutido ou um personalizado através das funções iCustom() ou IndicatorCreate().
Como criar o seu próprio limite móvel Como criar o seu próprio limite móvel
A regra básica do negociante - aumente o lucro, corte as despesas! Este artigo considera uma das técnicas básicas, permitindo seguir esta regra - mover o nível de parada de proteção (nível Stop Loss) após aumentar o lucro da posição, ou seja - nível do Limite móvel. Você encontrará o procedimento passo-a-passo para criar uma classe para o limite móvel nos indicadores SAR e NRTR. Todos poderão inserir este limite móvel em seus experts ou usá-los independentemente para controlar posições em suas contas.
Funções para gerenciamento de dinheiro em um conselheiro especialista Funções para gerenciamento de dinheiro em um conselheiro especialista
O desenvolvimento das estratégias de negócio foca principalmente em buscar padrões para entrar e sair do mercado, bem como manter posições. Se formos capazes de formalizar alguns padrões em regras para negociação automatizada, então, o negociante enfrenta o problema de cálculo do volume das posições, o tamanho das margens, bem como manter um nível seguro dos fundos de hipoteca para garantir posições abertas no modo automatizado. Neste artigo, usaremos a linguagem do MQL5 para construir exemplos simples para realizar estes cálculos.