English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Gerador de sinal de negócios baseado em um indicador personalizado

Gerador de sinal de negócios baseado em um indicador personalizado

MetaTrader 5Exemplos | 14 março 2014, 14:02
3 408 0
Vladimir Karputov
Vladimir Karputov

Introdução

Nesse artigo, direi a você como criar um gerador de sinal de negócios baseado em um indicador personalizado. Você verá como pode escrever seu próprio modelo de negócios para um indicador personalizado. Também explicarei o objetivo do modelo 0 e porque estruturas do tipo IS_PATTERN_USAGE(0) são utilizadas no módulo de sinais de negócios.

O artigo utilizará dois tipos de código: o código que estamos preste a modificar e o código já modificado. O código modificado será destacado como a seguir:

//+------------------------------------------------------------------+
//|                                                     MySignal.mqh |
//|                              Copyright © 2012, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+

O código modificado é o código a ser copiado e colado no gerador de sinal de negócios. Espero que você entenda melhor o código através do destaque.

1. Indicador personalizado

Tenho certeza que deve haver um indicador não incluído na entrega padrão que você a muito deseja utilizar. E esse é o indicador baseado no qual você deseja elaborar um módulo de sinal de negócios. Usarei o indicador MACD da entrega padrão como um indicador. O localização do indicador é a conforme a seguir: ...MQL5\Indicators\Examples\MACD.mq5.

Cada indicador pode descrever um ou mais modelos de mercado. Um modelo de mercado é uma certa combinação do valor do indicador e do valor do preço. Os modelos disponíveis para o indicador MACD são opostos, o cruzamento entre os principais e a linha do sinal, o cruzamento do nível zero, a divergência e a dupla divergência.

1.1 O modelo novo do indicador.

Vamos presumir que não estamos felizes com os modelos de mercado dados fornecidos disponíveis para o indicador e queremos introduzir nosso próprio modelo de indicador. A descrição do novo modelo de indicado: se o indicador MACD estiver abaixa da linha zero e seus valores estão aumentando, podemos esperar um crescimento futuro e abrirmos uma posição longa:

Figura 1: Modelo de crescimento potencial do indicador

Figura 1: Modelo de crescimento potencial do indicador

Se o indicador MACD estiver acima da linha zero e seus valores estiverem diminuindo, podemos esperar um decréscimo futuro e abrirmos uma posição curta:

Figura 2: Modelo de queda potencial do indicador

Figura 2: Modelo de queda potencial do indicador

Então, tomamos uma decisão sobre o indicador personalizado e surgimos com o novo modelo de negócios para o indicador e sua descrição. Vamos prosseguir para a escrita do código.

2. Escrevendo o gerador do sinal de negócios baseado em nosso indicador personalizado

Nosso gerador é o descendente da classe base CExpertSignal. A classe base CExpertSignal é uma classe para a criação de geradores de sinais de negócios. A classe CExpertSignal contém um conjunto de métodos públicos(sendo assim acessíveis externamente) que permitem a um Expert Advisor ver o indicador de um gerador de sinal de negócios com relação a direção da entrada no mercado.

Já que estamos trabalhando com nosso próprio gerador de sinal de negócios, ele deve ser herdado da classe CExpertSignal, com os relevantes métodos virtuais redefinidos (preenchidos com o código correspondente).

3. Criando a classe do gerador de sinal de negócios

O gerador do sinal de negociação deve estar por padrão localizado na pasta ...MQL5\Include\Expert\Signal. Para não sobrecarregar a pasta ...\Signal da biblioteca padrão com muita informação, vamos criar uma nova pasta sob a pasta ...\Expert e chamá-la de \MySignals:

Figura 3. Criando a nova pasta MySignals

Figura 3. Criando a nova pasta MySignals

Em seguida, criaremos um include file utilizando o assistente do MQL5. No MetaEditor, selecione "Novo" sob o menu do arquivo e depois selecione "Incluir Arquivo (*.mqh)".

Figura 4. Assistente do MQL5. Criando uma inclusão do arquivo mqh

Figura 4. Assistente do MQL5. Criando uma inclusão do arquivo mqh

O nome da classe do gerador de sinal será MySignal. Ela ficará localizada sob Include\Expert\MySignals\MySignal. Vamos especificá-lo:

Figura 5. Assistente do MQL5. Configuração do local do arquivo incluso.

Figura 5. Assistente do MQL5. Configuração do local do arquivo incluso.

