Início Negociação Sistemática Postagem

MACD Sample: Um Guia Prático para o Expert Advisor no MetaTrader 5

Anexo
2154.zip (3.45 KB, Baixar 0 vezes)

O MACD Sample EA vem incluído no pacote padrão do MetaTrader 5 e é um exemplo de EA que realiza operações de trading utilizando o indicador MACD.

O arquivo do MACD Sample.mq5 está localizado na pasta terminal_data_folder/MQL5/Experts/Examples/MACD/. Este Expert Advisor demonstra a abordagem orientada a objetos no desenvolvimento de EAs.

Vamos explorar a estrutura do Expert Advisor e como ele funciona.

1. Propriedades do EA

1.1. Detalhes do EA

//+------------------------------------------------------------------+
//|                                                  MACD Sample.mq5 |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2009-2013, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "5.20"
#property description "Certifique-se de que o expert funcione com um gráfico normal e de que não haja erros na configuração dos parâmetros de entrada (Lots, TakeProfit, TrailingStop). Neste caso, verificamos o TakeProfit em um gráfico com mais de 2 * trend_period barras"

As primeiras cinco linhas contêm um comentário, enquanto as sete linhas seguintes definem as propriedades do programa MQL5 (copyright, link, versão, descrição) usando as diretivas do pré-processador #property.

Quando você executa o Expert Advisor, essas informações são exibidas na aba "Comum":

The MACD Sample Expert Advisor

Figura 1. Parâmetros comuns do EA MACD Sample

1.2. Arquivos Inclusos

Em seguida, a diretiva #include informa ao compilador para incluir os arquivos que contêm classes de negociação da Biblioteca Padrão.

  • Trade.mqh (CTrade - classe para operações de negociação);
  • SymbolInfo.mqh (CSymbolInfo - classe para trabalhar com as propriedades de um instrumento de negociação);
  • PositionInfo.mqh (CPositionInfo - classe para propriedades de posições abertas);
  • AccountInfo.mqh (CAccountInfo - classe para propriedades da conta de negociação).
//--- incluindo arquivos 
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\AccountInfo.mqh>

Instâncias das classes apropriadas são então utilizadas como variáveis membro da classe CExpert (Seção 3).

1.3. Parâmetros de Entrada

Em seguida, temos o tipo, nome, valores padrão e um comentário. O papel deles é demonstrado na figura 2.

//--- Parâmetros de entrada do Expert Advisor
input double InpLots = 0.1; // Lots
input int InpTakeProfit = 50; // Take Profit (em pips)
input int InpTrailingStop = 30; // Nível do Trailing Stop (em pips)
input int InpMACDOpenLevel = 3; // Nível de abertura do MACD (em pips)
input int InpMACDCloseLevel = 2; // Nível de fechamento do MACD (em pips)
input int InpMATrendPeriod = 26; // Período da MA de tendência

Observe que os nomes dos parâmetros de entrada têm o prefixo "Inp". Além disso, as variáveis globais são prefixadas com "Ext". Essa abordagem simplifica o uso de várias variáveis.

O parâmetro InpLots representa o volume de negociação, enquanto InpTakeProfit e InpTrailingStop determinam os níveis de Take Profit e Trailing Stop, respectivamente.

O texto no comentário na linha do parâmetro de entrada, juntamente com os valores padrão, são exibidos na aba "Opções" em vez do nome do parâmetro de entrada:

Figura 2. Parâmetros de entrada do EA MACD Sample

Figura 2. Parâmetros de entrada do EA MACD Sample


1.4. Variáveis Globais

A seguir, a variável global ExtTimeOut é declarada. Ela será utilizada para controlar o tempo de execução das operações de negociação.

int ExtTimeOut=10; // tempo (em segundos) entre operações de negociação

Após a declaração da classe CSampleExpert, na linha 76 outra variável global é declarada: ExtExpert - instância da classe CSampleExpert:

//--- a variável global ExtExpert
CSampleExpert ExtExpert;

O objeto ExtExpert (exemplo da classe CSampleExpert) contém a lógica básica da estratégia de negociação (Seção 3).


2. Funções de Manipulação de Eventos

Funções de Manipulação de Eventos

2.1. A função de inicialização OnInit()

A função OnInit() é chamada uma vez durante a primeira execução do Expert Advisor. Geralmente, no manipulador de eventos OnInit(), o EA é preparado para operação: os parâmetros de entrada são verificados, os indicadores e parâmetros são inicializados, etc. Em caso de erros críticos, quando o trabalho posterior não faz sentido, a função é encerrada com o código de retorno INIT_FAILED.

//+------------------------------------------------------------------+
//| Função de inicialização do Expert                                   |
//+------------------------------------------------------------------+
int OnInit(void)
{
//--- inicialização e criação de todos os objetos necessários
if(!ExtExpert.Init())
return(INIT_FAILED);
//--- inicialização bem-sucedida
return(INIT_SUCCEEDED);
}

No caso, o método Init() do objeto ExtExpert é chamado, que retorna verdadeiro ou falso dependendo da preparação de todos os objetos necessários para a operação (veja a Seção 3.4). Em caso de erro, a função OnInit() é encerrada com o código de retorno INIT_FAILED - essa é a maneira correta de finalizar a operação do EA/indicador em caso de uma inicialização malsucedida.


2.2. A função OnTick()

A função OnTick() é chamada sempre que uma nova cotação é recebida para o símbolo do gráfico em que o EA está rodando.

//+------------------------------------------------------------------+
//| Função de tratamento de novo tick do Expert                                  |
//+------------------------------------------------------------------+
void OnTick(void)
{
static datetime limit_time=0; // armazena o tempo da última chamada + timeout
//--- não operar se o tempo necessário não tiver decorrido
if(TimeCurrent()>=limit_time)
{
//--- verificando os dados
if(Bars(Symbol(),Period())>2*InpMATrendPeriod)
{
//--- após a chamada do método Processing() aumentar o valor de limit_time em ExtTimeOut
if(ExtExpert.Processing())
limit_time=TimeCurrent()+ExtTimeOut;
}
}
}

No manipulador de eventos OnTick() inclui um mecanismo para chamadas periódicas do método ExtExpert.Processing(), que é utilizado para análise de mercado e operações de negociação quando as condições de negociação são atendidas.

O intervalo de tempo entre as chamadas é definido pelo valor do parâmetro de entrada ExtTimeOut.


2.3. A função de desinicialização OnDeInit()

A função OnDeInit() é chamada quando um EA é removido do gráfico. Se um programa coloca objetos gráficos durante a operação, eles podem ser removidos do gráfico.

Neste exemplo, não há função de desinicialização utilizada, nenhuma ação é realizada.


3. A classe CSampleExpert

3.1. A classe CSampleExpert

//+------------------------------------------------------------------+
//| Exemplo da classe MACD Sample EA                                   |
//+------------------------------------------------------------------+
class CSampleExpert
{
protected:
//--- variáveis protegidas - membros da classe estão disponíveis apenas dentro dos métodos da classe
double m_adjusted_point; // um multiplicador para cotações de 3/5 dígitos
CTrade m_trade; // exemplo da classe CTrade
CSymbolInfo m_symbol; // exemplo da classe CSymbolInfo
CPositionInfo m_position; // exemplo da classe CPositionInfo
CAccountInfo m_account; // exemplo da classe CAccountInfo
//--- handles de indicadores
int m_handle_macd; // handle do indicador MACD
int m_handle_ema; // handle do indicador de Média Móvel
//--- buffers de indicadores
double m_buff_MACD_main[]; // buffer da linha principal do indicador MACD
double m_buff_MACD_signal[]; // buffer da linha de sinal do indicador MACD
double m_buff_EMA[]; // buffers do indicador EMA
//--- valores atuais dos indicadores
double m_macd_current;
double m_macd_previous;
double m_signal_current;
double m_signal_previous;
double m_ema_current;
double m_ema_previous;
//--- níveis (em pontos padrões)
double m_macd_open_level;
double m_macd_close_level;
double m_traling_stop;
double m_take_profit;

public:
//--- construtor
CSampleExpert(void);
//--- destrutor
~CSampleExpert(void);
//--- método de inicialização
bool Init(void);
//--- método de desinicialização
void Deinit(void);
//--- método de processamento
bool Processing(void);
protected:
//--- métodos protegidos podem ser acessados apenas dentro dos métodos da classe
bool InitCheckParameters(const int digits_adjust);
bool InitIndicators(void);
bool LongClosed(void);
bool ShortClosed(void);
bool LongModified(void);
bool ShortModified(void);
bool LongOpened(void);
bool ShortOpened(void);
};

A classe EA contém a declaração de variáveis (membros da classe) e funções (métodos da classe).

Para um trabalho mais conveniente com as variáveis, todas as variáveis membro da classe contêm o prefixo m_ (membro), o que indica que é uma variável membro da classe. Antes da declaração de uma variável ou método, seu tipo é especificado (ou valor de retorno para funções).

A visibilidade das variáveis e métodos membros da classe é definida usando modificadores de acesso. Na classe CSampleExpert são utilizados os modificadores protected e public. Todas as variáveis e métodos definidos na seção pública são públicos e acessíveis de fora. A classe CSampleExpert possui cinco desses métodos:

  1. CSampleExpert(void) - um construtor (chamado automaticamente ao criar uma instância da classe);
  2. ~CSampleExpert(void) - um destrutor (chamado automaticamente ao excluir uma instância da classe);
  3. bool Init(void) - método de inicialização, no qual todos os dados necessários para a operação são preparados;
  4. void Deinit(void) - método de desinicialização;
  5. bool Processing(void) - método de processamento.

As variáveis membro da classe CSampleExpert declaradas com o modificador de acesso protected estarão disponíveis apenas dentro dos métodos da classe CSampleExpert (e em classes filhas).

  • double m_adjusted_point - variável multiplicadora para uma operação correta com cotações de 3/5 dígitos;
  • CTrade m_trade - exemplo da classe CTrade;
  • CSymbolInfo m_symbol - exemplo da classe CSymbolInfo;
  • CPositionInfo m_position - exemplo da classe CPositionInfo;
  • CAccountInfo m_account - exemplo da classe CAccountInfo;
  • int m_handle_macd - variável para armazenar o valor do handle do indicador MACD.
  • int m_handle_ema - variável para armazenar o valor do handle do indicador EMA;
  • double m_buff_MACD_main[] - um array dinâmico do tipo double, que é usado para requisitar os valores da linha principal do MACD;
  • double m_buff_MACD_signal[] - um array dinâmico do tipo double, que é usado para requisitar os valores da linha de sinal do MACD;
  • double m_buff_EMA[] - um array dinâmico do tipo double, que é usado para requisitar os valores do indicador EMA;
  • double m_macd_current - usado para armazenar o valor atual da linha principal do MACD;
  • double m_macd_previous - usado para armazenar o valor anterior da linha principal do MACD;
  • double m_signal_current - usado para armazenar o valor atual da linha de sinal do MACD;
  • double m_signal_previous - usado para armazenar o valor anterior da linha de sinal do MACD;
  • double m_ema_current - usado para armazenar o valor atual do indicador EMA;
  • double m_ema_previous - usado para armazenar o valor anterior do indicador EMA;
  • double m_macd_open_level,
  • double m_macd_close_level,
  • double m_traling_stop,
  • double m_take_profit - utilizados para armazenar os valores de níveis de preço (definidos nos parâmetros de entrada) levando em consideração o multiplicador m_adjusted_point.

Os métodos da classe CSampleExpert declarados com o modificador protected:

  1. bool InitCheckParameters(const int digits_adjust) - verifica a correção dos parâmetros de entrada e a inicialização dos parâmetros do EA;
  2. bool InitIndicators(void) - inicialização (criação) dos indicadores MACD e Média Móvel;
  3. bool LongClosed(void) - retorna verdadeiro (e fecha uma posição longa aberta) se as condições para fechamento de uma posição longa forem atendidas;
  4. bool ShortClosed(void) - retorna verdadeiro (e fecha uma posição curta aberta) se as condições para fechamento de uma posição curta forem atendidas;
  5. bool LongModified(void) - retorna verdadeiro (e modifica o preço do Stop Loss) se as condições para alterar o nível do Stop Loss de uma posição longa aberta forem atendidas;
  6. bool ShortModified(void) - retorna verdadeiro (e modifica o preço do Stop Loss) se as condições para alterar o nível do Stop Loss de uma posição curta aberta forem atendidas;
  7. bool LongOpened(void) - retorna verdadeiro (e abre uma posição longa) se as condições para abertura de uma posição longa forem atendidas;
  8. bool ShortOpened(void) - retorna verdadeiro (e abre uma posição curta) se as condições para abertura de uma posição curta forem atendidas.


3.2. Construtor da Classe CSampleExpert

//+------------------------------------------------------------------+
//| Construtor da Classe CSampleExpert                                   |
//+------------------------------------------------------------------+
CSampleExpert::CSampleExpert(void) : m_adjusted_point(0),
 m_handle_macd(INVALID_HANDLE),
 m_handle_ema(INVALID_HANDLE),
 m_macd_current(0),
 m_macd_previous(0),
 m_signal_current(0),
 m_signal_previous(0),
 m_ema_current(0),
 m_ema_previous(0),
 m_macd_open_level(0),
 m_macd_close_level(0),
 m_traling_stop(0),
 m_take_profit(0)
{
 ArraySetAsSeries(m_buff_MACD_main,true);
 ArraySetAsSeries(m_buff_MACD_signal,true);
 ArraySetAsSeries(m_buff_EMA,true);
}

A classe construtora é chamada automaticamente quando um objeto da classe é criado. Ao ser chamada, os valores padrão (entre parênteses) para as variáveis membro da classe são definidos e a direção do índice para m_buff_MACD_main[], m_buff_MACD_signal[], m_buff_EMA[] é configurada.


3.3. Destrutor da Classe CSampleExpert

//+------------------------------------------------------------------+
//| Destrutor da classe CSampleExpert                                   |
//+------------------------------------------------------------------+
CSampleExpert::~CSampleExpert(void)
{
}

O destrutor da classe CSampleExpert não contém nenhum código.


3.4. O Método Init da Classe CSampleExpert

//+------------------------------------------------------------------+
//| Inicialização e verificação de parâmetros de entrada         |
//+------------------------------------------------------------------+
bool CSampleExpert::Init(void)
{
//--- definindo propriedades comuns
 m_symbol.Name(Symbol()); // símbolo
 m_trade.SetExpertMagicNumber(12345); // mágica
//--- considerando cotações de 3/5 dígitos
 int digits_adjust=1;
 if(m_symbol.Digits()==3 || m_symbol.Digits()==5)
 digits_adjust=10;
 m_adjusted_point=m_symbol.Point()*digits_adjust;
//--- definindo os valores dos níveis considerando o modificador m_adjusted_point
 m_macd_open_level =InpMACDOpenLevel*m_adjusted_point;
 m_macd_close_level=InpMACDCloseLevel*m_adjusted_point;
 m_traling_stop =InpTrailingStop*m_adjusted_point;
 m_take_profit =InpTakeProfit*m_adjusted_point;
//--- definindo a slippage de 3 pontos
 m_trade.SetDeviationInPoints(3*digits_adjust);
//---
 if(!InitCheckParameters(digits_adjust))
 return(false);
 if(!InitIndicators())
 return(false);
//--- conclusão bem-sucedida
 return(true);
}

No método Init(), as variáveis membro da classe são inicializadas e os parâmetros de entrada são verificados.

Uma chamada ao método Name() para o objeto m_symbol (CSymbolInfo instancia) define o nome do símbolo sobre o qual o Expert Advisor roda, em seguida o método SetExpertMagicNumber() é chamado; ele define o valor do número mágico do EA para o objeto m_trade (que será usado para operações de negociação). Após isso, o método Digits() é utilizado para requisitar o número de dígitos do símbolo após o ponto decimal e, se necessário, os valores dos níveis são corrigidos.

Em seguida, o método SetDeviationInPoints() do objeto m_trade é chamado, no qual o valor da slippage permitida nas operações de negociação é definido.


3.5. O Método InitCheckParameters da Classe CSampleExpert

