English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Sistema de negociação simples com o uso de indicadores semáforo

Sistema de negociação simples com o uso de indicadores semáforo

MetaTrader 5Sistemas de negociação | 21 janeiro 2014, 13:48
6 311 0
Nikolay Kositsin
Nikolay Kositsin

Introdução

Indicadores semáforo ou sinal são detectores simples que indicam o momento para entrar ou sair do mercado. Caso houver um sinal de entrada na barra atual, uma etiqueta apropriada aparece em um gráfico de símbolo. Esta etiqueta pode então ser usada como condição para realização de uma negociação.

Há muitos indicadores desse tipo, mas a essência do sistema de negociação original com base nesses indicadores não foi modificada. Dessa forma, é uma boa ideia implementá-lo da forma mais simples e universal. Isto permitirá o uso posterior dos resultados obtidos ao trabalhar com quaisquer indicadores similares sem alterações significativas.

Figura 1. Indicador de sinal semáforo ASCtrend

Figura 1. Indicador de sinal semáforo ASCtrend

Figura 2. Indicador ASCtrend. Sinal de negociação para realização de um acordo

Figura 2. Sinal de negociação para realização de um acordo usando o indicador de sinal de semáforo ASCtrend


Exemplos de indicadores de sinal de semáforo típicos

Atualmente, há muitos desses indicadores na Base de códigos. Neste artigo, apenas forneceremos alguns links para as páginas adequadas:

Além dos indicadores de sinal de semáforo, há um grupo de indicadores de tendência de semáforo:

Figura 3. Sinais de negociação com o uso do indicador Heiken_Ashi_Smoothed

Figura 3. Indicador de tendência de semáforo

Figura 4. Sinal de negociação para realização de um acordo usando o indicador de tendência de semáforo Heiken Ashi Smoothed

Figura 4. Sinal de negociação para realização de um acordo usando o indicador de tendência de semáforo Heiken Ashi Smoothed

Sistemas de negociação que usam esses indicadores têm códigos um pouco diferentes para a obtenção de sinais de negociação, enquanto o código do Expert Advisor permanece quase inalterado.

Exemplos de indicadores de tendência de semáforo típicos

A base de códigos contém diversos indicadores desse tipo. Neste artigo, apenas forneceremos alguns links para as páginas adequadas:

Dados básicos para criação de um sistema de negociação:

  1. O indicador de semáforo com os parâmetros de entrada que devem ser apresentados no Expert Advisor.
  2. A lista de parâmetros adicionais de entrada de negociação do Expert Advisor:
    • um compartilhamento de recursos financeiros de depósito utilizados em uma negociação;
    • um tamanho de Stop Loss e Take Profit (os pedidos pendentes não devem ser utilizados em caso de valores nulos);
    • deslize (diferença máxima permitida entre preços de negociação estabelecidos e atuais);
    • índice da barra, a partir do qual os sinais de negociação serão recebidos;
    • permissões para abertura de posições curtas e longas;
    • permissões para fechamento forçado de posições curtas e longas de acordo com os sinais do indicador.

É evidente que seria muito mais conveniente dar ordens para a realização de negociações usando funções universais de negociação. Essas funções são muito complexas e deveriam ser agrupadas em um arquivo de biblioteca distinto para tonar o código do aplicativo o mais fácil possível.

O código do Expert Advisor que implementa o sistema de negociação de semáforo:

//+------------------------------------------------------------------+
//|                                                 Exp_ASCtrend.mq5 |
//|                             Copyright © 2011,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+
#property copyright "Copyright © 2011, Nikolay Kositsin"
#property link      "farria@mail.redcom.ru"
#property version   "1.00"
//+----------------------------------------------+
//| Expert Advisor indicator input parameters    |
//+----------------------------------------------+
input double MM=-0.1;             // Share of a deposit in a deal, negative values - lot size
input int    StopLoss_=1000;      // Stop loss in points
input int    TakeProfit_=2000;    // Take profit in points
input int    Deviation_=10;       // Max. price deviation in points
input bool   BuyPosOpen=true;     // Permission to buy
input bool   SellPosOpen=true;    // Permission to sell
input bool   BuyPosClose=true;    // Permission to exit long positions
input bool   SellPosClose=true;   // Permission to exit short positions
//+----------------------------------------------+
//| ASCtrend indicator input parameters          |
//+----------------------------------------------+
input ENUM_TIMEFRAMES InpInd_Timeframe=PERIOD_H1; // ASCtrend indicator time frame
input int  RISK=4;                               // Risk level
input uint SignalBar=1;                          // Bar index for getting an entry signal
//+----------------------------------------------+