Após clicar em "Concluir", o assistente do MQL5 gerará um modelo vazio. Desse momento em diante, faremos tudo manualmente e copiaremos/colaremos dados. Gostaria de chamar sua atenção para o fato de que, internamente, todos os sinais da biblioteca padrão são quase idênticos. Eles apenas diferem nos algoritmos utilizados para determinar modelos de negócios.

Portanto, você pode tomar qualquer arquivo da pasta \Include\Expert\Signal, copiar seu conteúdo e colá-lo dentro de seu modelo. Depois você pode começar a editar o arquivo resultante do gerador do sinal de negócios.

4. Descrição da classe do gerador do sinal de negócios

Como um modelo, eu peguei o arquivo \Include\Expert\Signal\SignalEnvelopes.mqh, do qual eu copiei tudo, menos o cabeçalho:
//+------------------------------------------------------------------+
//|                                              SignalEnvelopes.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+

e colei ele todo dentro de nosso modelo MySignal.mqh quase vazio. Cheguei a esse resultado:

//+------------------------------------------------------------------+
//|                                                     MySignal.mqh |
//|                              Copyright © 2012, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signals of indicator 'Envelopes'                           |
//| Type=SignalAdvanced                                              |
//| Name=Envelopes                                                   |
//| ShortName=Envelopes                                              |
//| Class=CSignalEnvelopes                                           |
//| Page=signal_envelopes                                            |
//| Parameter=PeriodMA,int,45,Period of averaging                    |
//| Parameter=Shift,int,0,Time shift                                 |
//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging     |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series   |
//| Parameter=Deviation,double,0.15,Deviation                        |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalEnvelopes.                                          |
//| Purpose: Class of generator of trade signals based on            |
//|          the 'Envelopes' indicator.                              |
//| It is derived from the CExpertSignal class.                      |
//+------------------------------------------------------------------+
class CSignalEnvelopes : public CExpertSignal
  {
protected:
   CiEnvelopes       m_env;            // object-indicator
   //--- adjusted parameters
   int               m_ma_period;      // the "period of averaging" parameter of the indicator
   int               m_ma_shift;       // the "time shift" parameter of the indicator
   ENUM_MA_METHOD    m_ma_method;      // the "method of averaging" parameter of the indicator
   ENUM_APPLIED_PRICE m_ma_applied;    // the "object of averaging" parameter of the indicator
   double            m_deviation;      // the "deviation" parameter of the indicator
   double            m_limit_in;       // threshold sensitivity of the 'rollback zone'
   double            m_limit_out;      // threshold sensitivity of the 'break through zone'
   //--- "weights" of market models (0-100)
   int               m_pattern_0;      // model 0 "price is near the necessary border of the envelope"
   int               m_pattern_1;      // model 1 "price crossed a border of the envelope"

public:
                     CSignalEnvelopes(void);
                    ~CSignalEnvelopes(void);
   //--- methods of setting adjustable parameters
   void              PeriodMA(int value)                 { m_ma_period=value;        }
   void              Shift(int value)                    { m_ma_shift=value;         }
   void              Method(ENUM_MA_METHOD value)        { m_ma_method=value;        }
   void              Applied(ENUM_APPLIED_PRICE value)   { m_ma_applied=value;       }
   void              Deviation(double value)             { m_deviation=value;        }
   void              LimitIn(double value)               { m_limit_in=value;         }
   void              LimitOut(double value)              { m_limit_out=value;        }
   //--- methods of adjusting "weights" of market models
   void              Pattern_0(int value)                { m_pattern_0=value;        }
   void              Pattern_1(int value)                { m_pattern_1=value;        }
   //--- method of verification of settings
   virtual bool      ValidationSettings(void);
   //--- method of creating the indicator and time series
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- methods of checking if the market models are formed
   virtual int       LongCondition(void);
   virtual int       ShortCondition(void);

protected:
   //--- method of initialization of the indicator
   bool              InitMA(CIndicators *indicators);
   //--- methods of getting data
   double            Upper(int ind)                      { return(m_env.Upper(ind)); }
   double            Lower(int ind)                      { return(m_env.Lower(ind)); }
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CSignalEnvelopes::CSignalEnvelopes(void) : m_ma_period(45),
                                           m_ma_shift(0),
                                           m_ma_method(MODE_SMA),
                                           m_ma_applied(PRICE_CLOSE),
                                           m_deviation(0.15),
                                           m_limit_in(0.2),
                                           m_limit_out(0.2),
                                           m_pattern_0(90),
                                           m_pattern_1(70)
  {
//--- initialization of protected data
   m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CSignalEnvelopes::~CSignalEnvelopes(void)
  {
  }
//+------------------------------------------------------------------+
//| Validation settings protected data.                              |
//+------------------------------------------------------------------+
bool CSignalEnvelopes::ValidationSettings(void)
  {
//--- validation settings of additional filters
   if(!CExpertSignal::ValidationSettings())
      return(false);
//--- initial data checks
   if(m_ma_period<=0)
     {
      printf(__FUNCTION__+": period MA must be greater than 0");
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Create indicators.                                               |
//+------------------------------------------------------------------+
bool CSignalEnvelopes::InitIndicators(CIndicators *indicators)
  {
//--- check pointer
   if(indicators==NULL)
      return(false);
//--- initialization of indicators and time series of additional filters
   if(!CExpertSignal::InitIndicators(indicators))
      return(false);
//--- create and initialize MA indicator
   if(!InitMA(indicators))
      return(false);
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialize MA indicators.                                        |
//+------------------------------------------------------------------+
bool CSignalEnvelopes::InitMA(CIndicators *indicators)
  {
//--- check pointer
   if(indicators==NULL)
      return(false);
//--- add object to collection
   if(!indicators.Add(GetPointer(m_env)))
     {
      printf(__FUNCTION__+": error adding object");
      return(false);
     }
//--- initialize object
   if(!m_env.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied,m_deviation))
     {
      printf(__FUNCTION__+": error initializing object");
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| "Voting" that the price will grow.                               |
//+------------------------------------------------------------------+
int CSignalEnvelopes::LongCondition(void)
  {
   int result=0;
   int idx   =StartIndex();
   double close=Close(idx);
   double upper=Upper(idx);
   double lower=Lower(idx);
   double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying
   if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width)
      result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying
   if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width)
      result=m_pattern_1;
//--- return the result
   return(result);
  }
//+------------------------------------------------------------------+
//| "Voting" that the price will fall.                               |
//+------------------------------------------------------------------+
int CSignalEnvelopes::ShortCondition(void)
  {
   int result  =0;
   int idx     =StartIndex();
   double close=Close(idx);
   double upper=Upper(idx);
   double lower=Lower(idx);
   double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling
   if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width)
      result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling
   if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width)
      result=m_pattern_1;
//--- return the result
   return(result);
  }
//+------------------------------------------------------------------+
    

‘Nota’ linha 6:

#include <Expert\ExpertSignal.mqh>

Aqui damos ao pré-processador um pedido para incluir a classe base CExpertSignal para a criação dos geradores de sinais do sinal de negócios em nosso modelo.

Continuamos a editar o modelo. Para garantir que nosso modelo esteja visível posteriormente no assistente do MQL5, precisamos alterar a descrição de nossa classe:

//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signals of indicator 'Envelopes'                           |
//| Type=SignalAdvanced                                              |
//| Name=Envelopes                                                   |
//| ShortName=Envelopes                                              |
//| Class=CSignalEnvelopes                                           |
//| Page=signal_envelopes                                            |
//| Parameter=PeriodMA,int,45,Period of averaging                    |
//| Parameter=Shift,int,0,Time shift                                 |
//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging     |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series   |
//| Parameter=Deviation,double,0.15,Deviation                        |
//+------------------------------------------------------------------+

Então, vamos ver. A linha

//| Title=Signals of indicator 'Envelopes'                           |

mostra o nome de nossa classe do sinal sob a qual ele será exibido no assistente do MQL5. Alteraremos esse nome para algo como isso:

//| Title=Signal of the 'Custom Indicator' indicator             |

A próxima linha:

//| Name=Envelopes                                                   |

indica o nome para variáveis descritivas de nossa classe do sinal de negócios. Essa descrição será utilizada pelo assistente do MQL5. Vamos modificar essa linha como a seguir:

//| Name=MyCustomIndicator                                           |

A próxima linha:

//| ShortName=Envelopes                                              |

Daremos o mesmo nome a esse parâmetro:

//| ShortName=MyCustomIndicator                                      |

A linha seguinte define o nome da classe:

//| Class=CSignalEnvelopes                                           |

Vamos renomear esse parâmetro:

//| Class=CSignalMyCustInd                                           |

Deixe o próximo parâmetro como está.

//| Page=signal_envelopes                                            |

O grupo de parâmetro seguinte é responsável pela descrição dos parâmetros do indicador subjacentes ao gerador do sinal de negócios. Conforme mencionei anteriormente, utilizarei o ...MQL5\Indicators\Examples\MACD.mq5 como o indicador personalizado. Ele tem os seguintes parâmetros:

//--- input parameters
input int                InpFastEMA=12;               // Fast EMA period
input int                InpSlowEMA=26;               // Slow EMA period
input int                InpSignalSMA=9;              // Signal SMA period
input ENUM_APPLIED_PRICE  InpAppliedPrice=PRICE_CLOSE; // Applied price

4.1 Bloco da descrição dos parâmetros

Por favor, note que os parâmetros dados acima aplicam-se somente ao MACD.mq5. Seu indicador personalizado pode ter parâmetros completamente diferentes. O principal aqui é coincidir os parâmetros do indicador com suas descrições na classe do sinal de negócios. O bloco de descrição do parâmetro na classe do sinal de negócios para o indicador personalizado em questão, MACD.mq5 , será como o seguinte:

//| Parameter=PeriodFast,int,12,Period of fast EMA                   |
//| Parameter=PeriodSlow,int,24,Period of slow EMA                   |
//| Parameter=PeriodSignal,int,9,Period of averaging of difference   |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series   |

Dê uma olhada em como os parâmetros no indicador coincidem agora com as descrições no bloco de descrição da classe. Seguindo todas as modificações, o bloco de descrição de nossa classe será como o seguinte:

//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signal of the 'Custom Indicator' indicator                 |
//| Type=SignalAdvanced                                              |
//| Name=MyCustomIndicator                                           |
//| ShortName=MyCustomIndicator                                      |
//| Class=CSignalMyCustInd                                           |
//| Page=signal_envelopes                                            |
//| Parameter=PeriodFast,int,12,Period of fast EMA                   |
//| Parameter=PeriodSlow,int,24,Period of slow EMA                   |
//| Parameter=PeriodSignal,int,9,Period of averaging of difference   |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series   |
//+------------------------------------------------------------------+

Em programação, é considerada uma boa prática fornecer comentários ao código de alguém, tornando assim o mesmo mais fácil de ser compreendido, ao retomá-lo após algum tempo ter se passado. Então, modificaremos o seguinte bloco:

//+------------------------------------------------------------------+
//| Class CSignalEnvelopes.                                          |
//| Purpose: Class of generator of trade signals based on            |
//|          the 'Envelopes' indicator.                              |
//| It is derived from the CExpertSignal class.                      |
//+------------------------------------------------------------------+

para coincidir com a descrição de nossa classe:

//+------------------------------------------------------------------+
//| Class CSignalMyCustInd.                                          |
//| Purpose: Class of the trading signal generator based on          |
//|          the custom indicator.                                   |
//| It is derived from the CExpertSignal class.                      |
//+------------------------------------------------------------------+

Para evitar confusão, precisamos substituir todos os valores "CSignalEnvelopes" por "CSignalMyCustInd".

Figura 6. Substituindo CSignalEnvelopes por CSignalMyCustInd

Figura 6. Substituindo CSignalEnvelopes por CSignalMyCustInd

Agora vamos dar uma olhada em alguns aspectos teóricos.

5. A classe CiCustom

Precisaremos da classe CiCustom para continuar a trabalhar no código da classe dos indicadores de negócios do indicador personalizado. A classe CiCustom foi criada especificamente para trabalhar com indicadores personalizados. A classe CiCustom fornece criação, configuração e acesso aos dados do indicador personalizado.

6. A classe CIndicators

CIndicators é a classe de coleção de instâncias de série temporal e de classes indicadoras técnicas. A classe CIndicators fornece criação, armazenamento e gerenciamento (sincronização de dados, identificação e gerenciamento de memória) de instância de classes de indicadores técnicos.

Estamos particularmente interessados na classe CIndicators por causa do método Create. Esse método cria um indicador de um tipo específico com parâmetros especificados.

7. Continue escrevendo nossa classe do sinal de negócios

O próximo bloco de código que modificaremos (linhas 28-42) é como a seguir:
class CSignalMyCustInd : public CExpertSignal
  {
protected:
   CiEnvelopes       m_env;            // object-indicator
   //--- adjusted parameters
   int               m_ma_period;      // the "period of averaging" parameter of the indicator
   int               m_ma_shift;       // the "time shift" parameter of the indicator
   ENUM_MA_METHOD    m_ma_method;      // the "method of averaging" parameter of the indicator
   ENUM_APPLIED_PRICE m_ma_applied;    // the "object of averaging" parameter of the indicator
   double            m_deviation;      // the "deviation" parameter of the indicator
   double            m_limit_in;       // threshold sensitivity of the 'rollback zone'
   double            m_limit_out;      // threshold sensitivity of the 'break through zone'
   //--- "weights" of market models (0-100)
   int               m_pattern_0;      // model 0 "price is near the necessary border of the envelope"
   int               m_pattern_1;      // model 1 "price crossed a border of the envelope"

8. Criação do indicador personalizado no gerador do sinal de negócios

Dê uma olhada no bloco do código fornecido acima. A linha

   CiEnvelopes       m_env;            // object-indicator

declara um objeto - o indicador de classe CiEnvelopes. CiEnvelopes é a classe para trabalhar com o indicador técnico da biblioteca padrão. A classe CiEnvelopes foi criada baseada no indicador técnico da biblioteca padrão. No entanto, estamos escrevendo o código do gerador baseado em nosso indicador personalizado. Portanto não há classe previamente pronta para nosso ou seu indicador personalizado na biblioteca padrão. O que podemos fazer é utilizar a classe CiCustom.

Vamos declarar nosso indicador como a classe CiCustom:

   CiCustom          m_mci;            // indicator object "MyCustomIndicator"

8.1 Quatro Variáveis

Você se lembra do bloco de descrição de parâmetro na classe? Existiam três parâmetros naquela descrição. Na área protegida de nosso gerador de classe, declararemos agora quatro variáveis para passarmos os valores para nossos quatro parâmetros:

   //--- adjustable parameters
   int               m_period_fast;    // "fast EMA period"
   int               m_period_slow;    // "slow EMA period"
   int               m_period_signal;  // "difference averaging period"
   ENUM_APPLIED_PRICE m_applied;       // "price type"

O bloco de código seguinte:

   //--- "weights" of market models (0-100)
   int               m_pattern_0;      // model 0 "price is near the necessary border of the envelope"
   int               m_pattern_1;      // model 1 "price crossed a border of the envelope"

Esse código declara variáveis que dão "peso" aos modelos de negócios de nosso gerador do sinal de negócios. Vamos substituir o bloco de "pesos" com o seguinte código:

   //--- "weights" of the market models (0-100)
   int               m_pattern_0;      // model 0 "the oscillator has required direction"
   int               m_pattern_1;      // model 1 "the indicator is gaining momentum - buy; the indicator is falling - sell"

9. Modelo 0

Como você se lembra, no início desse artigo foi decidido descrever somente um novo modelo que será gerado por nosso gerador do sinal de negócios. No entanto, no código acima especifiquei dois modelos de mercado (modelo 0 e modelo 1). Aqui, o modelo 0 é um importante modelo auxiliar. Ele é necessário ao fazer negócios com pedidos pendentes. Quando aplicado, o modelo 0 assegura que pedidos pendentes sejam deslocados junto ao preço. Vamos dar uma olhada em nosso gerador do sinal de negócios e as seguintes condições:

  • O indicador personalizado MACD está abaixo da linha zero,
  • e seus valores estão decrescendo,
  • estamos fazendo negócios com pedidos pendentes posicionados a 50 pontos do preço de abertura da barra (valor de preço de quatro dígitos).

Essas condições descrevem perfeitamente nosso modelo de negócios. Eis aqui como as coisas se desenrolarão: Nossas condições do modelo de negócios serão verificadas no aparecimento da barra nº 1. Aqui temos: O MACD está abaixo da linha zero, ainda que seja um momento vantajoso. Isso corresponde ao sinal de compra. Portanto, colocamos um pedido de interrupção de compra pendente:

Figura 7. Colocando um pedido de interrupção de compra pendente
Figura 7. Colocando um pedido de interrupção de compra pendente

Diante do aparecimento da próxima barra nº 2, o verificador de condição descobre que o MACD está abaixo de zero e está caindo. De acordo com nosso modelo de negócios, não existem condições atuais para compra ou venda. No entanto, perceba: quanto a lógica da classe CExpertSignal, já que não existem condições tanto para compra quanto para venda, todos os pedidos pendentes devem ser EXCLUíDOS. Nesse caso, se o preço subir de subitamente e dramaticamente, perderemos a oportunidade de entrar no mercado com nossa vantagem já que não haverá pedido pendente.

Aqui é onde o modelo 0 auxiliar parece ser bastante útil. O modelo auxiliar zero será aplicado, uma vez que:

  • O indicador personalizado MACD está abaixo da linha zero.

Então podemos colocar um pedido de interrupção de compra pendente: Já que colocamos um pedido a 50 pontos do preço de abertura da barra, nós, de fato, simplesmente deslocamos a pedido de interrupção de compra pendente de acordo com o movimento do preço:

Figura 8. Deslocando o pedido de interrupção de compra para baixo
Figura 8. Deslocando o pedido de interrupção de compra para baixo

Assim, ao utilizar o modelo 0 auxiliar obtemos a oportunidade de deslocar um pedido pendente quanto ao movimento do preço.

10. Modificações futuras do código modelo

O próximo bloco de código a ser modificado é o a seguir:
public:
                     CSignalMyCustInd(void);
                    ~CSignalMyCustInd(void);
   //--- methods of setting adjustable parameters
   void              PeriodMA(int value)                 { m_ma_period=value;        }
   void              Shift(int value)                    { m_ma_shift=value;         }
   void              Method(ENUM_MA_METHOD value)        { m_ma_method=value;        }
   void              Applied(ENUM_APPLIED_PRICE value)   { m_ma_applied=value;       }
   void              Deviation(double value)             { m_deviation=value;        }
   void              LimitIn(double value)               { m_limit_in=value;         }
   void              LimitOut(double value)              { m_limit_out=value;        }
   //--- methods of adjusting "weights" of market models
   void              Pattern_0(int value)                { m_pattern_0=value;        }
   void              Pattern_1(int value)                { m_pattern_1=value;        }
   //--- method of verification of settings
   virtual bool      ValidationSettings(void);
   //--- method of creating the indicator and time series
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- methods of checking if the market models are formed
   virtual int       LongCondition(void);
   virtual int       ShortCondition(void);

 
    

Nesse bloco, declaramos métodos de ajuste de parâmetros ajustáveis, métodos de ajuste de pesos de modelos de negócios, método de verificação de configurações, método de inicialização de indicador e métodos de verificação se os modelos do mercado estão gerados.

Levando em consideração que declaramos quatro variáveis nos parâmetros ajustáveis, o bloco de métodos para ajuste dos parâmetros será como a seguir:

   //--- methods of setting adjustable parameters
   void              PeriodFast(int value)               { m_period_fast=value;           }
   void              PeriodSlow(int value)               { m_period_slow=value;           }
   void              PeriodSignal(int value)             { m_period_signal=value;         }
   void              Applied(ENUM_APPLIED_PRICE value)   { m_applied=value;               }

O próximo fragmento de código permanecerá inalterado:

   //--- methods of adjusting "weights" of market models
   void              Pattern_0(int value)                { m_pattern_0=value;        }
   void              Pattern_1(int value)                { m_pattern_1=value;        }
   //--- method of verification of settings
   virtual bool      ValidationSettings(void);
   //--- method of creating the indicator and time series
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- methods of checking if the market models are generated
   virtual int       LongCondition(void);
   virtual int       ShortCondition(void);

O próximo bloco de código a ser modificado é o a seguir:

protected:
   //--- method of initialization of the indicator
   bool              InitMA(CIndicators *indicators);
   //--- methods of getting data
   double            Upper(int ind)                      { return(m_env.Upper(ind)); }
   double            Lower(int ind)                      { return(m_env.Lower(ind)); }
  };

Esse bloco será o mais modificado. Por favor, note que estou utilizando o método GetData da classe CIndicator. Nomes do métodos acionados serão fornecidos diretamente no código:

protected:
   //--- indicator initialization method
   bool              InitMyCustomIndicator(CIndicators *indicators);
   //--- methods for getting data
   //- getting the indicator value
   double            Main(int ind) { return(m_mci.GetData(0,ind));      }
   //- getting the signal line value
   double            Signal(int ind) { return(m_mci.GetData(1,ind));    }
   //- difference between two successive indicator values
   double            DiffMain(int ind) { return(Main(ind)-Main(ind+1)); }
   int               StateMain(int ind);
   double            State(int ind) { return(Main(ind)-Signal(ind)); }
   //- preparing data for the search
   bool              ExtState(int ind);
   //- searching the market model with the specified parameters
   bool              CompareMaps(int map,int count,bool minimax=false,int start=0);
  };

O próximo bloco de código é o construtor:

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CSignalMyCustInd::CSignalMyCustInd(void) : m_ma_period(45),
                                           m_ma_shift(0),
                                           m_ma_method(MODE_SMA),
                                           m_ma_applied(PRICE_CLOSE),
                                           m_deviation(0.15),
                                           m_limit_in(0.2),
                                           m_limit_out(0.2),
                                           m_pattern_0(90),
                                           m_pattern_1(70)
  {
//--- initialization of protected data
   m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
  }

No construtor, alteraremos os nomes das variáveis. Mais adiante, utilizaremos apenas duas séries: USE_SERIES_HIGH+USE_SERIES_LOW

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CSignalMyCustInd::CSignalMyCustInd(void) : m_period_fast(12),
                                           m_period_slow(24),
                                           m_period_signal(9),
                                           m_applied(PRICE_CLOSE),
                                           m_pattern_0(10),
                                           m_pattern_1(50)
  {
//--- initialization of protected data
   m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW;
  }

Vamos modificar o método ValidationSettings de nossa classe.

//+------------------------------------------------------------------+
//| Validation settings protected data.                              |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::ValidationSettings(void)
  {
//--- validation settings of additional filters
   if(!CExpertSignal::ValidationSettings())
      return(false);
//--- initial data checks
   if(m_ma_period<=0)
     {
      printf(__FUNCTION__+": period MA must be greater than 0");
      return(false);
     }
//--- ok
   return(true);
  }

No bloco de verificação, verificamos a condição principal para o indicador personalizado dado: m_period_fast>=m_period_slow

//+------------------------------------------------------------------+
//| Checking parameters of protected data                            |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::ValidationSettings(void)
  {
//--- validation settings of additional filters
   if(!CExpertSignal::ValidationSettings())
      return(false);
//--- initial data checks
   if(m_period_fast>=m_period_slow)
     {
      printf(__FUNCTION__+": slow period must be greater than fast period");
      return(false);
     }
//--- ok
   return(true);
  }

O próximo bloco lida com a criação de indicadores:

//+------------------------------------------------------------------+
//| Create indicators.                                               |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::InitIndicators(CIndicators *indicators)
  {
//--- check pointer
   if(indicators==NULL)
      return(false);
//--- initialization of indicators and time series of additional filters
   if(!CExpertSignal::InitIndicators(indicators))
      return(false);
//--- create and initialize MA indicator
   if(!InitMA(indicators))
      return(false);
//--- ok
   return(true);
  }

Conforme aplicado ao nosso indicador personalizado:

//+------------------------------------------------------------------+
//| Creation of indicators.                                          |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::InitIndicators(CIndicators *indicators)
  {
//--- check of pointer is performed in the method of the parent class
//---
//--- initialization of indicators and time series of additional filters
   if(!CExpertSignal::InitIndicators(indicators))
      return(false);
//--- creation and initialization of the custom indicator
   if(!InitMyCustomIndicator(indicators))
      return(false);
//--- ok
   return(true);
  }

O bloco seguinte é um bloco de inicialização do indicador:

//+------------------------------------------------------------------+
//| Initialize MA indicators.                                        |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::InitMA(CIndicators *indicators)
  {
//--- check pointer
   if(indicators==NULL)
      return(false);
//--- add object to collection
   if(!indicators.Add(GetPointer(m_env)))
     {
      printf(__FUNCTION__+": error adding object");
      return(false);
     }
//--- initialize object
   if(!m_env.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied,m_deviation))
     {
      printf(__FUNCTION__+": error initializing object");
      return(false);
     }
//--- ok
   return(true);
  }

