English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Assistente MQL5: Como ensinar um EA a abrir ordens pendentes a qualquer preço

Assistente MQL5: Como ensinar um EA a abrir ordens pendentes a qualquer preço

MetaTrader 5Exemplos | 26 março 2014, 13:40
4 736 0
Vladimir Karputov
Vladimir Karputov

Introdução

Um Expert Advisor gerado usando o assistente do MQL5 só pode abrir ordens pendentes na distância fixada do preço atual. Isto significa que, se a situação do mercado muda (por exemplo, uma alteração na volatilidade do mercado), o Expert Advisor terá que ser executado novamente com os novos parâmetros.

Isto não seria adequado para muitos sistemas de negociação. Na maioria dos casos, o nível do preço para ordens pendentes é determinado dinamicamente por um sistema de negociação. E a distância do preço atual está mudando constantemente. Neste artigo, discutiremos como modificar um Expert Advisor gerado usando o assistente do MQL5 de modo que ele possa abrir ordens pendentes em diferentes distâncias do preço atual.


1. O mecanismo de abertura de ordens pendentes no Expert Advisor gerado usando o Assistente do MQL5

Um Expert Advisor gerado teria aproximadamente o mesmo código em seu cabeçalho, conforme previsto abaixo:

//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
//--- inputs for expert
input string             Expert_Title="ExpertMySignalEnvelopes.mq5";      // Document name
ulong                    Expert_MagicNumber        =3915;        // 
bool                     Expert_EveryTick          =false;       // 
//--- inputs for main signal
input int                Signal_ThresholdOpen      =10;          // Signal threshold value to open [0...100]
input int                Signal_ThresholdClose     =10;          // Signal threshold value to close [0...100]
input double             Signal_PriceLevel         =0.0;         // Price level to execute a deal
input double             Signal_StopLevel          =85.0;        // Stop Loss level (in points)
input double             Signal_TakeLevel          =195.0;       // Take Profit level (in points)
input int                Signal_Expiration         =0;           // Expiration of pending orders (in bars)
input int                Signal_Envelopes_PeriodMA =13;          // Envelopes(13,0,MODE_SMA,...) Period of averaging
input int                Signal_Envelopes_Shift    =0;           // Envelopes(13,0,MODE_SMA,...) Time shift
input ENUM_MA_METHOD     Signal_Envelopes_Method   =MODE_SMA;    // Envelopes(13,0,MODE_SMA,...) Method of averaging
input ENUM_APPLIED_PRICE Signal_Envelopes_Applied  =PRICE_CLOSE; // Envelopes(13,0,MODE_SMA,...) Prices series
input double             Signal_Envelopes_Deviation=0.2;         // Envelopes(13,0,MODE_SMA,...) Deviation
input double             Signal_Envelopes_Weight   =1.0;         // Envelopes(13,0,MODE_SMA,...) Weight [0...1.0]
//--- inputs for money
input double             Money_FixLot_Percent      =10.0;        // Percent
input double             Money_FixLot_Lots         =0.1;         // Fixed volume
//+------------------------------------------------------------------+

Por favor, observe o parâmetro Signal_PriceLevel. Por padrão, o Expert Advisor é gerado com Signal_PriceLevel=0. Este parâmetro define a distância do preço atual. Se for igual a zero, uma ordem será aberta no preço atual do mercado. Para abrir uma ordem pendente, você deve definir um valor diferente de zero para o parâmetro Signal_PriceLevel, ou seja, o Signal_PriceLevel pode ser tanto negativo quanto positivo.

O valor do Signal_PriceLevel  é geralmente um número bem grande. A diferença entre os valores negativos e positivos é mostrada abaixo:

Signal_PriceLevel=-50:

Fig. 1. Signal_PriceLevel=-50

Fig. 1. Signal_PriceLevel=-50

Signal_PriceLevel=50:

Fig. 2. Signal_PriceLevel=50

Fig. 2. Signal_PriceLevel=50

Assim, se Signal_PriceLevel=-50, uma ordem pendente será aberta no preço que é menos favorável do que o preço atual, enquanto se Signal_PriceLevel=50, uma ordem pendente será aberta no preço que é melhor do que o preço atual.

Esta versão do Expert Advisor abre ordens de Sell Stop e Buy Stop (parada de compra e venda).


2. Onde armazenamos dados na distância do preço para abertura de uma ordem pendente?

Vamos primeiro dar uma olhada na figura abaixo e, em seguida, prosseguir com os comentários:

Fig. 3. Armazenamento de dados na distância do preço atual