int TimeShiftSec;
//---- declaration of integer variables for the indicators handles
int InpInd_Handle;
//---- declaration of integer variables of the start of data calculation
int min_rates_total;
//+------------------------------------------------------------------+
//| Trading algorithms                                               | 
//+------------------------------------------------------------------+
#include <TradeAlgorithms.mqh>
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---- getting ASCtrend indicator handle
   InpInd_Handle=iCustom(Symbol(),InpInd_Timeframe,"ASCtrend",RISK);
   if(InpInd_Handle==INVALID_HANDLE) Print(" Failed to get handle of ASCtrend indicator");

//---- initialization of a variable for storing a chart period in seconds  
   TimeShiftSec=PeriodSeconds(InpInd_Timeframe);

//---- initialization of variables of the start of data calculation
   min_rates_total=int(3+RISK*2+SignalBar);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//----
   GlobalVariableDel_(Symbol());
//----
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---- checking the number of bars to be enough for calculation
   if(BarsCalculated(InpInd_Handle)<min_rates_total) return;
   
//---- uploading history for IsNewBar() and SeriesInfoInteger() functions normal operation  
   LoadHistory(TimeCurrent()-PeriodSeconds(InpInd_Timeframe)-1,Symbol(),InpInd_Timeframe);

//---- declaration of local variables
   double DnVelue[1],UpVelue[1];
//---- declaration of static variables
   static bool Recount=true;
   static bool BUY_Open=false,BUY_Close=false;
   static bool SELL_Open=false,SELL_Close=false;
   static datetime UpSignalTime,DnSignalTime;
   static CIsNewBar NB;

//+----------------------------------------------+
//| Searching for deals performing signals       |
//+----------------------------------------------+
   if(!SignalBar || NB.IsNewBar(Symbol(),InpInd_Timeframe) || Recount) // checking for a new bar
     {
      //---- zeroing out trading signals
      BUY_Open=false;
      SELL_Open=false;
      BUY_Close=false;
      SELL_Close=false;
      Recount=false;

      //---- copy newly appeared data into the arrays
      if(CopyBuffer(InpInd_Handle,1,SignalBar,1,UpVelue)<=0) {Recount=true; return;}
      if(CopyBuffer(InpInd_Handle,0,SignalBar,1,DnVelue)<=0) {Recount=true; return;}

      //---- getting buy signals
      if(UpVelue[0] && UpVelue[0]!=EMPTY_VALUE)
        {
         if(BuyPosOpen) BUY_Open=true;
         if(SellPosClose) SELL_Close=true;
         UpSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec;
        }

      //---- getting sell signals
      if(DnVelue[0] && DnVelue[0]!=EMPTY_VALUE)
        {
         if(SellPosOpen) SELL_Open=true;
         if(BuyPosClose) BUY_Close=true;
         DnSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec;
        }

      //---- searching for the last trading direction for getting positions closing signals
      //if(!MQL5InfoInteger(MQL5_TESTING) && !MQL5InfoInteger(MQL5_OPTIMIZATION)) //if execution is set to "Random delay" in the Strategy Tester 
      if((BuyPosOpen && BuyPosClose || SellPosOpen && SellPosClose) && (!BUY_Close && !SELL_Close))
        {
         int Bars_=Bars(Symbol(),InpInd_Timeframe);

         for(int bar=int(SignalBar+1); bar<Bars_; bar++)
           {
            if(SellPosClose)
              {
               if(CopyBuffer(InpInd_Handle,1,bar,1,UpVelue)<=0) {Recount=true; return;}
               if(UpVelue[0]!=0 && UpVelue[0]!=EMPTY_VALUE)
                 {
                  SELL_Close=true;
                  break;
                 }
              }

            if(BuyPosClose)
              {
               if(CopyBuffer(InpInd_Handle,0,bar,1,DnVelue)<=0) {Recount=true; return;}
               if(DnVelue[0]!=0 && DnVelue[0]!=EMPTY_VALUE)
                 {
                  BUY_Close=true;
                  break;
                 }
              }
           }
        }
     }

//+----------------------------------------------+
//| Performing deals                             |
//+----------------------------------------------+
//---- Closing a long position
   BuyPositionClose(BUY_Close,Symbol(),Deviation_);

//---- Closing a short position   
   SellPositionClose(SELL_Close,Symbol(),Deviation_);

//---- Buying
   BuyPositionOpen(BUY_Open,Symbol(),UpSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_);

//---- Selling
   SellPositionOpen(SELL_Open,Symbol(),DnSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_);
//----
  }