Primeiro, adicionamos um objeto à coleção. Depois ajustamos os parâmetros de nosso indicador e criamos o indicador personalizado utilizando o método Create da classe CIndicators:

//+------------------------------------------------------------------+
//| Initialization of indicators.                                    |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::InitMyCustomIndicator(CIndicators *indicators)
  {
//--- add an object to the collection
   if(!indicators.Add(GetPointer(m_mci)))
     {
      printf(__FUNCTION__+": error adding object");
      return(false);
     }
//--- set parameters of the indicator
   MqlParam parameters[4];
//---
   parameters[0].type=TYPE_STRING;
   parameters[0].string_value="Examples\\MACD.ex5";
   parameters[1].type=TYPE_INT;
   parameters[1].integer_value=m_period_fast;
   parameters[2].type=TYPE_INT;
   parameters[2].integer_value=m_period_slow;
   parameters[3].type=TYPE_INT;
   parameters[3].integer_value=m_period_signal;
//--- object initialization
   if(!m_mci.Create(m_symbol.Name(),0,IND_CUSTOM,4,parameters))
     {
      printf(__FUNCTION__+": error initializing object");
      return(false);
     }
//--- number of buffers
   if(!m_mci.NumBuffers(4)) return(false);
//--- ok
   return(true);
  }