Fig. 3. Armazenamento de dados na distância do preço atual

Interpretação da figura acima.

Expert Advisor é o Expert Advisor gerado usando o Assistente do MQL5.

  • O objeto Expert Advisor da classe CExpert é declarado no Expert Advisor a nível global. 
  • Então, na função Onlnit() do Expert Advisor, declaramos um indicador para o objeto de sinal da classe CExpertSignal e o objeto de sinal é imediatamente criado usando o novo operador.
  • Enquanto estiver na função Onlnit(), chamamos a função InitSignal do objeto ExtExpert e inicializamos o objeto de sinal.
  • Enquanto estiver na função Onlnit(), chamamos a função PriceLevel do objeto de sinal que recebe o parâmetro Signal_PriceLevel.

Assim, o parâmetro Signal_PriceLevel, onde a distância do preço atual é armazenada e no qual foi declarada no Expert Advisor, é passada ao objeto de sinal da classe CExpertSignal.

A classe CExpertSignal armazena o valor da distância do preço atual na variável m_price_level declarada com o escopo da classe protegida:

class CExpertSignal : public CExpertBase
  {
protected:
   //--- variables
   double            m_base_price;     // base price for detection of level of entering (and/or exit?)
   //--- variables for working with additional filters
   CArrayObj         m_filters;        // array of additional filters (maximum number of fileter is 64)
   //--- Adjusted parameters
   double            m_weight;         // "weight" of a signal in a combined filter
   int               m_patterns_usage; // bit mask of  using of the market models of signals
   int               m_general;        // index of the "main" signal (-1 - no)
   long              m_ignore;         // bit mask of "ignoring" the additional filter
   long              m_invert;         // bit mask of "inverting" the additional filter
   int               m_threshold_open; // threshold value for opening
   int               m_threshold_close;// threshold level for closing
   double            m_price_level;    // level of placing a pending orders relatively to the base price
   double            m_stop_level;     // level of placing of the "stop loss" order relatively to the open price
   double            m_take_level;     // level of placing of the "take profit" order relatively to the open price
   int               m_expiration;     // time of expiration of a pending order in bars


3. Estrutura do Expert Advisor gerado usando o assistente do MQL5

O Expert Advisor consiste em vários blocos com funcionalidades diferentes.


Fig. 4. Estrutura do Expert Advisor 

Fig. 4. Estrutura do Expert Advisor

Interpretação da figura acima:

  • Expert Advisor é o Expert Advisor gerado usando o assistente do MQL5.
  • CExpert é a classe base para a implementação de estratégias de negócio.
  • CExpertSignal é a classe base para a criação de geradores do sinal de negociação.
  • filter0 ... filtern são geradores de sinal de negociação, descendentes da classe CExpertSignal. Deve notar-se que o nosso sistema de negociação é baseado no gerador do sinal de negociação do indicador de envelopes, mas os sinais dentro do gerador foram modificados. Vamos falar sobre essas mudanças na seção 7.


4. Blocos convenientes do Expert Advisor para modificação

Como você pode ver a partir da estrutura do Expert Advisor gerado usando o Assistente do MQL5, há blocos de classe base. As classes base são parte da biblioteca padrão.

As classes em si são descendentes de outras classes base e elas, por sua vez, consistem de uma ou mais classes de base. Abaixo, você pode encontrar as primeiras linhas do código das duas classes - CExpert e CExpertSignal:

//+------------------------------------------------------------------+
//|                                                       Expert.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#include "ExpertBase.mqh"
#include "ExpertTrade.mqh"
#include "ExpertSignal.mqh"
#include "ExpertMoney.mqh"
#include "ExpertTrailing.mqh"
//+------------------------------------------------------------------+
.
.
.
class CExpert : public CExpertBase

e

//+------------------------------------------------------------------+
//|                                                 ExpertSignal.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#include "ExpertBase.mqh"
.
.
.
class CExpertSignal : public CExpertBase

Eu sou fortemente contra quaisquer modificações das classes de base:

  1. Quando o MetaEditor é atualizado, todas as alterações que você faz nas classes de base são substituídas e as mesmas são restauradas ao seu estado inicial.
  2. A herança seria mais apropriada neste caso. Mas, então, você terá que modificar a biblioteca padrão INTEIRA.

Em vez disso, seria melhor modificar o bloco do Expert Advisor e os módulos do gerador do sinal de negociação, especialmente porque o nosso sistema de negociação já terá um módulo modificado em uso - o gerador do sinal de negociação do indicador de envelopes.

Então, isso está resolvido: vamos fazer mudanças nos blocos do Expert Advisor e no bloco do gerador do sinal de negociação.


5. A lógica da implementação

O indicador será transmitido do Expert Advisor para o gerador do sinal de negociação.

Para este efeito, precisamos declarar adicionalmente uma variável com o escopo protegido e escrever um método que armazene o indicador do Expert Advisor na variável interna:


  Fig. 5. A lógica da implementação

Fig. 5. A lógica da implementação


6. Sistema de negociação

O período de tempo gráfico é D1. O indicador a ser utilizado é o de Envelopes com o período médio de 13 e método de média exponencial. Os tipos de ordens que o Expert Advisor pode abrir são Sell Stop e Buy Stop (paradas de compra e venda).

Se a barra anterior era de alta, definimos uma ordem de Sell Stop (ordem de parada de venda). Se a barra anterior era de baixa, definimos uma ordem de Buy Stop (ordem de parada de compra). Em outras palavras, nós esperamos pela retirada:

Fig. 6. Sistema de negociação

Fig. 6. Sistema de negociação

Para gerar sinais de negociação, conforme exigido pelo sistema de negociação, o módulo padrão do gerador do sinal de negociação SignalEnvelopes.mqh foi modificado.

Observe que aqui você pode usar qualquer gerador de sinal de negociação a partir da biblioteca padrão.


7. Modificação do gerador do sinal de negociação. Obtendo o preço da barra

Então, vamos começar. Preciso dizer que prefiro salvar meus programas no armazenamento do MQL5.

A primeira coisa que devemos fazer a fim de começar a modificar o gerador do sinal de negociação é criar um arquivo incluso em branco, zerá-lo e passar todo o conteúdo do gerador do sinal de negociação padrão do indicador de Envelopes.

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

Fig. 7. Criando a pasta MySignals

Fig. 7. Criando a pasta MySignals

Em seguida, criaremos um arquivo incluso utilizando o Assistente do MQL5.

No MetaEditor, selecione "Novo" no menu do arquivo e depois selecione "Incluir Arquivo (*.mqh)".

Fig. 8. Assistente do MQL5. Criando uma inclusão do arquivo mqh

Fig. 8. Assistente do MQL5. Criando uma inclusão do arquivo mqh

O nome da nossa classe do gerador de sinal será MySignalEnvelopes.

E será localizado em: Include\Expert\MySignals\MySignalEnvelopes. Vamos especificá-lo:

Fig. 9. Assistente do MQL5. Configuração do local do arquivo incluso.

Fig. 9. Assistente do MQL5. Configuração do local do arquivo incluso.

Após clicar em "Concluir", o Assistente do MQL5 gerará um modelo vazio.

O arquivo MySignalEnvelopes.mqh gerado deve então ser adicionado no armazenamento do MQL5:

Fig. 10. Armazenamento do MQL5. Adicionando o arquivo

Fig. 10. Armazenamento do MQL5. Adicionando o arquivo

Uma vez que o arquivo foi adicionado, precisamos confirmar as alterações para o armazenamento do MQL5:

Fig. 11. Armazenamento do MQL5. Execução das alterações

Fig. 11. Armazenamento do MQL5. Execução das alterações

Depois de completar os passos acima, podemos prosseguir para a modificação do nosso gerador do sinal de negociação.

Uma vez que o gerador está baseado no arquivo \Include\Expert\Signal\SignalEnvelopes.mqh, copiamos todo o conteúdo do arquivo e o passamos ao arquivo gerador, deixando apenas o cabeçalho original:

//+------------------------------------------------------------------+
//|                                            MySignalEnvelopes.mqh |
//|                              Copyright © 2013, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2013, Vladimir Karputov"
#property link      "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.                              |
//| 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 timeseries
   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 timeseries 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 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 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);
  }