//+------------------------------------------------------------------+

O código para a realização desta ideia é muito simples e claro. Entretanto, alguns detalhes devem ser esclarecidos.

O período do gráfico utilizado por um indicador de sinal e por um Expert Advisor é fixado à variável de entrada InpInd_Timeframe do Expert Advisor. Assim, a mudança em um gráfico, no qual um Expert Advisor está localizado, não altera este parâmetro para o Expert Advisor.

A função IsNewBar() necessária para determinar o momento de chegada de uma nova barra é implementada como uma classe posicionada no arquivo TradeAlgorithms.mqh. Isso permite usar facilmente qualquer número dessas funções no código através do estabelecimento de uma variável CIsNewBar individual estática para cada uma delas.

As variáveis UpSignalTime e DnSignalTime são usadas para armazenar e transferir o tempo, após o qual é possível realizar a próxima negociação depois da anterior, às funções de negociação. Em nosso caso, este recurso é utilizado para evitar a realização de diversos acordos em uma mesma direção da mesma barra (ao realizar um acordo, a função de negociação armazena o tempo do fim da barra atual e não realiza novos acordos na mesma direção até aquele momento).

O bloco "Buscando a última direção de negociação para obter sinais para fechamento de posições" na função OnTick() é necessário para o recebimento de sinais de fechamento de posições nas barras sem sinais de negociação. Em caso de operação normal de um Expert Advisor, isso não é necessário. Mas em caso de falha na conexão com a Internet, é muito possível que um novo sinal de negociação seja perdido. Não é muito boa ideia entrar no mercado post factum, mas fechar as posições abertas seria uma jogada inteligente.

Utilizar o sistema de negociação com outros indicadores de sinal de semáforo

Agora, se houver necessidade de usar este código com outro indicador de sinal de semáforo, as seguintes ações devem ser realizadas:

  1. Substituir os dados do indicador anterior pelos parâmetros necessários do novo indicador nos parâmetros de entrada de um Expert Advisor.
  2. Alterar o código de obtenção do handle do indicador no bloco OnInit().
  3. Determinar os índices dos buffers do indicador, utilizados para armazenar sinais de negociação de compra e venda a partir do código do indicador, e inseri-los adequadamente nas chamadas da função CopyBuffer() no bloco OnTick(). Neste caso, são usados os buffers zero e primeiro do indicador.
  4. Alterar a inicialização da variável de ponto de início da inicialização do cálculo de dados (min_rates_total) em um Expert Advisor de acordo com o código do indicador.
  5. Alterar o bloco "Buscando a última direção de negociação para obter sinais para fechamento de posições" na função OnTick() de acordo com o código do indicador.

Utilizar o sistema de negociação com outros indicadores de tendência de semáforo

Ao utilizar este sistema de negociação com o indicador de tendência de semáforo, o código do Expert Advisor foi alterado um pouco no bloco para determinação de sinais para negociações da função OnTick(). Por exemplo, o código terá o aspecto abaixo para o Expert Advisor baseado no indicador FiboCandles:

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---- checking the number of bars to be enough for calculation
   if(BarsCalculated(InpInd_Handle)<min_rates_total) return;
   
//---- uploading history for IsNewBar() and SeriesInfoInteger() functions  
   LoadHistory(TimeCurrent()-PeriodSeconds(InpInd_Timeframe)-1,Symbol(),InpInd_Timeframe);

//---- declaration of local variables
   double TrendVelue[2];
//---- declaration of static variables
   static bool Recount=true;
   static bool BUY_Open=false,BUY_Close=false;
   static bool SELL_Open=false,SELL_Close=false;
   static datetime UpSignalTime,DnSignalTime;
   static CIsNewBar NB;

//+----------------------------------------------+
//| Searching for deals performing signals       |
//+----------------------------------------------+
   if(!SignalBar || NB.IsNewBar(Symbol(),InpInd_Timeframe) || Recount) // checking for a new bar
     {
      //---- zeroing out trading signals
      BUY_Open=false;
      SELL_Open=false;
      BUY_Close=false;
      SELL_Close=false;
      Recount=false;

      //---- copy the newly obtained data into the arrays
      if(CopyBuffer(InpInd_Handle,4,SignalBar,2,TrendVelue)<=0) {Recount=true; return;}

      //---- getting buy signals
      if(TrendVelue[0]==1 && TrendVelue[1]==0)
        {
         if(BuyPosOpen) BUY_Open=true;
         if(SellPosClose)SELL_Close=true;
         UpSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec;
        }

      //---- getting sell signals
      if(TrendVelue[0]==0 && TrendVelue[1]==1)
        {
         if(SellPosOpen) SELL_Open=true;
         if(BuyPosClose) BUY_Close=true;
         DnSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec;
        }

      //---- searching for the last trading direction for getting positions closing signals
      //if(!MQL5InfoInteger(MQL5_TESTING) && !MQL5InfoInteger(MQL5_OPTIMIZATION)) //if execution is set to "Random delay" in the Strategy Tester 
        {
         if(SellPosOpen && SellPosClose  &&  TrendVelue[1]==0) SELL_Close=true;
         if(BuyPosOpen  &&  BuyPosClose  &&  TrendVelue[1]==1) BUY_Close=true;
        }
     }

//+----------------------------------------------+
//| Performing deals                             |
//+----------------------------------------------+
//---- Closing a long position
   BuyPositionClose(BUY_Close,Symbol(),Deviation_);

//---- Closing a short position   
   SellPositionClose(SELL_Close,Symbol(),Deviation_);

//---- Buying
   BuyPositionOpen(BUY_Open,Symbol(),UpSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_);

//---- Selling
   SellPositionOpen(SELL_Open,Symbol(),DnSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_);
//----
  }

Neste caso, os sinais de negociação são recebidos a partir de um único buffer de indicador de cor (que contém índices de cor). Os dados deste buffer podem ter somente dois valores: 0 - para mercado crescente e 1 - para decrescente. O código do bloco "Buscando a última direção de negociação para obter sinais para fechamento de posições" tornou-se o mais simples possível visto que a direção de tendência em qualquer barra pode ser recebida diretamente a partir da célula adequada do buffer do indicador.

No bloco "realizando negociações" as funções de fechamento de posições vão primeiro, seguidas pelas funções de abertura. Em caso de sequência oposta, será possível fechar apenas as negociações em uma barra. Você não poderá abri-las simultaneamente ao realizar testes no modo "apenas preços Open"! Dessa forma, os resultados de negociação serão seriamente interrompidos.


Teste do sistema de negociação

Antes de passarmos ao teste do sistema de negociação, um detalhe importante deve ser esclarecido. Caso a variável de entrada SignalBar seja igual a zero, o Expert Advisor obterá negociações realizando sinais da barra atual. Mas o sinal da barra atual não é confiável para indicar a mudança da tendência que se moveu na direção oposta a este sinal na barra anterior. Os sinais da barra atual podem aparecer e desaparecer, enquanto que uma tendência pode se mover na direção contrária a esses sinais por muito tempo. Isto pode ser facilmente percebido caso um Expert Advisor seja testado em todos os ticks com visualização habilitada e a variável SignalBar seja igual a zero. A visualização da operação do indicador ASCtrend apresenta uma evidência muito clara desse fato no caso em análise.

Novamente, apenas o modo "Cada tick" é adequado para uma otimização de Expert Advisor com um sinal recebido da barra atual. Caso ele seja recebido de qualquer barra que já tenha sido fechada, o modo "apenas preços Open" já é suficiente. Isso acelera muito a análise de comportamento do sistema de negociação sem qualquer perda considerável de qualidade.

Assim, é melhor não usar sinais da barra atual para testar e otimizar esses sistemas de negociação!

Então, vamos testar o Expert Advisor com parâmetros padrão em EUR/USD desde o início do ano até o início de dezembro:

Figura 5. Resultados de teste do Expert Advisor Exp_ASCtrend com parâmetros padrão em EUR/USD H1

Figura 5. Resultados de teste do Expert Advisor Exp_ASCtrend com parâmetros padrão em EUR/USD H1

Após alterar um pouco as configurações do Expert Advisor no Provador de Estratégia, podemos encontrar a combinação mais adequada de parâmetros de Expert Advisor para dados históricos existentes muito facilmente:

Figura 6. Resultados de teste do Expert Advisor Exp_ASCtrend após a otimização com melhores parâmetros em EUR/USD H1

Figura 6. Resultados de teste do Expert AdvisorExp_ASCtrend após a otimização com melhores parâmetros em EUR/USD H1

O processo de otimização do sistema de negociação não possui quaisquer peculiaridades. Esta é a razão pela qual apresentaremos um único link para o artigo que descreve este processo em detalhes: "MQL5: Guia de teste e otimização de Expert Advisors em MQL5".

É claro que seria ingênuo esperar lucros expressivos com um sistema de negociação tão simples. Mas, é bastante possível conseguir bons resultados no caso deste sistema semi-automático ser habilmente manuseado e ser regularmente sintonizado de acordo com o comportamento atual do mercado.

Por exemplo, havia uma tendência crescente no gráfico EUR/USD H12 em 2011, de janeiro a maio. E isso era facilmente detectável nas primeiras etapas:

Figura 7. Gráfico EUR/USD H12 (janeiro/maio de 2011)

Figura 7. Gráfico EUR/USD H12 (janeiro/maio de 2011)

Seria interessante testar o Expert Advisor neste intervalo de tempo com as configurações padrão, somente a possibilidade de comprar e o uso de apenas 5% de um depósito (MM=0.05). Aqui estão os resultados do Expert Advisor com esses parâmetros testado no gráfico H1:

Figura 8. Resultados de teste do Expert Advisor Exp_ASCtrend com parâmetros padrão em EUR/USD H1 para janeiro-maio de 2011 (apenas posições longas, MM=0.05)

Figura 8. Resultados de teste do Expert Advisor Exp_ASCtrend com parâmetros padrão em EUR/USD H1 para janeiro-maio de 2011 (apenas posições longas, MM=0.05)

É claro que, neste caso, um negociador é totalmente responsável pela seleção de uma direção de negociação. Mas se lembrarmos que isso deve ser feito com o uso de grandes gráficos de período de tempo, dificilmente encontraremos qualquer dificuldade.


Modificação do módulo de negociação para utilizá-lo com outro indicador

Este artigo poderia terminar aqui, mas o MetaEditor implementou a possibilidade de gerar Expert Advisors com base em módulos de negociação prontos para uso. O processo de criação desses módulos, considerando todo o material apresentado aqui, é muito complexo e requer um estudo separado. Por essa razão, o nosso foco será os módulos de criação já criados que são completamente análogos aos sistemas de negociação que foram sugeridos. E apenas após isso é que passaremos aos detalhes da modificação desses módulos de acordo com os indicadores de sinal específicos, evitando detalhamento desnecessário.

Vamos supor que já tenhamos a coleção de módulos de negociação para sistemas de sinal de semáforo (MySignals.zip) e desejamos criar o módulo análogo para qualquer indicador específico. Como exemplo, vamos usar o indicador BykovTrendSignal.mq5, que é um indicador de sinal de semáforo típico. Primeiramente, devemos encontrar o mais análogo ao indicador nesta coleção (indicators.zip). Visualmente, determinamos que o primeiro indicador deste artigo (ASCtrend) é o mais similar a ele. Assim, utilizaremos o módulo de negociação deste indicador para a modificação.

Considerando o uso dele no código de programa requerido, o próprio indicador (BykovTrend) possui um conjunto de parâmetros de entrada:

//+----------------------------------------------+
//| Indicator input parameters                   |
//+----------------------------------------------+
input int RISK=3;
input int SSP=9;
//+----------------------------------------------+

E nós precisamos dos índices dos buffers de indicador utilizados para armazenar os sinais para realização de negociações. Em nosso caso, ele são: 0 - para sinais de venda e 1 - para sinais de compra.

Agora que sabemos qual módulo deve ser usado para a modificação, copiamos ele na pasta \MQL5\Include\Expert\Signal\MySignals\ com o nome de arquivo BykovTrendSignal.mqh e o abrimos no MetaEditor. Há uma expressão "ASCtrend" (o nome do indicador anterior) regularmente encontrada no código utilizado. Ela deve ser substituída pelo nome do novo indicador - "BykovTrend". Para fazer isso, pressione as teclas "Ctrl" e "H" simultaneamente e faça a modificação necessária:

Substituir o nome do indicador no código do módulo de negociação

Figura 9. Substituir o nome do indicador no código do módulo de negociação

A próxima etapa do nosso trabalho é a mais meticulosa. Temos que substituir tudo o que diz respeito aos parâmetros de entrada do indicador no código do módulo de negociação. O processo é muito similar ao que foi apresentado no artigo "MQL5 Wizard: Como criar um módulo de sinais de negociação".

Primeiramente, devemos fazer algumas mudanças no bloco comentado da descrição de classe de sinais de negociação do MQL5 Wizard:

//+----------------------------------------------------------------------+
//| Description of the class                                             |
//| Title=The signals based on BykovTrend indicator                      |
//| Type=SignalAdvanced                                                  |
//| Name=BykovTrend                                                      |
//| Class=CBykovTrendSignal                                              |
//| Page=                                                                |
//| Parameter=BuyPosOpen,bool,true,Permission to buy                     |
//| Parameter=SellPosOpen,bool,true,Permission to sell                   |
//| Parameter=BuyPosClose,bool,true,Permission to exit a long position   |
//| Parameter=SellPosClose,bool,true,Permission to exit a short position |
//| Parameter=Ind_Timeframe,ENUM_TIMEFRAMES,PERIOD_H1,Timeframe          |
//| Parameter=RISK,int,4,Risk level                                      |
//| Parameter=SSP,int,9,SSP                                              |
//| Parameter=SignalBar,uint,1,Bar index for entry signal                |
//+----------------------------------------------------------------------+
//--- wizard description end
//+----------------------------------------------------------------------+
//| CBykovTrendSignal class.                                             |
//| Purpose: Class of generator of trade signals based on                |
//| BykovTrend indicator https://www.mql5.com/ru/code/497/.               |
//|             Is derived from the CExpertSignal class.                 |
//+----------------------------------------------------------------------+

Ambos os indicadores contém a mesma variável de entrada RISK (risco). Dessa forma, ela pode ser mantida. Mas o valor padrão é diferente para esses indicadores. Na realidade, esta diferença não é expressiva e ele pode permanecer inalterado. A linha de comentário da variável SSP foi adicionada:

//| Parameter=SSP,int,9,SSP                                    |

E o link para o indicador Base de códigos foi substituído:

//| Purpose: Class of generator of trade signals based on      |
//| BykovTrend values https://www.mql5.com/ru/code/497/.        |

Agora, tudo o que se relaciona às mudanças dos parâmetros de entrada deve ser refletido na descrição da classe de sinais de negociação CBykovTrendSignal. Nós temos a linha da nova declaração de variável de classe global m_SSP nos parâmetros de configuração:

   uint              m_SSP;              // SSP

E a linha da nova declaração de parâmetros de configuração de método de instalação SSP():

   void               SSP(uint value)                         { m_SSP=value;              } 

Tudo que se relaciona à variável de entrada RISK no módulo de sinais de negociação que criarmos é equivalente ao módulo de entrada e, dessa forma, não há mudanças nos blocos de módulo de negociação atuais ou em quaisquer outros.

Agora, passamos ao construtor de classe CBykovTrendSignal::CBykovTrendSignal(). A inicialização de uma nova variável deve ser adicionada a este bloco:

   m_SSP=4;

O processo de verificação de funcionamento correto da nova variável deve ser realizado no bloco de verificação de parâmetros de configuração BykovTrendSignal::ValidationSettings():

   if(m_SSP<=0)
     {
      printf(__FUNCTION__+": SSP must be above zero");
      return(false);
     }

Após isso, podemos passar ao bloco de inicialização do indicador BykovTrend - BykovTrendSignal::InitBykovTrend(). O novo indicador tem um número diferente de variáveis de entrada e, assim, a dimensão da série declarada de parâmetros de entrada também será diferente:

//--- setting the indicator parameters
   MqlParam parameters[3];

Em nosso caso, precisamos de uma dimensão para o nome da string do indicador e mais duas para os seus parâmetros de entrada.

Agora temos que inicializar uma nova célula das séries de parâmetros de entrada, indicando o tipo de variável que será armazenado nela:

   parameters[2].type=TYPE_INT;
   parameters[2].integer_value=m_SSP;

Após isso, mude o número de variáveis de entrada para 3 neste bloco na chamada para a inicialização do indicador:

//--- object initialization   
   if(!m_indicator.Create(m_symbol.Name(),m_Ind_Timeframe,IND_CUSTOM,3,parameters))

O número de buffers no indicador permanece o mesmo e igual a dois. Assim, em nosso caso, não há necessidade de alterar nada na linha de inicialização de número de buffers do indicador:

//--- number of buffers
   if(!m_indicator.NumBuffers(2))  return(false);

Cada um dos indicadores ASCtrend e BykovTrend têm dois buffers. As funções dos buffers são completamente similares. O buffer zero é usado para armazenar sinais de venda, enquanto que o buffer que tem índica 1 é usado para armazenar sinais de compra. Assim, não há necessidade de alterar nada nos blocos de funções para entrada de sinais de negociação CBykovTrendSignal::LongCondition() e CBykovTrendSignal::ShortCondition() e o trabalho de modificação do módulo de sinais de negociação pode ser considerado completo.

Mas, em geral, todos os indicadores de semáforo são diferentes e, assim, esses blocos para indicadores de semáforo diferentes podem ser consideravelmente diferentes uns dos outros. O arquivo de módulo de negociação MySignals.zip e o arquivo Indicators.zip adequado contêm quantidades suficientes de exemplos para a criação de vários indicadores. Após um exame, é possível encontrar os detalhes do processo de substituição e possíveis versões de código para isso.

Agora, vamos focar na variável de entrada Ind_Timeframe do módulo de sinais de negociação. Esta variável permite baixar um período de tempo apropriado no indicador. Entretanto, o Expert Advisor que foi gerado opera no período de tempo para o qual foi designado. Isso significa que, para proporcionar uma operação normal de módulo, o período de tempo da variável de entrada Ind_Timeframe nunca deve exceder um período do gráfico em que o Expert Advisor opera.

Finalmente, vamos revelar outra peculiaridade da criação de módulos de sinais de negociação. Às vezes, enumerações personalizadas são implementadas no código de indicador básico como os tipos para as variável de entrada do módulo. Por exemplo, a enumeração personalizada Smooth_Method é utilizada como um tipo de variável MA_SMethod para o indicador Candles_Smoothed:

//+-----------------------------------+
//|  Declaration of enumerations      |
//+-----------------------------------+
enum Smooth_Method
  {
   MODE_SMA_,  // SMA
   MODE_EMA_,  // EMA
   MODE_SMMA_, // SMMA
   MODE_LWMA_, // LWMA
   MODE_JJMA,  // JJMA
   MODE_JurX,  // JurX
   MODE_ParMA, // ParMA
   MODE_T3,    // T3
   MODE_VIDYA, // VIDYA
   MODE_AMA,   // AMA
  }; */
//+----------------------------------------------+
//| Indicator input parameters                   |
//+----------------------------------------------+
input Smooth_Method MA_SMethod=MODE_LWMA; // Smoothing method
input int MA_Length=30;                   // Smoothing depth                    
input int MA_Phase=100;                   // Smoothing parameter
                                          // for JJMA varying within the range -100 ... +100,
                                          // for VIDIA it is a CMO period, for AMA it is a slow average period
//+----------------------------------------------+

Neste caso, variáveis de entrada desse tipo e todos os elementos associados no módulo de sinais de negociação (Candles_SmoothedSignal.mqh) devem ser modificados para as variáveis do tipo int ou uint. Além disso, o procedimento inverso de enumerações personalizadas até os parâmetros de entrada do Expert Advisor e substituição dos tipos de variável de entrada necessários (ExpM_Candles_Smoothed Expert Advisor) devem ser realizados para facilitar o uso dessas variáveis de entrada no código que já foi gerado do Expert Advisor pronto:

//+------------------------------------------------------------------+
//|  Declaration of enumerations                                     |
//+------------------------------------------------------------------+
enum Smooth_Method
  {
   MODE_SMA_,  // SMA
   MODE_EMA_,  // EMA
   MODE_SMMA_, // SMMA
   MODE_LWMA_, // LWMA
   MODE_JJMA,  // JJMA
   MODE_JurX,  // JurX
   MODE_ParMA, // ParMA
   MODE_T3,    // T3
   MODE_VIDYA, // VIDYA
   MODE_AMA,   // AMA
  };
//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
//--- inputs for expert
input string          Expert_Title         ="Candles_Smoothed"; // Document name
ulong                 Expert_MagicNumber   =29976;              // 
bool                  Expert_EveryTick     =false;              // 
//--- inputs for main signal
input int             Signal_ThresholdOpen =40;                 // Signal threshold value to open [0...100]
input int             Signal_ThresholdClose=20;                 // Signal threshold value to close [0...100]
input double          Signal_PriceLevel    =0.0;                // Price level to execute a deal
input double          Signal_StopLevel     =50.0;               // Stop Loss level (in points)
input double          Signal_TakeLevel     =50.0;               // Take Profit level (in points)
input int             Signal_Expiration    =1;                  // Expiration of pending orders (in bars)
input bool            Signal__BuyPosOpen   =true;               // Candles_Smoothed() Permission to buy
input bool            Signal__SellPosOpen  =true;               // Candles_Smoothed() Permission to sell
input bool            Signal__BuyPosClose  =true;               // Candles_Smoothed() Permission to exit a long position
input bool            Signal__SellPosClose =true;               // Candles_Smoothed() Permission to exit a short position
input ENUM_TIMEFRAMES Signal__Ind_Timeframe=PERIOD_H1;            // Candles_Smoothed() Timeframe
input Smooth_Method   Signal__MA_SMethod   =4;                  // Candles_Smoothed() Smoothing method (1 - 10)
input uint            Signal__MA_Length    =30;                 // Candles_Smoothed() Smoothing depth
input uint            Signal__MA_Phase     =100;                // Candles_Smoothed() Smoothing parameter
input uint            Signal__SignalBar    =1;                  // Candles_Smoothed() Bar index for the entry signal
input double          Signal__Weight       =1.0;                // Candles_Smoothed() Weight [0...1.0]
//--- inputs for money
input double          Money_FixLot_Percent =10.0;               // Percent
input double          Money_FixLot_Lots    =0.1;                // Fixed volume

