20 sinais de negociação no MQL5
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
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
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso