
Assistente MQL5: Como ensinar um EA a abrir ordens pendentes a qualquer preço
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
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
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
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:
- 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.
- 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
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
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
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
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.
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
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
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
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. 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





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