//+------------------------------------------------------------------+

Agora, trabalharemos nas modificações de algumas partes do código.

Para evitar confusão, o código modificado será destacado:

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

O código modificado é o código que precisa ser copiado e passado ao gerador do sinal de negociação. Espero que tal destaque ajude você a entender melhor o código.

Uma vez que estamos escrevendo nossa própria classe de gerador de sinal de negociação, o seu nome deve ser diferente do nome da classe base. Substituímos, portanto, CSignalEnvelopes por CMySignalEnvelopes ao longo de todo o código:

Fig. 12. Renomeando a classe

Fig. 12. Renomeando a classe

Para garantir que a classe do gerador do sinal de negociação seja exibida no assistente do MQL5 sob seu nome, altere o nome da classe na parte de descrição

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

para

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

Mude o valor do período MA

//| Parameter=PeriodMA,int,45,Period of averaging                    |

para 13 (esta é apenas a minha sugestão, você pode definir qualquer valor que preferir)

//| Parameter=PeriodMA,int,13,Period of averaging                    |

Além disso, também modificamos o parâmetro de desvio

//| Parameter=Deviation,double,0.15,Deviation                        |

definindo um valor maior

//| Parameter=Deviation,double,1.15,Deviation                        |

De acordo com a nossa lógica de implementação, precisamos declarar uma variável interna que armazenará o indicador para o sinal principal.