//+------------------------------------------------------------------+
//| Verificação de parâmetros de entrada                                    |
//+------------------------------------------------------------------+
bool CSampleExpert::InitCheckParameters(const int digits_adjust)
{
//--- verificando a correção do nível de Take Profit
 if(InpTakeProfit*digits_adjust<m_symbol.StopsLevel())
 {
 printf("Take Profit deve ser maior que %d",m_symbol.StopsLevel());
 return(false);
 }
//--- verificando a correção do nível de Trailing Stop
 if(InpTrailingStop*digits_adjust<m_symbol.StopsLevel())
 {
 printf("Trailing Stop deve ser maior que %d",m_symbol.StopsLevel());
 return(false);
 }
//--- verificando a correção do volume de negociação
 if(InpLots<m_symbol.LotsMin() || InpLots>m_symbol.LotsMax())
 {
 printf("A quantidade de Lots deve estar na faixa de %f a %f",m_symbol.LotsMin(),m_symbol.LotsMax());
 return(false);
 }
 if(MathAbs(InpLots/m_symbol.LotsStep()-MathRound(InpLots/m_symbol.LotsStep()))>1.0E-10)
 {
 printf("A quantidade de Lots não está de acordo com o passo de lot %f",m_symbol.LotsStep());
 return(false);
 }
//--- mostrar aviso se Take Profit<=Trailing Stop
 if(InpTakeProfit<=InpTrailingStop)
 printf("Aviso: Trailing Stop deve ser menor que Take Profit");
//--- conclusão bem-sucedida
 return(true);
}

A correção dos parâmetros de entrada do EA é verificada no método InitCheckParameters(). Se algum dos parâmetros estiver inválido, uma mensagem apropriada aparece e a função retorna false.


3.6. O Método InitIndicators() da Classe CSampleExpert

//+------------------------------------------------------------------+
//| Método de inicialização de indicadores                                 |
//+------------------------------------------------------------------+
bool CSampleExpert::InitIndicators(void)
{
//--- criando o indicador MACD
 if(m_handle_macd==INVALID_HANDLE)
 if((m_handle_macd=iMACD(NULL,0,12,26,9,PRICE_CLOSE))==INVALID_HANDLE)
 {
 printf("Erro ao criar o indicador MACD");
 return(false);
 }
//--- criando o indicador EMA
 if(m_handle_ema==INVALID_HANDLE)
 if((m_handle_ema=iMA(NULL,0,InpMATrendPeriod,0,MODE_EMA,PRICE_CLOSE))==INVALID_HANDLE)
 {
 printf("Erro ao criar o indicador EMA");
 return(false);
 }
//--- conclusão bem-sucedida
 return(true);
}

No método InitIndicators(), a correção dos valores iniciais das variáveis m_handle_macd e m_handle_ema é verificada (elas devem ser iguais a INVALID_HANDLE, pois foram inicializadas no construtor), e os indicadores técnicos MACD e Média Móvel são criados (usando as funções iMACD e iMA). Em caso de sucesso, a função retorna true, e os handles dos indicadores são salvos nas variáveis membro m_handle_macd e m_handle_ema da classe.

Os handles dos indicadores criados serão então usados para verificar a quantidade de dados calculados (BarsCalculated) e obter os valores numéricos (CopyBuffer) dos indicadores no método Processing().


3.7. O Método LongClosed() da Classe CSampleExpert

//+------------------------------------------------------------------+
//| Verificando condições para fechamento de uma posição longa                  |
//+------------------------------------------------------------------+
bool CSampleExpert::LongClosed(void)
{
 bool res=false;
//--- A posição deve ser fechada?
 if(m_macd_current>0)
 if(m_macd_currentm_signal_previous)
 if(m_macd_current>m_macd_close_level)
 {
 //--- fechando a posição
 if(m_trade.PositionClose(Symbol()))
 printf("Posição longa de %s deve ser fechada",Symbol());
 else
 printf("Erro ao fechar a posição de %s : '%s'",Symbol(),m_trade.ResultComment());
 res=true;
 }
//--- retornando o resultado
 return(res);
}

O método LongClosed() retorna verdadeiro (e fecha a posição longa aberta) se as condições para fechamento da posição forem atendidas:

  1. m_macd_current>0 - o valor atual da linha principal do indicador MACD é positivo (o histograma do MACD está acima da linha zero);
  2. m_macd_current<m_signal_current && m_macd_previous>m_signal_previous - a linha principal do indicador MACD cruzou a linha de sinal para baixo.
  3. m_macd_current>m_macd_close_level - o valor atual da linha principal do indicador MACD é maior que m_macd_close_level.


3.8. O Método ShortClosed() da Classe CSampleExpert

//+------------------------------------------------------------------+
//| Verificando condições para fechamento de uma posição curta                 |
//+------------------------------------------------------------------+
bool CSampleExpert::ShortClosed(void)
{
 bool res=false;
//--- A posição deve ser fechada?
 if(m_macd_current<0)
 if(m_macd_current>m_signal_current && m_macd_previousm_macd_close_level)
 {
 //--- fechando a posição
 if(m_trade.PositionClose(Symbol()))
 printf("Posição curta de %s deve ser fechada",Symbol());
 else
 printf("Erro ao fechar a posição de %s : '%s'",Symbol(),m_trade.ResultComment());
 res=true;
 }
//--- retornando o resultado
 return(res);
}

O método ShortClosed() retorna verdadeiro (e fecha uma posição curta aberta) se as condições para fechamento da posição curta forem atendidas:

  1. m_macd_current<0 - o valor atual da linha principal do indicador MACD é negativo (o histograma do MACD está abaixo da linha zero).
  2. m_macd_current>m_signal_current && m_macd_previous<m_signal_previous - a linha principal do indicador MACD cruzou a linha de sinal para cima.
  3. MathAbs(m_macd_current)>m_macd_close_level - o valor atual da linha principal do indicador MACD é maior que m_macd_close_level.


3.9. O Método LongModified() da Classe CSampleExpert