O próximo bloco verifica as condições de compra:

//+------------------------------------------------------------------+
//| "Voting" that the price will grow.                               |
//+------------------------------------------------------------------+
int CSignalMyCustInd::LongCondition(void)
  {
   int result=0;
   int idx   =StartIndex();
   double close=Close(idx);
   double upper=Upper(idx);
   double lower=Lower(idx);
   double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying
   if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width)
      result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying
   if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width)
      result=m_pattern_1;
//--- return the result
   return(result);
  }

De acordo com nossa implementação do modelo 0, dois modelos são verificados:

//+------------------------------------------------------------------+
//| "Voting" that the price will grow.                               |
//+------------------------------------------------------------------+
int CSignalMyCustInd::LongCondition(void)
  {
   int result=0;
   int idx   =StartIndex();
//--- check direction of the main line
   if(DiffMain(idx)>0.0)
     {
      //--- the main line goes upwards, which confirms the possibility of the price growth
      if(IS_PATTERN_USAGE(0))
         result=m_pattern_0;      // "confirming" signal number 0
      //--- if the model 1 is used, look for a reverse of the main line
      if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)<0.0)
         result=m_pattern_1;      // signal number 1
     }
//--- return the result
   return(result);
  }

O seguinte bloco verifica as condições de venda:

//+------------------------------------------------------------------+
//| "Voting" that the price will fall.                               |
//+------------------------------------------------------------------+
int CSignalMyCustInd::ShortCondition(void)
  {
   int result  =0;
   int idx     =StartIndex();
   double close=Close(idx);
   double upper=Upper(idx);
   double lower=Lower(idx);
   double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling
   if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width)
      result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling
   if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width)
      result=m_pattern_1;
//--- return the result
   return(result);
  }

De acordo com nossa implementação do modelo 0, dois modelos são verificados:

//+------------------------------------------------------------------+
//| "Voting" that the price will fall.                               |
//+------------------------------------------------------------------+
int CSignalMyCustInd::ShortCondition(void)
  {
   int result=0;
   int idx   =StartIndex();
//--- check direction of the main line
   if(DiffMain(idx)<0.0)
     {
            //--- the main line gown downwards, which confirms the possibility of the price fall
      if(IS_PATTERN_USAGE(0))
         result=m_pattern_0;      // "confirming" signal number 0
      //--- if the model 1 is used, look for a reverse of the main line
      if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)>0.0)
         result=m_pattern_1;      // signal number 1
     }
//--- return the result
   return(result);
  }

Conclusão

Espero que esse artigo tenha ajudado a você compreender com você pode criar um gerador do sinal de negócios baseado em seu indicador personalizado.

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