Uma vez que esta deve ser uma variável interna (dentro do escopo da classe do gerador do sinal de negociação somente), ela será adicionada à seguinte parte do código:

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
   //--- "weights" of market models (0-100)
   int               m_pattern_0;      // model 0
   CExpertSignal    *m_signal;         // storing the pointer to the main signal

Por favor, observe também que eu apaguei as variáveis​ desnecessárias do código. 

O método para armazenar o indicador para o sinal principal será declarado em outra parte do código - o "método de definição do indicador para o sinal principal". Aqui, também excluí alguns métodos irrelevantes.

public:
                     CMySignalEnvelopes(void);
                    ~CMySignalEnvelopes(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;        }
   //--- methods of adjusting "weights" of market models
   void              Pattern_0(int value)                { m_pattern_0=value;        }
   //--- method of verification of settings
   virtual bool      ValidationSettings(void);
   //--- method of creating the indicator and timeseries
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- methods of checking if the market models are formed
   virtual int       LongCondition(void);
   virtual int       ShortCondition(void);
   //--- method of setting the pointer to the main signal
   virtual bool      InitSignal(CExpertSignal *signal=NULL);

Vamos agora especificar alguns parâmetros modificados no construtor e eliminar as variáveis que não são mais necessárias:

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CMySignalEnvelopes::CMySignalEnvelopes(void) : m_ma_period(13),
                                               m_ma_shift(0),
                                               m_ma_method(MODE_SMA),
                                               m_ma_applied(PRICE_CLOSE),
                                               m_deviation(1.15),
                                               m_pattern_0(50)  

Neste ponto, podemos prosseguir modificando a lógica de geração do sinal de negociação de acordo com o nosso sistema de negociação.

A parte do código responsável por um sinal de compra:

int CMySignalEnvelopes::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);
  }

será como mostrado abaixo, seguindo as mudanças necessárias:

int CMySignalEnvelopes::LongCondition(void) //---buy
  {
   int result=0;
   int idx   =StartIndex();
   double open=Open(idx);
   double close=Close(idx);
   double prlevel;
      if(IS_PATTERN_USAGE(0) && close<open)
        {
         prlevel=GetPriceLevelStopp(open,Open(0));
         m_signal.PriceLevel(prlevel);
         result=m_pattern_0;
        }
//--- return the result
   return(result);
  }

A parte do código responsável por um sinal de venda:

int CMySignalEnvelopes::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);
  }

será como mostrado abaixo, seguindo as mudanças necessárias:

int CMySignalEnvelopes::ShortCondition(void) //---sell
  {
   int result  =0;
   int idx     =StartIndex();
   double open=Open(idx);
   double close=Close(idx);
   double prlevel;
      if(IS_PATTERN_USAGE(0) && close>open)
        {
         prlevel=GetPriceLevelStopp(Open(0),open);
         m_signal.PriceLevel(prlevel);
         result=m_pattern_0;
        }
//--- return the result
   return(result);
  }


8. Alguns comentários sobre a parte do código do sinal

Se a condição necessária para um determinado sinal é alcançada, chamamos o método GetPriceLevelStopp que retorna um número como "20" ou "15" - o valor da distância do preço atual.

Isto é seguido pela chamada do método PriceLevel do objeto m_signal (que define a distância para a determinação do preço do nível da ordem pendente). Deve ser lembrado que m_signal é o objeto da classe CExpertSignal que armazena o indicador para o sinal principal.

O código do método GetPriceLevelStopp é fornecido abaixo:

double CMySignalEnvelopes::GetPriceLevelStopp(double price_0,double min)
  {
   double level;
   double temp;
   temp-=(price_0-min)/PriceLevelUnit();
   level=NormalizeDouble(temp,0);
   return(level);
  }

Precisamos declarar este método no cabeçalho da classe:

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)); }
   double            GetPriceLevelStopp(double price,double min);
  };

Outro método que precisaremos é o método de passagem do indicador para o sinal principal à variável interna:

bool CMySignalEnvelopes::InitSignal(CExpertSignal *signal)
  {
   m_signal=signal;
   return(true);
  }

 Depois disso, devemos criar um Expert Advisor no Assistente do MQL5 e incluir nele o módulo de sinal 'MySignalEnvelopes'.

Nós também precisamos adicionar a chamada do método InitSignal ao código do Expert Advisor gerado usando o Assistente do MQL5:

//--- Set filter parameters
   filter0.PeriodMA(Signal_Envelopes_PeriodMA);
   filter0.Shift(Signal_Envelopes_Shift);
   filter0.Method(Signal_Envelopes_Method);
   filter0.Applied(Signal_Envelopes_Applied);
   filter0.Deviation(Signal_Envelopes_Deviation);
   filter0.Weight(Signal_Envelopes_Weight);
   filter0.InitSignal(signal);
//...

Para melhor visualização da operação do Expert Advisor, eu forneci um breve vídeo:

O código do Expert Advisor gerado usando o Assistente do MQL5, bem como o código do módulo do sinal, estão anexos ao artigo.

Abaixo você pode ver os resultados dos testes do Expert Advisor. Ele foi testado para EURUSD e USDJPY com os seguintes parâmetros: período de teste 2013.01.01 - 2013.09.01, período de tempo - D1, nível de Stop Loss = 85, nível de Take Profit = 195.

Fig. 13. Teste para EURUSD em D1

Fig. 13. Teste para EURUSD em D1

Fig. 14. Teste para USDJPY em D1

Fig. 14. Teste para USDJPY em D1


Conclusão

Acabamos de ver como podemos modificar o código do módulo do sinal de negociação para a implementação da funcionalidade que permite que configuremos ordens pendentes a qualquer distância do preço atual: podendo ser o preço de abertura ou fechamento da barra anterior ou do valor da média móvel. Há uma enorme quantidade de opções. O importante é que você possa definir qualquer preço de abertura para uma ordem pendente.

O artigo demonstrou como podemos acessar o indicador para o sinal principal e, por conseguinte, os métodos da classe CExpertSignal.  Acredito que esse artigo será útil para negociadores que negociam com ordens pendentes.

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

Surpreenda seus clientes MQL5 com um coquetel prático de tecnologias! Surpreenda seus clientes MQL5 com um coquetel prático de tecnologias!
O MQL5 fornece programadores com um conjunto muito completo de funções e IPA baseado em objetos graças aos quais eles podem fazer tudo o que quiserem dentro do ambiente MetaTrader. No entanto, Tecnologia Web é uma ferramenta extremamente versátil hoje em dia que pode vir para o resgate em algumas situações quando você precisa fazer algo muito específico, seja para surpreender seus clientes com algo diferente ou simplesmente por você não ter tempo suficiente para dominar uma parte específica da Biblioteca Padrão MT5. O exercício de hoje o leva através de um exemplo prático de como você pode gerenciar a duração de desenvolvimento, ao mesmo tempo que você também cria um coquetel tecnológico incrível.
Construindo um negociante de notícias automático Construindo um negociante de notícias automático
Essa é a continuação do artigo Outra classe orientada a objeto do MQL5, que mostrou a você como construir um CE orientado a objeto simples do inicio e deu a você algumas dicas sobre programação orientada a objeto. Hoje vou mostrar a você o fundamental técnico necessário para desenvolver um EA capaz de negociar as notícias. Meu objetivo é continuar a dar ideias a você sobre OOP e também cobrir um novo tópico nesta série de artigos, trabalhando com o sistema de arquivo.
Eleve os seus sistemas de negociação lineares ao poder Eleve os seus sistemas de negociação lineares ao poder
O artigo de hoje mostra a programadores MQL5 intermediários como eles podem obter mais lucro de seus sistemas de negociação lineares (Fixed Lot) facilmente implementando a chamada técnica de exponenciação. Isto é porque o crescimento de curva de capital resultante é, em seguida, geométrico, ou exponencial, tendo a forma de uma parábola. Especificamente, implementaremos uma variante MQL5 prática do dimensionamento da posição fracionária fixa desenvolvida por Ralph Vince.
Criando EAs de rede neural usando o assistente do MQL5 e o gerador EA Hlaiman Criando EAs de rede neural usando o assistente do MQL5 e o gerador EA Hlaiman
O artigo descreve um método de criação automatizada de EAs de rede neural usando o assistente do MQL5 e o gerador EA Hlaiman. Ele mostra como você pode facilmente começar a trabalhar com redes neurais, sem ter que aprender todo o corpo de informações teóricas, e escrever o seu próprio código.