//+------------------------------------------------------------------+
//| Verificando condições para modificação de posição longa               |
//+------------------------------------------------------------------+
bool CSampleExpert::LongModified(void)
{
 bool res=false;
//--- verificando se o Trailing Stop é necessário
 if(InpTrailingStop>0)
 {
 if(m_symbol.Bid()-m_position.PriceOpen()>m_adjusted_point*InpTrailingStop)
 {
 double sl=NormalizeDouble(m_symbol.Bid()-m_traling_stop,m_symbol.Digits());
 double tp=m_position.TakeProfit();
 if(m_position.StopLoss()

O método LongModified() retorna verdadeiro (e modifica o valor do Stop Loss da posição) se as condições para modificação da posição longa forem atendidas: Se o valor do parâmetro de entrada InpTrailingStop>0, então é verificada a passagem do preço por InpTrailingStop pontos a partir do preço de abertura na direção da posição. Em seguida, é calculado o valor do novo nível de Stop Loss e o parâmetro Stop Loss da posição aberta é modificado.


3.10. O Método ShortModified() da Classe CSampleExpert

//+------------------------------------------------------------------+
//| Verificando condições para modificação de posição curta               |
//+------------------------------------------------------------------+
bool CSampleExpert::ShortModified(void)
{
 bool res=false;
//--- verificando se o Trailing Stop é necessário
 if(InpTrailingStop>0)
 {
 if((m_position.PriceOpen()-m_symbol.Ask())>(m_adjusted_point*InpTrailingStop))
 {
 double sl=NormalizeDouble(m_symbol.Ask()+m_traling_stop,m_symbol.Digits());
 double tp=m_position.TakeProfit();
 if(m_position.StopLoss()>sl || m_position.StopLoss()==0.0)
 {
 //--- modificando Stop Loss e Take Profit da posição
 if(m_trade.PositionModify(Symbol(),sl,tp))
 printf("Posição curta de %s deve ser modificada",Symbol());
 else
 {
 printf("Erro ao modificar a posição de %s : '%s'",Symbol(),m_trade.ResultComment());
 printf("Parâmetros de Modificação : SL=%f,TP=%f",sl,tp);
 }
 res=true;
 }
 }
 }
//--- retornando o resultado
 return(res);
}

O método ShortModified() retorna verdadeiro (e modifica o valor do Stop Loss da posição) se as condições para modificação da posição curta forem atendidas: Se o valor do parâmetro de entrada InpTrailingStop>0, então é verificada a passagem do preço por InpTrailingStop pontos a partir do preço de abertura na direção da posição. Em seguida, é calculado o valor do novo nível de Stop Loss e o parâmetro Stop Loss da posição aberta é modificado.


3.11. O Método LongOpened() da Classe CSampleExpert

//+------------------------------------------------------------------+
//| Verificando abertura de posição longa                                  |
//+------------------------------------------------------------------+
bool CSampleExpert::LongOpened(void)
{
 bool res=false;
//--- verificando condições para abertura de posição longa
 if(m_macd_current<0)
 if(m_macd_current>m_signal_current && m_macd_previous(m_macd_open_level) && m_ema_current>m_ema_previous)
 {
 double price=m_symbol.Ask();
 double tp =m_symbol.Bid()+m_take_profit;
//--- verificando margem livre
 if(m_account.FreeMarginCheck(Symbol(),ORDER_TYPE_BUY,InpLots,price)<0.0)
 printf("Não temos dinheiro. Margem Livre = %f",m_account.FreeMargin());
 else
 {
 //--- abrindo uma posição longa
 if(m_trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,InpLots,price,0.0,tp))
 printf("Posição de %s deve ser aberta",Symbol());
 else
 {
 printf("Erro ao abrir posição de COMPRA em %s : '%s'",Symbol(),m_trade.ResultComment());
 printf("Parâmetros de Abertura : preço=%f,TP=%f",price,tp);
 }
 res=true;
 }
 }
//--- retornando o resultado
 return(res);
}

O método LongOpened() retorna verdadeiro (e abre uma posição longa) se as condições para abertura de uma posição de compra forem atendidas:

  1. m_macd_current<0 - o valor atual da linha principal do indicador MACD é negativo (o histograma do MACD está abaixo da linha zero);
  2. m_macd_current>m_signal_current && m_macd_previous<m_signal_previous - a linha principal do indicador MACD cruzou a linha de sinal para cima;
  3. MathAbs(m_macd_current)>m_macd_open_level - o valor atual do módulo da linha principal do indicador MACD é maior que m_macd_open_level;
  4. m_ema_current>m_ema_previous - a EMA está em alta.

Quando todas as condições são atendidas, a margem livre é verificada (o método FreeMarginCheck() da classe CAccountInfo da Biblioteca Padrão) e uma posição longa é aberta usando o método PositionOpen() da classe CTrade.


3.12. O Método ShortOpened da Classe CSampleExpert

//+------------------------------------------------------------------+
//| Verificando abertura de posição curta                                 |
//+------------------------------------------------------------------+
bool CSampleExpert::ShortOpened(void)
{
 bool res=false;
//--- verificando condições para abertura de posição curta
 if(m_macd_current>0)
 if(m_macd_currentm_signal_previous)
 if(m_macd_current>(m_macd_open_level) && m_ema_current

O método ShortOpened() retorna verdadeiro (e abre uma posição curta) se as condições para abertura de uma posição de venda forem atendidas:

  1. m_macd_current>0 - o valor atual da linha principal do indicador MACD é positivo (o histograma do MACD está acima da linha zero);
  2. m_macd_current<m_signal_current && m_macd_previous>m_signal_previous - a linha principal do indicador MACD cruzou a linha de sinal para baixo;
  3. m_macd_current>m_macd_open_level - o valor atual da linha principal do MACD é maior que m_macd_open_level;
  4. m_ema_current<m_ema_previous - a EMA está em baixa.

Quando todas as condições são atendidas, a margem livre é verificada (o método FreeMarginCheck() da classe CAccountInfo da Biblioteca Padrão) e uma posição curta é aberta usando o método PositionOpen() da classe CTrade.


3.13 O Método Processing() da Classe CSampleExpert

//+------------------------------------------------------------------+
//| função principal retorna verdadeiro se alguma posição processada             |
//+------------------------------------------------------------------+
bool CSampleExpert::Processing(void)
{
//--- atualizando cotações
 if(!m_symbol.RefreshRates())
 return(false);
//--- atualizando valores dos indicadores
 if(BarsCalculated(m_handle_macd)<2 || BarsCalculated(m_handle_ema)<2)
 return(false);
 if(CopyBuffer(m_handle_macd,0,0,2,m_buff_MACD_main)!=2 ||
 CopyBuffer(m_handle_macd,1,0,2,m_buff_MACD_signal)!=2 ||
 CopyBuffer(m_handle_ema,0,0,2,m_buff_EMA)!=2)
 return(false);
//--- para simplificar o trabalho com indicadores e para acesso mais rápido
//--- os valores atuais dos indicadores são salvos em variáveis internas (membros da classe)
 m_macd_current =m_buff_MACD_main[0];
 m_macd_previous=m_buff_MACD_main[1];
 m_signal_current =m_buff_MACD_signal[0];
 m_signal_previous=m_buff_MACD_signal[1];
 m_ema_current =m_buff_EMA[0];
 m_ema_previous =m_buff_EMA[1];
//--- a entrada correta no mercado é importante, mas a saída correta é ainda mais importante
//--- primeiro verificamos se há uma posição aberta
 if(m_position.Select(Symbol()))
 {
 if(m_position.PositionType()==POSITION_TYPE_BUY)
 {
 //--- se necessário, tentamos fechar ou modificar uma posição longa
 if(LongClosed())
 return(true);
 if(LongModified())
 return(true);
 }
 else
 {
 //--- se necessário, tentamos fechar ou modificar uma posição curta
 if(ShortClosed())
 return(true);
 if(ShortModified())
 return(true);
 }
 }
//--- sem posições abertas
 else
 {
 //--- verificamos as condições e abrimos uma posição longa, se necessário
 if(LongOpened())
 return(true);
 //--- verificamos as condições e abrimos uma posição curta, se necessário
 if(ShortOpened())
 return(true);
 }
//--- saída sem processamento de posição
 return(false);
}

O método Processing() da classe CSampleExpert é o método do Expert Advisor. O método Processing() é chamado no manipulador de eventos OnTick(), e o intervalo de tempo entre chamadas sucessivas deste método é monitorado (não menos que ExtTimeOut segundos) (seção 2.2).

Ao chamar o método RefreshRates() da classe CSymbolInfo, as cotações são atualizadas. A função BarsCalculated() é usada para requisitar o número de barras para as quais os indicadores MACD e Média Móvel são calculados (seção 3.6.); se o número de barras for menor que 2, a função é encerrada e retorna false.

Em seguida, a função CopyBuffer solicita os dois últimos valores dos indicadores técnicos (as linhas principal e de sinal do MACD e os valores da Média Móvel); e se a quantidade de dados copiados for menor que dois, a função é encerrada. Após isso, os valores dos indicadores dos arrays m_buff_MACD_main[], m_buff_MACD_signal[] e m_buff_EMA[] são copiados para as variáveis m_macd_current, m_macd_previous, m_signal_current, m_signal_previous, m_ema_current e m_ema_previous.

O próximo passo é trabalhar com uma posição, realizada por meio da classe CPositionInfo da Biblioteca Padrão. Se a chamada do método Select() retornou verdadeiro, isto significa que atualmente há uma posição aberta, seu tipo é determinado usando o método PositionType(). O trabalho seguinte é realizado de acordo com o tipo da posição aberta.


4. Teste Retroativo

Os melhores valores dos parâmetros podem ser encontrados utilizando o Testador de Estratégia do terminal MetaTrader 5.

A Figura 3 mostra os resultados do teste do Expert Advisor para 2013 com as configurações padrão.

Figura 3. Resultados de teste retroativo do Expert Advisor MACD Sample

Figura 3. Resultados de teste retroativo do Expert Advisor MACD Sample

Conclusões

O Expert Advisor MACD Sample, incluído no pacote padrão do MetaTrader 5, é um exemplo da abordagem orientada a objetos no desenvolvimento de EAs.


Publicações relacionadas

Comentário (0)