Arquivos anexados |
mysignal.mqh (9.38 KB)
Resultados do MQL5 Market para o segundo trimestre de 2013 Resultados do MQL5 Market para o segundo trimestre de 2013
Operando com sucesso a um ano e meio, o MQL5 Market se tornou a maior loja de estratégias de negócios e indicadores técnicos de negociadores. Ele oferece cerca de 800 aplicações fornecidas por 350 desenvolvedores de todo o mundo. Mais de 100.000 programas de negócio já foram comprados e baixados por negociantes para os terminais do MetaTrader 5.
Resultados do MQL5 Market para o primeiro trimestre de 2013 Resultados do MQL5 Market para o primeiro trimestre de 2013
Desde sua fundação, a loja de robôs de negociação e indicadores técnicos MQL5 Market já atraiu mais de 250 desenvolvedores que publicaram 580 produtos. O primeiro trimestre de 2013 acabou se tornando de grande sucesso para alguns vendedores do MQL5 Market que conseguiram ganhar bons lucros vendendo seus produtos.
Negócios sociais com as plataformas de negócios MetaTrader 4 e MetaTrader 5 Negócios sociais com as plataformas de negócios MetaTrader 4 e MetaTrader 5
O que são negócios sociais? São uma cooperação mútua benéfica entre negociadores e investidores pelo meio dos quais negociadores de sucesso permitem o monitoramento de suas negociações e investidores em potencial aproveitam a oportunidade de monitorar seus desempenhos e copiar negociações daqueles que parecerem mais promissores.
Jeremy Scott - Vendedor de sucesso no MQL5 Market Jeremy Scott - Vendedor de sucesso no MQL5 Market
Jeremy Scott, que é melhor conhecido pelo apelido de Johnnypasado na comunidade MQL5.community, tornou-se famoso oferecendo produtos em nosso serviço do MQL5 Market. Jeremy já ganhou vários milhares de dólares no mercado e esse não é o limite. Decidimos olhar mais de perto o futuro milionário e recebermos alguns conselhos para vendedores do MQL5 Market.