
Automatizando Estratégias de Negociação com a Estratégia Parabolic SAR em MQL5: Criando um Expert Advisor Eficaz
Introdução
As estratégias de negociação algorítmica revolucionaram imensamente o comércio financeiro ao permitir que os traders tomassem decisões informadas rapidamente. Isso ajudou a eliminar erros humanos e viéses emocionais, pois os sistemas automatizados seguem parâmetros pré-determinados no ambiente de mercado dinâmico. Portanto, no trading automatizado, existe consistência, pois o sistema usa a mesma lógica para executar negociações a cada vez.
É uma prática comum construir e implementar técnicas automatizadas usando o MetaTrader 5. Este artigo explora profundamente o processo de criação de um Expert Advisor (EA) que utiliza o indicador Parabolic SAR para executar negociações automaticamente.
Visão Geral da Estratégia Parabolic SAR
Indicador Parabolic SAR. Este indicador foi inventado em 1978 por Welles Wilder. O indicador destaca os pontos de possível reversão na tendência de mercado por meio de uma série de pontos em um gráfico que segue o movimento do preço acima e abaixo. Quando os pontos estão abaixo do preço, o mercado está em uma tendência de alta; quando estão acima, o mercado está em uma tendência de baixa. Isso o torna particularmente útil para identificar pontos de reversão potenciais, onde uma tendência pode estar chegando ao fim.
Passo SAR: Isso ajuda a determinar quão próximo os pontos SAR estão do preço. O passo mais baixo atrasa os pontos em relação ao preço, diminuindo a sensibilidade. Um passo maior move os pontos mais próximos do preço, aumentando a sensibilidade.
Pontos SAR: Isso age como um fator de aceleração como um limite superior. Em um mercado em tendência, o Parabolic SAR aumenta os passos para acompanhar os preços. Portanto, os traders podem identificar pontos de entrada e saída para potenciais reversões de tendência.
Portanto, os traders podem identificar pontos de entrada e saída para potenciais reversões de tendência.
Implementação no MQL5
No cabeçalho, incluímos metadados básicos, como copyright e número da versão. A biblioteca Trade.mqh é incluída para lidar com as operações de negociação, ou seja, abertura e fechamento de posições.
#property copyright "Copyright 2024, MetaQuotes Ltd." "Duke" #property link "https://www.mql5.com" #property version "1.00" #include <Trade\Trade.mqh>
Agora, vamos definir os parâmetros de entrada que nos permitem personalizar o EA.
Tamanho do Lote: Isso ajuda o EA a determinar o tamanho das negociações. Isso significa que um tamanho de lote pequeno reduzirá os riscos e lucros devido ao tamanho reduzido da negociação. Além disso, se o tamanho do lote for grande, isso significa que haverá riscos e lucros aumentados.
SAR_Step e SAR_Maximum: Eles controlam a sensibilidade do Parabolic SAR na detecção do movimento de preços e no cálculo do indicador Parabolic SAR.
Deslizamento: Isso ajudará o EA a definir o deslizamento máximo permitido ao realizar ordens.
//--- Input parameters input double LotSize = 0.2 ; // Lot size for trading input double SAR_Step = 0.02; // Parabolic SAR step input double SAR_Maximum = 0.2; // Parabolic SAR maximum input int Slippage = 3; // Slippage for orders
Podemos criar uma instância da classe CTrade para gerenciar as operações de negociação.
//--- Trade object
CTrade trade;
Nosso próximo passo é a função OnInit, que é executada quando o EA é carregado. Neste EA simples, ele apenas imprime uma mensagem de confirmação para a inicialização bem-sucedida do log do Expert Advisor (EA). Portanto, vamos verificar se o EA foi carregado e inicializado sem problemas. Essa função também é útil na depuração, garantindo que o EA esteja pronto para começar a processar os dados. A função também pode retornar INIT_FAILED se a inicialização falhar por algum motivo, impedindo o EA de operar.
int OnInit() { //--- Initialization code here Print("Parabolic SAR EA Initialized"); return(INIT_SUCCEEDED); }
Passamos para a função OnDeint. Quando o EA é recompilado, ele é removido do gráfico. Essa ação ativa a função OnDeint para realizar tarefas de limpeza e garantir que os recursos sejam liberados adequadamente. Você pode determinar se o EA foi removido explicitamente, recompilado ou se é resultado do fechamento do terminal observando este log, o que pode fornecer informações úteis durante o estágio de desenvolvimento e teste. Essa função pode ser expandida para quaisquer procedimentos de limpeza necessários. Por exemplo, pode ser necessário fechar recursos abertos, liberar manipuladores de arquivos ou salvar o estado atual.
Isso ajudará a melhorar a confiabilidade e estabilidade, pois garantirá que problemas de desempenho nas primeiras execuções não interfiram na capacidade do EA de recarregar ou reiniciar.
void OnDeinit(const int reason) { //--- Cleanup code here Print("Parabolic SAR EA Deinitialized"); }
Após o OnDeint, olhamos para a função OnTick. Essa função é o núcleo do EA, executada a cada tick de mercado. Ela calcula o valor do Parabolic SAR e o compara com o último preço de fechamento. Com base nessa comparação, o EA determina se deve abrir uma ordem de compra ou venda.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Get the Parabolic SAR value double sar = iSAR(_Symbol, _Period, SAR_Step, SAR_Maximum); // Calculate the Parabolic SAR value double lastPrice = iClose(_Symbol, _Period, 1); // Get the close price of the previous candle //--- Check if there is an existing position if(!IsPositionOpen(_Symbol)) { //--- Determine trade direction based on SAR if(lastPrice > sar) { OpenBuyOrder(); // If the last price is above the SAR, open a buy order } else if(lastPrice < sar) { OpenSellOrder(); // If the last price is below the SAR, open a sell order } } }
Podemos agora detalhar a função OnTick para melhor compreensão.
- O cálculo do Parabolic SAR: A primeira linha do código calcula o valor do Parabolic SAR:
double sar = iSAR(_Symbol, _Period, SAR_Step, SAR_Maximum); // Calculate the Parabolic SAR value
- iSAR(): Esta é uma função incorporada nas plataformas MetaTrader que calcula o valor do indicador Parabolic SAR para um determinado ativo ao longo de um período especificado.
- _Symbol: Refere-se ao instrumento financeiro ou ativo de negociação, como EUR/USD, Ouro ou qualquer outro item de negociação que você está analisando.
- _Período: Isso indica o intervalo de tempo do gráfico (como 1-minuto, 1-hora, 1-dia, etc.) Isso ajuda a função a determinar quais velas usar para calcular o SAR.
- _SAR_Step e SAR Máximo: São parâmetros específicos do indicador Parabolic SAR que controlam sua sensibilidade. O SAR_Step é o valor do passo incremental que acelera o indicador à medida que a tendência avança, enquanto o SAR Máximo limita a aceleração para evitar que o indicador reaja muito rapidamente às mudanças de preço.
- Recuperando o Preço de Fechamento da Última Candeia: A próxima linha recupera o preço de fechamento da última vela completada:
double lastPrice = iClose(_Symbol, _Period, 1); // Get the close price of the previous candle
- iClose(): Esta função retorna o preço de fechamento de uma vela específica no gráfico.
- _Symbol e _Period: Assim como a função iSAR(), isso refere-se ao instrumento financeiro específico e ao intervalo de tempo que está sendo analisado.
- 1: Este parâmetro especifica qual preço de fechamento queremos. Neste caso, 1 indica a última vela completada (a anterior), pois a vela atual ainda está se formando.
Este valor, armazenado na variável LastPrice, representa o nível final de preço no qual o ativo foi negociado quando a última vela foi fechada.
Usamos o código Parabolic SAR para automatizar decisões sobre definir stop-losses e determinar saídas de negociações ou reversões. Por exemplo, se o preço de fechamento cair abaixo do valor do SAR em uma posição longa, isso pode indicar uma reversão de tendência, fazendo com que o trader feche a posição ou considere uma posição curta. O EA usa essa comparação para determinar se o mercado continuará sua tendência ou se reverterá, ajudando a remover as emoções e confiar em sinais claros para negociação.
Ao construir um algoritmo de negociação, é comum implementar uma verificação para ver se uma posição para um ativo específico (símbolo) já está aberta.
//--- Check if there is an existing position if(!IsPositionOpen(_Symbol))
IsPositinOpen(_Symbol): Esta função verifica se há uma posição aberta atualmente para o símbolo _Symbol. O símbolo geralmente representa o código do ticker ou do ativo.
!IsPositionOpen(_Symbol): Isso significa que a condição se torna verdadeira somente se não houver uma posição aberta para o símbolo dado.
A declaração if: Se não houver uma posição aberta para o símbolo dado, o código dentro do bloco if será executado. Isso pode envolver a abertura de uma nova posição, execução de uma negociação ou ativação de outra lógica de negociação.
Portanto, essa função garantirá que não haja overtrading, que seria causado por abrir várias posições para o mesmo símbolo. Isso ajudará o sistema a manter melhor controle sobre a atividade de negociação.
O Parabolic SAR acompanha as tendências, indicando pontos de entrada e saída com um stop-loss móvel que se ajusta com os movimentos de preço. Um cruzamento sinaliza uma possível reversão de tendência.
//--- Determine trade direction based on SAR if(lastPrice > sar) { OpenBuyOrder(); // If the last price is above the SAR, open a buy order } else if(lastPrice < sar) { OpenSellOrder(); // If the last price is below the SAR, open a sell order } } }
LastPrice: Isso representa o preço atual de mercado do ativo sendo negociado.
sar: Este é o valor do Parabolic SAR no momento atual.
Através da comparação dos dois, o algoritmo determina se a tendência é de alta ou de baixa e age de acordo.
A Lógica de Compra e Venda
Ordens de Compra: As ordens de compra são iniciadas quando o preço final excede o valor do SAR, indicando uma tendência de alta. O algoritmo então chama a função OpenBuyOrder() para executar a negociação, com a suposição de que o mercado continuará a subir com o preço acima do SAR.
Ordens de Venda: Por outro lado, se o LastPrice for menor que o SAR, isso é interpretado como um sinal de que o mercado está em uma tendência de baixa. O algoritmo responde chamando a função OpenSellOrder(), iniciando uma negociação de venda. Aqui, a estratégia assume que, como o preço caiu abaixo do SAR, o mercado pode continuar a cair.
O código prioriza a avaliação de uma ordem de compra primeiro. Se a condição para uma ordem de compra (lastPrice > sar) for satisfeita, o sistema executa imediatamente a negociação de compra. Se essa condição não for atendida, o código verifica então a condição para uma venda (lastPrice < sar). Se a condição for verdadeira, uma negociação de venda é executada.
Nosso próximo passo é a função utilitária
Aqui começamos verificando a função OpenPositions. A função IsPositionOpen verifica se já há uma posição aberta para o símbolo de negociação atual. Isso impede que o EA abra várias posições na mesma direção simultaneamente.
//+------------------------------------------------------------------+ //|Check if there is an open position for the given symbol | //+------------------------------------------------------------------+ bool IsPositionOpen(string symbol) { uint total=PositionsTotal(); //Get the total number of open positions for(uint i=0; i<total; i++) { string POSITION_SYMBOL=PositionGetSymbol(i); //Get the symbol of the position if(POSITION_SYMBOL == _Symbol) //Check if the symbol matches the current symbol { return true; } } return false; }
Agora vamos detalhar isso, quebrando o código da função como segue:
- Parâmetros de Entrada: A função recebe um argumento string de símbolo que representa o símbolo desejado, como um par de moedas ou um ticker de ação.
- Obtém o Total de Posições: A função recupera o número total de posições abertas atualmente usando PositionsTotal(). Essa função retorna o número de posições abertas no terminal no momento da execução.
- Itera pelas Posições: Usando um loop for, o código percorre todas as posições abertas. A variável total armazena o número de posições abertas, o loop roda de 0 até total - 1.
- Compara símbolos: O símbolo recuperado, POSITION_SYMBOL, é então comparado com o símbolo atual usando a condição if (POSITION_SYMBOL == _SYMBOL). A variável _Symbol é um identificador predefinido que representa o símbolo do gráfico de onde a função é chamada. Se os símbolos coincidirem, isso indica que já há uma posição aberta para o símbolo dado.
- Valor de Retorno: Se a função encontrar uma correspondência (ou seja, uma posição para o símbolo dado já está aberta), ela retorna true. Se nenhuma posição correspondente for encontrada após o loop ter verificado todas as posições abertas, a função retorna false, indicando que não há posições abertas para o símbolo especificado.
Essa função é particularmente útil para evitar que o algoritmo abra uma nova posição no mesmo ativo quando uma já estiver ativa. Por exemplo, se você estiver negociando "EURUSD" e a função retornar true, a estratégia pode evitar abrir uma nova posição e se concentrar na gestão da posição existente.
Nosso próximo utilitário é OpenBuyOrder(); essa função é responsável por executar uma negociação de compra. Ela tenta abrir uma ordem de compra com um tamanho de lote especificado, enquanto também inclui tratamento de erros para garantir que o processo seja concluído corretamente ou notificar o trader se algo der errado.
//+------------------------------------------------------------------+ //| Open a Buy order | //+------------------------------------------------------------------+ void OpenBuyOrder() { if(trade.Buy(LotSize, NULL, 0, 0, 0, "Buy Order")) { Print("Buy order placed successfully"); } else { Print("Error placing buy order: ", GetLastError()); } }
A função é declarada como void OpenBuyOrder(), o que significa que ela não retorna nenhum valor, mas executa uma tarefa específica, neste caso, colocando uma ordem de compra.
A função usa o método trade.Buy() para executar uma ordem de compra. O método requer os seguintes parâmetros:
- Tamanho do Lote: Isso especifica o tamanho da ordem e, no nosso caso, é 0.2.
- Null: Refere-se ao símbolo atual do gráfico de onde a função é chamada. Neste caso, NULL por padrão é o símbolo no gráfico atual.
- 0: Define o preço no qual a ordem será colocada. Usar zero indica que a ordem será executada ao preço de mercado atual.
- 0: Este parâmetro representa o nível de stop-loss. 0 significa que nenhum stop-loss é especificado quando a ordem é aberta.
- 0: Este parâmetro é o nível de take-profit. Configurar como zero significa que nenhum take-profit é definido inicialmente.
- "Ordem de Compra": Este é o comentário associado à ordem, utilizado para fins de identificação.
Se a ordem for colocada com sucesso (se trade.Buy(...) for avaliado como true), a função chama a função Print() para registrar a mensagem: "Ordem de compra realizada com sucesso". Isso fornece feedback ao trader de que a ordem foi executada com sucesso.
Se a ordem falhar (else), a função registra uma mensagem de erro: "Erro ao realizar a ordem de compra", seguida pelo código de erro específico retornado por GetLastError(). A função GetLastError() recupera o último erro ocorrido no sistema, fornecendo ao trader informações valiosas para solucionar o problema.
Nosso último utilitário é a função para Abrir uma Ordem de Venda: Esta função é projetada para automatizar o processo de abrir uma ordem de venda em um sistema de negociação algorítmica. Essa função reflete a lógica da função OpenBuyOrder(), mas é adaptada para negociações curtas ou ordens de venda no mercado.
//+------------------------------------------------------------------+ //| Open a Sell order | //+------------------------------------------------------------------+ void OpenSellOrder() { if(trade.Sell(LotSize, NULL, 0, 0, 0, "Sell Order")) { Print("Sell order placed successfully"); } else { Print("Error placing sell order: ", GetLastError()); } }
A função void OpenSellOrder() não retorna nenhum valor, mas foca em executar uma tarefa específica: colocar uma ordem de venda.
O método trade.Sell() é usado para iniciar uma ordem de venda. Os parâmetros passados para esse método são os seguintes:
- Tamanho do Lote: Define o número de lotes para a ordem de venda e, no nosso caso, é 0.2.
- NULL: Representa o símbolo do gráfico atual de onde a função está sendo chamada. Passando null, a função por padrão irá negociar o símbolo do gráfico atual.
- 0: Define o preço para a ordem. Usando 0, a ordem será executada ao preço de mercado atual.
- 0: Representa o nível de stop-loss. Um valor de 0 significa que nenhum nível de stop-loss é especificado quando a ordem é aberta.
- 0: Define o nível de take-profit. Um valor de zero significa que nenhum take-profit é configurado inicialmente.
- Ordem de Venda: Este é um comentário anexado à ordem, o que ajuda a identificar e rastrear a ordem.
Se a ordem de venda for colocada com sucesso, ela registra uma mensagem de sucesso usando a função Print(). A mensagem "Ordem de venda realizada com sucesso" aparecerá no log do terminal para confirmar que a negociação foi executada.
Caso a ordem de venda falhe por qualquer motivo, a função registra uma mensagem de erro: "Erro ao realizar a ordem de venda:", seguida pelo código de erro específico retornado por GetLastError(). Isso ajuda a diagnosticar por que a ordem de venda não foi realizada.
Abaixo está o código completo do nosso artigo:
//+------------------------------------------------------------------+ //| ParabolicSAR_EA.mq5 | //| Copyright 2024, MetaQuotes Ltd."Duke" | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Ltd." "Duke" #property link "https://www.mql5.com" #property version "1.00" #include <Trade\Trade.mqh> //--- Input parameters input double LotSize = 0.2 ; // Lot size for trading input double SAR_Step = 0.02; // Parabolic SAR step input double SAR_Maximum = 0.2; // Parabolic SAR maximum input int Slippage = 3; // Slippage for orders //--- Trade object CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Initialization code here Print("Parabolic SAR EA Initialized"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Cleanup code here Print("Parabolic SAR EA Deinitialized"); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Get the Parabolic SAR value double sar = iSAR(_Symbol, _Period, SAR_Step, SAR_Maximum); // Calculate the Parabolic SAR value double lastPrice = iClose(_Symbol, _Period, 1); // Get the close price of the previous candle //--- Check if there is an existing position if(!IsPositionOpen(_Symbol)) { //--- Determine trade direction based on SAR if(lastPrice > sar) { OpenBuyOrder(); // If the last price is above the SAR, open a buy order } else if(lastPrice < sar) { OpenSellOrder(); // If the last price is below the SAR, open a sell order } } } //+------------------------------------------------------------------+ //|Check if there is an open position for the given symbol | //+------------------------------------------------------------------+ bool IsPositionOpen(string symbol) { uint total=PositionsTotal(); //Get the total number of open positions for(uint i=0; i<total; i++) { string POSITION_SYMBOL=PositionGetSymbol(i); //Get the symbol of the position if(POSITION_SYMBOL == _Symbol) //Check if the symbol matches the current symbol { return true; } } return false; } //+------------------------------------------------------------------+ //| Open a Buy order | //+------------------------------------------------------------------+ void OpenBuyOrder() { if(trade.Buy(LotSize, NULL, 0, 0, 0, "Buy Order")) { Print("Buy order placed successfully"); } else { Print("Error placing buy order: ", GetLastError()); } } //+------------------------------------------------------------------+ //| Open a Sell order | //+------------------------------------------------------------------+ void OpenSellOrder() { if(trade.Sell(LotSize, NULL, 0, 0, 0, "Sell Order")) { Print("Sell order placed successfully"); } else { Print("Error placing sell order: ", GetLastError()); } }
Até este ponto, implementamos nosso EA.
Abaixo estão os resultados do backtest:
O teste foi feito no USDJPY em um gráfico M1. O período de teste foi de 01.01.2024 a 05.08.2024. Tipo de modelagem, a cada tick.
Abaixo estão os parâmetros de entrada usados no processo de teste:
Após vários testes em um gráfico M1, percebi que:
- Esta estratégia é adequada para USDJPY e EURUSD.
- Esta estratégia não funciona bem no GBPUSD.
Conclusão
A partir dos resultados, podemos concluir que este Expert Advisor (EA) simples pode garantir bons resultados para o trader se mais refinamentos e adaptações forem feitos no EA para aprimorar sua gestão e também reduzir a exposição dos ativos a riscos elevados. Isso envolverá a implementação de características de gerenciamento de risco, como adicionar um trailing stop que ajudará a melhorar o desempenho do EA ao proteger os lucros à medida que o mercado se move favoravelmente. A otimização de parâmetros, vários testes e ajustes finos nas configurações, como SAR Step e Maximum, serão necessários para um desempenho ideal em diversas condições de mercado.
Aviso Legal: Este código tem o único intuito de ajudar traders a entenderem o básico de como implementar a estratégia Parabolic SAR: Criando um Expert Advisor eficaz. Os resultados da demonstração que obtivemos com nosso backtest não garantem o desempenho futuro do EA no trading.
Testes completos de backtesting e forward testing são cruciais antes do deployment ao vivo, com monitoramento contínuo essencial para evitar perdas inesperadas e fazer ajustes rápidos. Automatizar negociações com esta estratégia pode ajudar a minimizar erros humanos e fadiga, permitindo a criação de um sistema de negociação sofisticado e lucrativo por meio de personalização, otimização e testes. Portanto, adotar esse tipo de automação pode levar a uma capitalização mais eficiente nas oportunidades e melhorar o desempenho das negociações. Até este ponto, o artigo demonstrou e forneceu o conhecimento e as habilidades necessárias para a implementação da Estratégia Parabolic SAR. Outros recursos necessários para a implementação podem ser acessados em nossa plataforma MQL5.
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/15589





- 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