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":

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
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:
- CSampleExpert(void) - um construtor (chamado automaticamente ao criar uma instância da classe);
- ~CSampleExpert(void) - um destrutor (chamado automaticamente ao excluir uma instância da classe);
- bool Init(void) - método de inicialização, no qual todos os dados necessários para a operação são preparados;
- void Deinit(void) - método de desinicialização;
- 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:
- bool InitCheckParameters(const int digits_adjust) - verifica a correção dos parâmetros de entrada e a inicialização dos parâmetros do EA;
- bool InitIndicators(void) - inicialização (criação) dos indicadores MACD e Média Móvel;
- 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;
- 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;
- 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;
- 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;
- bool LongOpened(void) - retorna verdadeiro (e abre uma posição longa) se as condições para abertura de uma posição longa forem atendidas;
- 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:
- m_macd_current>0 - o valor atual da linha principal do indicador MACD é positivo (o histograma do MACD está acima da linha zero);
- 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.
- 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:
- m_macd_current<0 - o valor atual da linha principal do indicador MACD é negativo (o histograma do MACD está abaixo da linha zero).
- 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.
- 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:
- m_macd_current<0 - o valor atual da linha principal do indicador MACD é negativo (o histograma do MACD está abaixo da linha zero);
- 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;
- 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;
- 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:
- m_macd_current>0 - o valor atual da linha principal do indicador MACD é positivo (o histograma do MACD está acima da linha zero);
- 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;
- m_macd_current>m_macd_open_level - o valor atual da linha principal do MACD é maior que m_macd_open_level;
- 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
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
- Baixe Todo o Histórico de Ticks de um Símbolo no MetaTrader 5
- Trader Automático: RSI e MFI com Otimização Automática para MetaTrader 4
- MasterMind 2: O Robô de Trading para MetaTrader 4 que Você Precisa Conhecer
- Template de EA para Análise de Notícias no MetaTrader 4 sem DLL
- Template de EA para Notícias sem DLL - MetaTrader 4