Em nosso caso, isso foi feito com a variável de entrada Signal__MA_SMethod.

Você pode acelerar significativamente a modificação se você abrir as duas versões de código (ASCtrendSignal.mqh e BykovTrendSignal.mqh) simultaneamente no editor (posicionando uma delas ao lado esquerdo e a outra ao lado direito) e compará-las cuidadosamente.

Conclusão

Incluímos uma quantidade suficiente de Expert Advisors baseados no sistema de negociação de semáforo no arquivo Experts.zip, anexo a este artigo, para permitir que criadores iniciantes de Expert Advisors possam compreender facilmente todas as características da escrita desse código ou, pelo menos, trabalhar com Expert Advisors pronto para uso, os quais utilizam indicadores muito populares.

Todos os Expert Advisors anexos são adicionalmente apresentados como módulos de treinamento para aqueles que desejam usar o gerador de estratégias de negociação como base para os seus próprios sistemas de negociação. Esses módulos estão localizados em MySignals.zip, enquanto que os sistemas de negociação baseados neles podem ser encontrados em Expertsez.zip. Os indicadores utilizados nos Expert Advisors estão em Indicators.zip. Os caminhos para extração dos arquivos são os seguintes:

  • Experts.zip: "\MQL5\Experts\";
  • Expertsez.zip: "\MQL5\Experts\";
  • MySignals.zip: "\MQL5\Include\Expert\Signal\MySignals\";
  • Indicators.zip: "\MQL5\Indicators\";
  • SmoothAlgorithms.mqh: "\Include\";
  • TradeAlgorithms.mqh: "\Include\".

Reinicie o MetaEditor, abra a janela do navegador, clique com o botão direito do mouse na etiqueta MQL5 e selecione "Compilar" no menu pop-up.

O arquivo SmoothAlgorithms.mqh é necessário para a compilação de alguns indicadores do arquivo Indicators.zip, enquanto que o arquivo TradeAlgorithms.mqh é necessário para a compilação de todos os Expert Advisors do arquivo Experts.zip.

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

Arquivos anexados |
experts.zip (34.67 KB)
expertsez.zip (31.51 KB)
indicators__3.zip (39.15 KB)
mysignals.zip (44.08 KB)
Crie o seu próprio robô de negociação em 6 passos! Crie o seu próprio robô de negociação em 6 passos!
Se você não sabe como as classes de negócio são construídas, e se assusta com as palavras "Programação orientada a objeto", então, este artigo é para você. Na realidade, você não precisa saber os detalhes para escrever seu próprio módulo de sinais de negociação. Apenas siga algumas regras simples. Todo o resto será feito pelo Assistente MQL5, e você terá um robô de negócio pronto para uso!
Abordagem orientada a objetos para construção de painéis de múltiplos períodos de tempo e múltiplas moedas Abordagem orientada a objetos para construção de painéis de múltiplos períodos de tempo e múltiplas moedas
Este artigo descreve como a programação orientada a objetos pode ser usada para criar painéis de múltiplos períodos de tempo múltiplas moedas para o MetaTrader 5. O principal objetivo é construir um painel universal, que pode ser utilizado para exibição de diversos tipos diferentes de dados, tal como preços, variação de preços, valores de indicador ou condições personalizadas de compra/venda, sem a necessidade de modificar o código do painel em si.
Visualizar uma estratégia no Tester do MetaTrader 5 Visualizar uma estratégia no Tester do MetaTrader 5
Todos conhecemos o ditado "é melhor ver uma vez do que ouvir cem vezes". Você pode ler diversos livros sobre Paris ou Veneza, mas com base nas imagens mentais, você não teria os mesmos sentimentos do que se estivesse caminhando à noite por essas cidades fabulosas. A vantagem da visualização pode ser facilmente projetada em qualquer aspecto de nossas vidas, incluindo trabalho no mercado, por exemplo, a análise de preço em gráficos utilizando indicadores e, é evidente, a visualização de teste de estratégia. Este artigo contém descrições de todos os recursos de visualização do Strategy Tester do MetaTrader 5.
Os Fundamentos da programação orientada a objetos Os Fundamentos da programação orientada a objetos
Você não precisa saber o que são polimorfismo, encapsulação, etc. tudo sobre o uso da programação orientada a objeto (OOP)... você pode simplesmente usar estes recursos. Este artigo cobre o básico de OOP com exemplos práticos.