English Русский 中文 Español
preview
Implementando uma Estratégia de Trading Rápido com Parabolic SAR e Média Móvel Simples (SMA) em MQL5

Implementando uma Estratégia de Trading Rápido com Parabolic SAR e Média Móvel Simples (SMA) em MQL5

MetaTrader 5Sistemas de negociação | 23 abril 2025, 11:54
30 0
Allan Munene Mutiiria
Allan Munene Mutiiria

Introdução

Este artigo irá guiá-lo pelos processos vitais de testar e otimizar nosso algoritmo de trading. Usaremos o Testador de Estratégias do MQL5 para fazer o backtest do nosso EA contra dados históricos. Em termos simples, vamos verificar o quão bem nosso algoritmo teria se comportado no passado em comparação com as condições reais de mercado. Enquanto discutimos o desempenho do nosso EA, também abordaremos como interpretar várias métricas de desempenho (por exemplo, fator de lucro, drawdown, taxa de acerto, etc.) e o que elas nos dizem sobre a confiabilidade e lucratividade do nosso algoritmo. Ao final deste artigo, teremos uma ideia muito mais clara de como implementar uma estratégia de trading rápido e o que é necessário para garantir seu sucesso. Os seguintes tópicos serão abordados ao longo do artigo:

  1. Introdução à Estratégia de Trading Rápido
  2. Entendendo os Indicadores: Parabolic SAR e SMA
  3. Implementação no MQL5
  4. Testes e Otimização
  5. Conclusão


Uma estratégia de trading rápido foca em lucrar com movimentos rápidos e frequentes do mercado, executando várias negociações em um curto período de tempo, muitas vezes mantendo as posições por menos de uma hora. Essa abordagem contrasta com as estratégias tradicionais que visam tendências de longo prazo, buscando em vez disso explorar pequenas mudanças de preço em ativos que se movem rapidamente. O sucesso dessa estratégia depende da capacidade de processar e responder aos dados de mercado quase instantaneamente, tornando os sistemas automatizados, como Expert Advisors, cruciais para a execução eficiente das negociações.

O ponto chave da eficácia dessa estratégia é o uso de indicadores técnicos, como o Parabolic SAR e a Média Móvel Simples, que ajudam a identificar reversões de tendência e suavizar os dados de preços. Esses indicadores, integrados a um algoritmo de trading de alta frequência, permitem que a estratégia se adapte rapidamente às mudanças de mercado, mantendo a precisão na geração de sinais e execução de negociações. Quando implementada corretamente, o trading rápido pode gerar lucros rápidos, embora exija um gerenciamento cuidadoso de custos e riscos.


Entendendo os Indicadores: Parabolic SAR e SMA

Uma estratégia eficaz de trading rápido requer uma compreensão dos importantes indicadores técnicos que orientam as decisões de trading. Dois guias úteis nesse aspecto são o Parabolic SAR (Stop and Reverse) e a Média Móvel Simples (SMA). A SMA é um dos indicadores de tendência mais antigos e mais usados. O Parabolic SAR é relativamente novo em comparação, mas certamente não é uma ferramenta menos conhecida; ambos os indicadores são muito úteis para determinar as condições do mercado e sinalizar possíveis oportunidades de trading.

Desenhado para seguir tendências, o indicador Parabolic SAR tem como objetivo encontrar e identificar possíveis reversões na direção do preço. Ele funciona traçando uma série de pontos acima ou abaixo do preço, relativos à posição do preço em relação ao SAR (stop and reverse). Se incorporarmos o Parabolic SAR à nossa estratégia de trading, podemos interpretá-lo em relação à série de pontos para decidir comprar, vender ou abrir uma posição vendida no mercado. Se o preço estiver acima dos pontos SAR, estamos em uma tendência de alta; se o preço estiver abaixo dos pontos SAR, estamos em uma tendência de baixa. As configurações padrão do indicador devem ser usadas. Isso é ilustrado abaixo:

CONFIGURAÇÕES DO PARABOLIC SAR

Configuração do indicador Parabolic SAR:

CONFIGURAÇÕES DO PARABOLIC SAR

Outra parte essencial da nossa estratégia de trading é a Média Móvel Simples (SMA). A SMA pega os dados de preços de um período específico e "suaviza" esses dados. Ela nos dá uma visão mais fácil de ler sobre qual é a tendência geral. Também podemos usar a SMA para obter uma leitura ainda mais simples sobre a tendência. Se a SMA estiver subindo, podemos dizer, em termos simples, que o mercado está em uma tendência de alta. Se a SMA estiver caindo, podemos dizer que o mercado está em uma tendência de baixa. A SMA é um filtro de tendência. Ela nos diz se devemos procurar por posições longas (tendência de alta), curtas (tendência de baixa) ou nenhuma operação (quando o preço está oscilando ao redor da linha plana da SMA). Deve ser usada uma média móvel simples de período 60. Isso é ilustrado abaixo:

CONFIGURAÇÕES DA SMA

Configuração do indicador Média Móvel Simples:

CONFIGURAÇÕES DA SMA

Quando usados juntos, o Parabolic SAR e a Média Móvel Simples oferecem uma visão completa das condições do mercado. O SAR pode ser lido para sinais imediatos sobre o que pode estar acontecendo com a tendência atual. Ele pode e frequentemente sinaliza reversões de tendência antes de elas acontecerem. A SMA olha para mais dados ao longo de um período maior e, portanto, confirma a direção da tendência com mais certeza. Quando combinados, temos eles conforme mostrado abaixo:

CONFIGURAÇÃO COMBINADA DO PARABOLIC SAR E SMA

Com a visão geral fornecida da estratégia, vamos agora criar o Expert Advisor da estratégia em MQL5.


Implementação no MQL5

Após aprender todas as teorias sobre a estratégia de trading rápido, vamos então automatizar a teoria e criar um Expert Advisor (EA) em MetaQuotes Language 5 (MQL5) para MetaTrader 5 (MT5).

Para criar um expert advisor (EA), no seu terminal MetaTrader 5, clique na guia Ferramentas e marque Editor de Linguagem MetaQuotes, ou simplesmente pressione F4 no seu teclado. Alternativamente, você pode clicar no ícone IDE (Ambiente de Desenvolvimento Integrado) na barra de ferramentas. Isso abrirá o ambiente MetaQuotes Language Editor, que permite escrever robôs de trading, indicadores técnicos, scripts e bibliotecas de funções.

ABRIR METAEDITOR

Uma vez aberto o MetaEditor, na barra de ferramentas, navegue até a guia Arquivo e marque Novo Arquivo, ou simplesmente pressione CTRL + N, para criar um novo documento. Alternativamente, você pode clicar no ícone Novo na guia de ferramentas. Isso resultará em um pop-up do Assistente MQL.

CRIAR NOVO EA

No Assistente que aparece, marque Expert Advisor (template) e clique em Próximo.

ASSISTENTE MQL

Nas propriedades gerais do Expert Advisor, na seção de nome, forneça o nome do arquivo do seu expert. Note que para especificar ou criar uma pasta, se ela não existir, use a barra invertida antes do nome do EA. Por exemplo, aqui temos "Experts" por padrão. Isso significa que nosso EA será criado na pasta Experts e podemos encontrá-lo lá. As outras seções são bastante diretas, mas você pode seguir o link na parte inferior do Assistente para saber como realizar o processo com precisão.

NOME DO NOVO EA

Depois de fornecer o nome do arquivo desejado do Expert Advisor, clique em Próximo, clique em Próximo novamente e, em seguida, clique em Concluir. Depois de fazer tudo isso, estamos prontos para codificar e programar nossa estratégia.

Primeiro, começamos definindo alguns metadados sobre o Expert Advisor (EA). Isso inclui o nome do EA, as informações de copyright e um link para o site da MetaQuotes. Também especificamos a versão do EA, que é definida como "1.00".

//+------------------------------------------------------------------+
//|                                               #1. RAPID FIRE.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+

#property copyright "Copyright 2024, MetaQuotes Ltd."   // Set the copyright property for the Expert Advisor
#property link      "https://www.mql5.com"              // Set the link property for the Expert Advisor
#property version   "1.00"                              // Set the version of the Expert Advisor

Ao carregar o programa, a informação mostrada abaixo é realizada.

METADADOS DO EA

Primeiro, incluímos uma instância de negociação utilizando #include no início do código fonte. Isso nos dá acesso à classe CTrade, que usaremos para criar um objeto de trade. Isso é crucial, pois precisamos dele para abrir negociações.

#include <Trade/Trade.mqh>   // Include the MQL5 standard library for trading operations
CTrade obj_Trade;            // Create an instance of the CTrade class to handle trade operations

O pré-processador substituirá a linha #include <Trade/Trade.mqh> pelo conteúdo do arquivo Trade.mqh. Os colchetes angulares indicam que o arquivo Trade.mqh será retirado do diretório padrão (geralmente é terminal_installation_directory\MQL5\Include). O diretório atual não está incluído na busca. A linha pode ser colocada em qualquer lugar do programa, mas geralmente todas as inclusões são colocadas no início do código-fonte, para uma melhor estrutura do código e referência mais fácil. A declaração do objeto obj_Trade da classe CTrade nos dará acesso aos métodos contidos nessa classe com facilidade, graças aos desenvolvedores do MQL5.

CLASSE CTRADE

Precisaremos criar identificadores de indicador para que possamos incluir os indicadores necessários na estratégia.

int handleSMA = INVALID_HANDLE, handleSAR = INVALID_HANDLE;  // Initialize handles for SMA and SAR indicators

Aqui, declaramos e inicializamos duas variáveis do tipo inteiro, "handleSMA" e "handleSAR". Essas variáveis servirão como identificadores para dois dos indicadores técnicos que planejamos usar no nosso Expert Advisor. Em MQL5, um identificador é um identificador único atribuído a um indicador quando o criamos utilizando funções específicas do MQL5. Usaremos esses identificadores para fazer referência aos indicadores não pintados em qualquer lugar do programa. Também atribuímos ambos os identificadores à constante INVALID_HANDLE, o que garante que o programa não faça referência a um identificador inválido caso deixemos de verificar a lógica do fluxo do programa após sua compilação. Ambos os indicadores funcionarão sem problemas se os manipulamos corretamente e evitamos fazer referência a um identificador inválido ou fazer qualquer coisa errada sem verificar os identificadores primeiro.

Em seguida, precisaremos criar arrays onde armazenaremos os valores ou dados que recuperamos dos indicadores.

double sma_data[], sar_data[];  // Arrays to store SMA and SAR indicator data

Aqui, definimos dois arrays dinâmicos, "sma_data" e "sar_data", aos quais atribuíremos os pontos de dados gerados pelos indicadores SMA (Média Móvel Simples) e SAR (Parabolic SAR). Atribuímos os valores mais recentes calculados por cada indicador a esses arrays, deixando-os livres para referência e análise dos dados ao gerar sinais de negociação. Os sinais de negociação podem ser gerados a partir do cruzamento da linha de sinal. Para gerar um sinal de negociação com a tendência atual ou uma reversão da tendência atual, podemos usar os valores passados mantidos nesses arrays. Ao usar esses valores passados, devemos ser capazes de interpretar com mais precisão nossos indicadores e a ação de preço do ativo sendo negociado.

Em seguida, precisamos do manipulador de evento OnInit. O manipulador é essencial porque é chamado automaticamente quando o Expert Advisor (EA) é inicializado em um gráfico. Essa função é responsável por configurar o EA, incluindo a criação de identificadores de indicadores necessários, inicialização de variáveis e preparação de recursos. Em outras palavras, OnInit é uma função embutida que garante que tudo esteja corretamente configurado antes que o EA comece a processar os dados do mercado. Isso é o seguinte:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){
   // OnInit is called when the EA is initialized on the chart
//...
}

No manipulador de evento OnInit, precisamos inicializar os identificadores de indicador para que os valores dos dados sejam atribuídos a eles.

   handleSMA = iMA(_Symbol,PERIOD_M1,60,0,MODE_SMA,PRICE_CLOSE);  // Create an SMA (Simple Moving Average) indicator handle for the M1 timeframe

Aqui, usamos a função iMA para criar um identificador para o indicador Média Móvel Simples (SMA). O identificador nos dará acesso aos valores do SMA para qualquer símbolo de negociação e período de tempo que especificarmos. Aqui, configuramos para o símbolo de negociação atual (_Symbol) em um gráfico de 1 minuto (PERIOD_M1), com um período de 60 barras. O parâmetro "0" indica que não há deslocamento no cálculo do SMA, enquanto a solicitação para calcular o modo é especificada pela constante MODE_SMA; portanto, estaremos calculando uma média móvel simples. Finalmente, especificamos o tipo de preço PRICE_CLOSE, o que significa que o indicador será baseado nos preços de fechamento de cada barra. Armazenamos o identificador resultante na variável "handleSMA". Em seguida, criamos o identificador para o indicador Parabolic SAR.

   handleSAR = iSAR(_Symbol,PERIOD_M1,0.02,0.2);                  // Create a SAR (Parabolic SAR) indicator handle for the M1 timeframe

Da mesma forma, criamos um identificador para o indicador Parabolic SAR (SAR) usando a função iSAR. A função iSAR retorna os valores do Parabolic SAR para um símbolo de negociação e período de tempo específicos. No nosso caso, usamos para o símbolo de negociação atual (_Symbol) no gráfico de 1 minuto (PERIOD_M1). Os parâmetros 0.02 e 0.2 definem o passo e o valor máximo do SAR, o que significa que eles controlam a sensibilidade do indicador aos movimentos de preço. O identificador resultante nos permitirá acessar os dados do SAR, que serão centrais para nossa primeira estratégia de negociação, que depende das tendências de mercado e das reversões de preço.

Por padrão, o identificador do indicador começa em 10 e progride com um intervalo de 1. Portanto, se imprimirmos os valores do indicador, devemos obter 10 e 11, já que temos dois identificadores. Para visualizar seus valores, vamos registrá-los.

   Print("SMA Handle = ",handleSMA);
   Print("SAR Handle = ",handleSAR);

Os valores que obtemos são os seguintes:

VALORES DOS IDENTIFICADORES

Agora registramos os valores corretamente. Em seguida, vamos garantir que os identificadores dos indicadores realmente não estejam vazios.

   // Check if the handles for either the SMA or SAR are invalid (indicating failure)
   if (handleSMA == INVALID_HANDLE || handleSAR == INVALID_HANDLE){
      Print("ERROR: FAILED TO CREATE SMA/SAR HANDLE. REVERTING NOW");  // Print error message in case of failure
      return (INIT_FAILED);  // Return failure code, stopping the EA from running
   }

Nesta seção, configuramos um mecanismo para capturar erros críticos que ocorrem durante a criação dos identificadores dos indicadores SMA e SAR. Se esses identificadores não forem criados com sucesso, o Expert Advisor não funcionará corretamente. Portanto, verificamos se "handleSMA" ou "handleSAR" permaneceu igual a INVALID_HANDLE, o que indicaria uma falha na inicialização de um desses dois indicadores. Se encontrarmos que um desses identificadores é inválido, imprimimos uma mensagem de erro ("ERRO: FALHA AO CRIAR IDENTIFICADOR SMA/SAR. REVERTENDO AGORA.") e retornamos o valor INIT_FAILED da função de inicialização. Essas ações, juntas, constituem uma rotina de tratamento de erros adequada e servem para garantir que o EA não tome decisões de negociação inseguras. Em seguida, precisamos configurar os arrays de armazenamento como séries temporais. Isso é alcançado através do seguinte trecho de código:

   // Configure the SMA and SAR data arrays to work as series, with the newest data at index 0
   ArraySetAsSeries(sma_data,true);
   ArraySetAsSeries(sar_data,true);

Configuramos nossos arrays de armazenamento para operar como dados de séries temporais, com as informações mais recentes localizadas no índice 0. Conseguimos isso usando a função ArraySetAsSeries e os dois arrays ("sma_data" e "sar_data") como o primeiro argumento, com o valor verdadeiro como o segundo argumento para garantir que os arrays sejam tratados como séries. Este é um passo necessário para acessar os valores mais recentes dos indicadores nos momentos de decisão ordinária na lógica de negociação, quando os dados representados pelos indicadores seriam passados para a rotina de tomada de decisão de negociação. A próxima parte da lógica faz referência a uma série de valores atuais e passados para os dois indicadores. Finalmente, se chegarmos a este ponto, significa que tudo foi inicializado corretamente e, portanto, retornamos uma instância de inicialização bem-sucedida.

   return(INIT_SUCCEEDED);  // Return success code to indicate successful initialization

Até este ponto, tudo na seção de inicialização funcionou corretamente. O código completo responsável pela inicialização do programa é o seguinte:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){
   // OnInit is called when the EA is initialized on the chart

   handleSMA = iMA(_Symbol,PERIOD_M1,60,0,MODE_SMA,PRICE_CLOSE);  // Create an SMA (Simple Moving Average) indicator handle for the M1 timeframe
   handleSAR = iSAR(_Symbol,PERIOD_M1,0.02,0.2);                  // Create a SAR (Parabolic SAR) indicator handle for the M1 timeframe
   
   Print("SMA Handle = ",handleSMA);
   Print("SAR Handle = ",handleSAR);
   
   // Check if the handles for either the SMA or SAR are invalid (indicating failure)
   if (handleSMA == INVALID_HANDLE || handleSAR == INVALID_HANDLE){
      Print("ERROR: FAILED TO CREATE SMA/SAR HANDLE. REVERTING NOW");  // Print error message in case of failure
      return (INIT_FAILED);  // Return failure code, stopping the EA from running
   }

   // Configure the SMA and SAR data arrays to work as series, with the newest data at index 0
   ArraySetAsSeries(sma_data,true);
   ArraySetAsSeries(sar_data,true);

   return(INIT_SUCCEEDED);  // Return success code to indicate successful initialization
}

Em seguida, passamos para o manipulador de evento OnDeinit, que é uma função chamada quando o programa é desinicializado.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
   // OnDeinit is called when the EA is removed from the chart or terminated
//...
}

A função OnDeinit é invocada quando o Expert Advisor (EA) é removido do gráfico ou quando o terminal é desligado. Precisamos usar esse manipulador de evento para garantir a manutenção correta e o gerenciamento de recursos. Quando o EA termina, devemos liberar quaisquer identificadores para os indicadores que criamos na fase de inicialização. Se não fizermos isso, podemos deixar para trás locais de memória que usamos, o que seria ineficiente; certamente não queremos correr o risco de deixar para trás recursos que não precisamos. É por isso que OnDeinit é importante e por que os passos de limpeza são críticos em qualquer ambiente de programação.

   // Release the indicator handles to free up resources
   IndicatorRelease(handleSMA);
   IndicatorRelease(handleSAR);

Limpamos todos os recursos que reservamos para uso. Para realizar essa limpeza, usamos a função IndicatorRelease, que chamamos separadamente para cada identificador que alocamos e inicializamos, assim como os armazenamos quando começamos a usá-los. Isso garante que liberemos os recursos na ordem inversa de sua alocação. Aqui, olhamos especificamente para os indicadores SMA e SAR. A limpeza é crucial para manter o desempenho da plataforma, especialmente se você estiver usando múltiplos Expert Advisors ou executando a plataforma por períodos prolongados. Portanto, o código completo para liberar os recursos é o seguinte:

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
   // OnDeinit is called when the EA is removed from the chart or terminated

   // Release the indicator handles to free up resources
   IndicatorRelease(handleSMA);
   IndicatorRelease(handleSAR);
}

Em seguida, precisamos verificar as oportunidades de negociação sempre que houver atualizações de preço. Isso é alcançado no manipulador de evento OnTick.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){
   // OnTick is called whenever there is a new market tick (price update)

//...

}

A função manipuladora de eventos, OnTick, executa e processa as informações de preço recentes toda vez que há um novo tick ou uma mudança nas condições do mercado. Ela é uma parte essencial da operação do nosso Expert Advisor (EA) porque é onde executamos nossa lógica de negociação, cujas condições de negociação são, esperamos, estruturadas para gerar negociações lucrativas. Quando os dados de mercado mudam, avaliamos o estado atual do mercado e tomamos decisões sobre abrir ou fechar uma posição. A função é executada sempre que as condições do mercado mudam, garantindo que nossa estratégia opere em tempo real e seja responsiva aos preços atuais e às mudanças nos valores dos nossos indicadores de mercado.

Para manter-se atualizado com as condições atuais do mercado, precisamos obter os valores das cotações de preços atuais.

   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);  // Get and normalize the Ask price
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);  // Get and normalize the Bid price

Aqui, obtemos os preços mais atuais de Ask e Bid para o símbolo negociado. Para obter esses preços, usamos a função SymbolInfoDouble. Para o preço Ask, especificamos SYMBOL_ASK, e para o preço Bid, especificamos SYMBOL_BID. Após obtermos os preços, usamos a função NormalizeDouble para arredondar os preços para o número de casas decimais definido por _Digits. Este passo é crucial porque garante que nossas operações de negociação sejam realizadas usando preços que são tanto padronizados quanto precisos. Se não arredondássemos os preços, imprecisões de ponto flutuante poderiam gerar resultados enganosos nos cálculos dos preços de operação. Em seguida, copiamos os valores dos indicadores para usá-los na análise e nas operações de negociação.

   // Retrieve the last 3 values of the SMA indicator into the sma_data array
   if (CopyBuffer(handleSMA,0,0,3,sma_data) < 3){
      Print("ERROR: NOT ENOUGH DATA FROM SMA FOR FURTHER ANALYSIS. REVERTING");  // Print error if insufficient SMA data
      return;  // Exit the function if not enough data is available
   }

Usamos a função CopyBuffer para recuperar os três valores mais recentes do indicador Média Móvel Simples. A função CopyBuffer recebe como entrada o identificador do indicador SMA, o índice do buffer de dados do SMA, a posição inicial (neste caso, o valor mais recente), o número de valores a serem recuperados (três) e o array para armazenar os dados (sma_data). Depois de copiar os valores do SMA para o array, verificamos se eles foram copiados corretamente. Se houver um erro neste ponto, imprimimos uma mensagem de erro no log e saímos da função para evitar prosseguir com nossa lógica de negociação com dados potencialmente falhos ou incompletos.

Da mesma forma, usamos a função CopyBuffer para recuperar os dados do indicador SAR. O seguinte trecho de código é empregado.

   // Retrieve the last 3 values of the SAR indicator into the sar_data array
   if (CopyBuffer(handleSAR,0,0,3,sar_data) < 3){
      Print("ERROR: NOT ENOUGH DATA FROM SAR FOR FURTHER ANALYSIS. REVERTING");  // Print error if insufficient SAR data
      return;  // Exit the function if not enough data is available
   }

Tudo o que você precisa saber agora é o índice inicial da barra de onde armazenar os dados e o índice do buffer. Vamos visualizá-los abaixo:

ÍNDICES DA BARRA E DO BUFFER

Vamos imprimir seus dados no diário para vermos se obtemos os dados corretamente.

   ArrayPrint(sma_data,_Digits," , ");
   ArrayPrint(sar_data,_Digits," , ");

Usamos a função ArrayPrint para mostrar o conteúdo dos arrays "sma_data" e "sar_data". ArrayPrint é uma função básica que imprime o conteúdo de um array no terminal. É boa para preparar visualizações simples dos dados com os quais estamos trabalhando. Para usar a função, você precisa passar três informações:

  • O array que você deseja imprimir ("sma_data" ou "sar_data").
  • A precisão que você deseja para os valores exibidos (_Digits), o que determina quantas casas decimais serão exibidas.
  • O delimitador a ser usado entre os valores impressos (", ") na saída.

Ao imprimir o conteúdo dos arrays SMA e SAR, podemos acompanhar os números reais que nosso algoritmo está utilizando, o que é útil para fins de depuração. Também podemos verificar esses dados em um backtest para verificar se realmente obtemos os dados necessários.

CONFIRMAÇÃO DOS DADOS

A partir da imagem, podemos ver que os dados foram recuperados e armazenados corretamente. Os dados em vermelho representam os dados da Média Móvel, enquanto os dados em azul representam os dados do SAR. A partir da mira, estamos fazendo referência à segunda barra e ao índice 1. Agora está claro que obtemos 3 valores de dados recuperados, como solicitado. Podemos prosseguir para obter os valores necessários da barra.

   // Get the low prices for the current and previous bars on the M1 timeframe
   double low0 = iLow(_Symbol,PERIOD_M1,0);  // Low of the current bar
   double low1 = iLow(_Symbol,PERIOD_M1,1);  // Low of the previous bar

Aqui, extraímos os preços baixos das barras atuais e anteriores no período de 1 minuto usando a função iLow. O primeiro parâmetro, _Symbol, ajusta-se automaticamente ao instrumento de negociação para o qual o Expert Advisor está operando (por exemplo, EUR/USD). O segundo parâmetro, PERIOD_M1, informa ao sistema que estamos trabalhando no gráfico de 1 minuto; isso é vital porque a estratégia de trading rápido depende de realizar negociações de curto prazo com base em movimentos rápidos de preço. O terceiro parâmetro, 0, em "iLow(_Symbol, PERIOD_M1, 0)", indica que queremos o preço baixo da barra atual que está sendo formada. Da mesma forma, em "iLow(_Symbol, PERIOD_M1, 1)", o 1 sinaliza que queremos o preço baixo da barra anterior já concluída. Armazenamos os valores recuperados nas variáveis do tipo "double" chamadas "low0" e "low1", respectivamente.

Da mesma forma, para recuperar os preços altos das barras atuais e anteriores, uma lógica similar é adotada.

   // Get the high prices for the current and previous bars on the M1 timeframe
   double high0 = iHigh(_Symbol,PERIOD_M1,0);  // High of the current bar
   double high1 = iHigh(_Symbol,PERIOD_M1,1);  // High of the previous bar

Aqui, a única coisa que muda é a função usada, iHigh, que recupera os dados de preço alto para o índice da barra e o período de tempo especificados. Para confirmar se os dados que obtemos estão corretos, vamos imprimi-los novamente usando a função

   Print("High bar 0 = ",high0,", High bar 1 = ",high1);
   Print("Low bar 0 = ",low0,", Low bar 1 = ",low1);

A confirmação dos dados é a seguinte:

CONFIRMAÇÃO DE DADOS DE ALTA E BAIXA

Isso foi um sucesso. Agora podemos passar para a criação da lógica de negociação. No entanto, não precisamos executar a lógica de negociação a cada tick. Portanto, vamos criar um mecanismo para garantir que negociemos apenas uma vez por barra.

   // Define a static variable to track the last time a signal was generated
   static datetime signalTime = 0;
   datetime currTime0 = iTime(_Symbol,PERIOD_M1,0);  // Get the time of the current bar

Nesta seção, criamos uma variável, "signalTime", para acompanhar quando o último sinal de negociação foi gerado. Tornamos esta variável estática para garantir que ela mantenha seu valor entre as chamadas para a função OnTick. Se "signalTime" não tivesse duração de armazenamento estática, ela seria alocada toda vez que a OnTick fosse chamada, e seu valor desapareceria depois que a OnTick terminasse de ser executada. Queremos que o tempo do sinal seja configurado apenas uma vez para cada barra e que ele mantenha seu valor até a próxima barra começar. Assim, definimos seu valor como 0 no início para que ela tenha um valor apenas após o primeiro sinal ser gerado. Para evitar que um segundo (ou múltiplos) sinais sejam gerados durante a mesma barra, vamos comparar o tempo da barra atual com o valor armazenado na variável. Depois disso, podemos agora definir a lógica de negociação.

   // Check for BUY signal conditions:
   // - Current SAR is below the current low (bullish)
   // - Previous SAR was above the previous high (bullish reversal)
   // - SMA is below the current Ask price (indicating upward momentum)
   // - No other positions are currently open (PositionsTotal() == 0)
   // - The signal hasn't already been generated on the current bar
   if (sar_data[0] < low0 && sar_data[1] > high1 && signalTime != currTime0
      && sma_data[0] < Ask && PositionsTotal() == 0){
      Print("BUY SIGNAL @ ",TimeCurrent());  // Print buy signal with timestamp
      signalTime = currTime0;  // Update the signal time to the current bar time
   }

Aqui, verificamos as condições para emitir um sinal de compra com base no comportamento simultâneo dos indicadores Parabolic SAR e SMA, juntamente com algumas outras restrições. Para qualificar um sinal de alta do Parabolic SAR, o valor atual do SAR ("sar_data[0]") deve estar abaixo do preço baixo atual ("low0"). Ao mesmo tempo, o valor anterior do SAR ("sar_data[1]") deve ter estado acima do preço alto anterior ("high1"). Para qualificar um sinal de alta do SMA, o SMA deve estar abaixo do preço Ask atual ("sma_data[0] < Ask").

Além disso, verificamos se não há outras posições abertas (PositionsTotal == 0). Não queremos abrir múltiplas negociações ao mesmo tempo. Em seguida, garantimos que o sinal não tenha sido gerado para a barra atual, comparando "signalTime" com "currTime0". Se todas essas verificações passarem, imprimimos uma mensagem anunciando a geração de um sinal de compra. Também atualizamos a variável de tempo do sinal para o tempo atual. Esse truque simples é o que nos permite limitar a geração de sinais para apenas uma vez por barra. No final, o que estamos fazendo é garantindo que o EA só reaja a determinadas condições de mercado e não faça nenhum trabalho desnecessário. Os resultados que obtemos são os seguintes:

SINAL DE COMPRA

Como obtemos o sinal, vamos então prosseguir para abrir posições de compra.

      obj_Trade.Buy(0.01,_Symbol,Ask,Ask-150*_Point,Ask+100*_Point);  // Execute a buy order with a lot size of 0.01, stop loss and take profit

Aqui, executamos uma ordem de compra usando o método "Buy" da classe CTrade (representada pelo objeto "obj_Trade" que criamos). Aqui está uma explicação dos parâmetros:

  • 0.01: Este é o tamanho do lote da negociação. Aqui, estamos especificando um tamanho de posição pequeno de 0.01 lotes.
  • _Symbol: Este representa o símbolo de negociação (par de moedas, ação, etc.) ao qual o Expert Advisor está anexado. O símbolo é detectado automaticamente usando a variável embutida _Symbol.
  • Ask: Este é o preço no qual a ordem de compra será executada, que é o preço Ask atual no mercado. O preço Ask é normalmente usado para negociações de compra.
  • Ask - 150 * _Point: Este é o nível de stop loss. Definimos o stop loss a 150 pontos abaixo do preço Ask para limitar perdas potenciais no caso de o mercado se mover contra a negociação.
  • Ask + 100 * _Point: Este é o nível de take profit. Definimos o take profit a 100 pontos acima do preço Ask, o que significa que a negociação será automaticamente fechada quando o mercado atingir esse nível de lucro.

Ao colocar esta ordem, estamos instruindo o Expert Advisor a abrir uma negociação de compra no preço Ask atual, com níveis pré-definidos de stop loss e take profit para gerenciar risco e recompensa. O trecho final de código para confirmar os sinais de compra e abrir ordens de compra é o seguinte:

   // Check for BUY signal conditions:
   // - Current SAR is below the current low (bullish)
   // - Previous SAR was above the previous high (bullish reversal)
   // - SMA is below the current Ask price (indicating upward momentum)
   // - No other positions are currently open (PositionsTotal() == 0)
   // - The signal hasn't already been generated on the current bar
   if (sar_data[0] < low0 && sar_data[1] > high1 && signalTime != currTime0
      && sma_data[0] < Ask && PositionsTotal() == 0){
      Print("BUY SIGNAL @ ",TimeCurrent());  // Print buy signal with timestamp
      signalTime = currTime0;  // Update the signal time to the current bar time
      obj_Trade.Buy(0.01,_Symbol,Ask,Ask-150*_Point,Ask+100*_Point);  // Execute a buy order with a lot size of 0.01, stop loss and take profit
   }

Para confirmar um sinal de venda e abrir uma ordem de venda, aplica-se uma lógica semelhante.

   // Check for SELL signal conditions:
   // - Current SAR is above the current high (bearish)
   // - Previous SAR was below the previous low (bearish reversal)
   // - SMA is above the current Bid price (indicating downward momentum)
   // - No other positions are currently open (PositionsTotal() == 0)
   // - The signal hasn't already been generated on the current bar
   else if (sar_data[0] > high0 && sar_data[1] < low1 && signalTime != currTime0
      && sma_data[0] > Bid && PositionsTotal() == 0){
      Print("SELL SIGNAL @ ",TimeCurrent());  // Print sell signal with timestamp
      signalTime = currTime0;  // Update the signal time to the current bar time
      obj_Trade.Sell(0.01,_Symbol,Bid,Bid+150*_Point,Bid-100*_Point);  // Execute a sell order with a lot size of 0.01, stop loss and take profit
   }

Aqui, implementamos uma lógica de negociação de venda que será executada quando condições específicas de mercado estiverem presentes. Primeiro, verificamos se o indicador Parabolic SAR (SAR) sugere uma tendência de baixa. Fazemos isso comparando os dados mais recentes do SAR com os preços das barras. O SAR deve estar acima do preço alto da barra para a vela atual ("sar_data[0] > high0"), e o valor anterior do SAR deve ter estado abaixo do preço baixo da barra anterior ("sar_data[1] < low1"), o que indica uma possível reversão de baixa. A indicação de tendência do SAR pode ser "seguro para negociar" com momentum. Em seguida, verificamos o SMA. Ele deve estar acima do preço Bid ("sma_data[0] > Bid"), o que indica uma possível tendência de baixa "segura para negociar".

Quando todas as condições mencionadas acima forem atendidas, sinalizamos uma venda e registramos isso ("Print("SELL SIGNAL @ ", TimeCurrent())"). A variável "signalTime" registra o horário da barra atual; isso é importante porque devemos garantir que não emitimos mais de um sinal de venda por barra. Para executar a negociação, usamos a função do objeto "obj_Trade.Sell". Entramos sistematicamente no mercado em pontos no tempo quando possíveis reversões de baixa podem ocorrer. Fazemos isso com atenção ao risco que estamos assumindo. E gerenciamos esse risco usando ordens de stop loss e take profit. A configuração de confirmação de venda é a seguinte:

CONFIRMAÇÃO DE CONFIGURAÇÃO DE VENDA

Até este ponto, agora está claro que criamos corretamente o algoritmo do Expert Advisor de Trading Rápido. Assim, o código completo da função OnTick responsável por confirmar negociações e abrir posições é o seguinte:

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){
   // OnTick is called whenever there is a new market tick (price update)

   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);  // Get and normalize the Ask price
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);  // Get and normalize the Bid price

   // Retrieve the last 3 values of the SMA indicator into the sma_data array
   if (CopyBuffer(handleSMA,0,0,3,sma_data) < 3){
      Print("ERROR: NOT ENOUGH DATA FROM SMA FOR FURTHER ANALYSIS. REVERTING");  // Print error if insufficient SMA data
      return;  // Exit the function if not enough data is available
   }

   // Retrieve the last 3 values of the SAR indicator into the sar_data array
   if (CopyBuffer(handleSAR,0,0,3,sar_data) < 3){
      Print("ERROR: NOT ENOUGH DATA FROM SAR FOR FURTHER ANALYSIS. REVERTING");  // Print error if insufficient SAR data
      return;  // Exit the function if not enough data is available
   }
   
   //ArrayPrint(sma_data,_Digits," , ");
   //ArrayPrint(sar_data,_Digits," , ");
   
   // Get the low prices for the current and previous bars on the M1 timeframe
   double low0 = iLow(_Symbol,PERIOD_M1,0);  // Low of the current bar
   double low1 = iLow(_Symbol,PERIOD_M1,1);  // Low of the previous bar

   // Get the high prices for the current and previous bars on the M1 timeframe
   double high0 = iHigh(_Symbol,PERIOD_M1,0);  // High of the current bar
   double high1 = iHigh(_Symbol,PERIOD_M1,1);  // High of the previous bar
   
   //Print("High bar 0 = ",high0,", High bar 1 = ",high1);
   //Print("Low bar 0 = ",low0,", Low bar 1 = ",low1);
   
   // Define a static variable to track the last time a signal was generated
   static datetime signalTime = 0;
   datetime currTime0 = iTime(_Symbol,PERIOD_M1,0);  // Get the time of the current bar

   // Check for BUY signal conditions:
   // - Current SAR is below the current low (bullish)
   // - Previous SAR was above the previous high (bullish reversal)
   // - SMA is below the current Ask price (indicating upward momentum)
   // - No other positions are currently open (PositionsTotal() == 0)
   // - The signal hasn't already been generated on the current bar
   if (sar_data[0] < low0 && sar_data[1] > high1 && signalTime != currTime0
      && sma_data[0] < Ask && PositionsTotal() == 0){
      Print("BUY SIGNAL @ ",TimeCurrent());  // Print buy signal with timestamp
      signalTime = currTime0;  // Update the signal time to the current bar time
      obj_Trade.Buy(0.01,_Symbol,Ask,Ask-150*_Point,Ask+100*_Point);  // Execute a buy order with a lot size of 0.01, stop loss and take profit
   }

   // Check for SELL signal conditions:
   // - Current SAR is above the current high (bearish)
   // - Previous SAR was below the previous low (bearish reversal)
   // - SMA is above the current Bid price (indicating downward momentum)
   // - No other positions are currently open (PositionsTotal() == 0)
   // - The signal hasn't already been generated on the current bar
   else if (sar_data[0] > high0 && sar_data[1] < low1 && signalTime != currTime0
      && sma_data[0] > Bid && PositionsTotal() == 0){
      Print("SELL SIGNAL @ ",TimeCurrent());  // Print sell signal with timestamp
      signalTime = currTime0;  // Update the signal time to the current bar time
      obj_Trade.Sell(0.01,_Symbol,Bid,Bid+150*_Point,Bid-100*_Point);  // Execute a sell order with a lot size of 0.01, stop loss and take profit
   }
}
//+------------------------------------------------------------------+

Parabéns para nós por criar o programa. Agora, precisamos testar o Expert Advisor e otimizá-lo para obter os máximos ganhos. Isso será feito na próxima seção.


Testes e Otimização

Esta seção se concentra nos testes e otimização da nossa estratégia de trading rápido usando o Testador de Estratégias do MetaTrader 5. O teste é essencial porque precisamos garantir que nosso Expert Advisor (EA) esteja funcionando corretamente e que ele esteja se saindo bem em diversas condições de mercado. Para começar a testar nosso EA, precisamos carregá-lo no Testador de Estratégias, escolher o símbolo de negociação e o período de tempo desejados (especificamos o período M1 em nosso código) e definir o período de teste. Ao fazer o backtest do nosso EA, podemos obter uma simulação histórica de como o nosso EA teria se comportado com a estratégia e os parâmetros especificados. Claro, tentamos identificar quaisquer problemas potenciais que possam causar falhas no funcionamento do EA em um cenário de negociação ao vivo. Para abrir o testador de estratégias, clique em "Visualizar" e selecione "Testador de Estratégias".

ABRIR TESTADOR DE ESTRATÉGIAS

Uma vez aberto, navegue até a guia de visão geral, selecione "Visualizar", mude para a guia de configurações, carregue o programa e defina as configurações desejadas. Para o nosso caso, teremos o período de teste apenas para este mês, para trabalharmos com dados pequenos.

CONFIGURAÇÕES DO TESTADOR

Após o teste, temos os seguintes resultados:

RESULTADOS DO TESTADOR

Precisamos analisar cuidadosamente os resultados da fase de teste, concentrando-nos nas métricas de desempenho vitais, como lucro líquido total, drawdown máximo e porcentagem de negociações vencedoras. Esses números nos dirão como nossa estratégia está se saindo (e como está falhando) e nos darão uma ideia de sua robustez geral. Também queremos examinar os relatórios de negociação que o Testador de Estratégias gera. Esses relatórios nos permitirão ver os tipos de negociações que o nosso EA está fazendo (ou não fazendo) e nos darão uma chance de entender seu "raciocínio" quando ele encontra várias condições de mercado. Se não estivermos satisfeitos com os resultados, teremos que revisar a estratégia para procurar melhores conjuntos de parâmetros para os indicadores SMA e SAR. Ou teremos que investigar mais a fundo a lógica geral da estratégia para descobrir por que ela não está se saindo melhor do que está.

Para encontrar a melhor estratégia de negociação, precisamos ajustá-la ao mercado. Para isso, usamos um método chamado "otimização de estratégia". A otimização de estratégia não é algo que fazemos uma vez e esquecemos. Precisamos ver como o sistema se comporta sob diferentes configurações e, em seguida, escolher a configuração que nos dá os resultados mais consistentes em todos os testes que realizamos. Quando testamos uma estratégia dessa forma, estamos efetivamente encontrando os parâmetros ideais e usando-os como chaves para desbloquear a estratégia de negociação que estamos analisando. Depois de encontrar essas chaves, precisamos rodar a estratégia novamente e testá-la em um período de walkforward. Caso contrário, não seremos melhores do que alguém que apenas chuta a direção futura do mercado. Para otimizar o sistema, precisaremos de algumas entradas para onde as iterações podem ocorrer. A lógica a seguir é implementada.

input int sl_points = 150; // Stoploss points
input int tp_points = 100; // Takeprofit points

Após a otimização, temos os seguintes resultados:

RESULTADOS DA OTIMIZAÇÃO

O gráfico dos resultados otimizados se parece com o abaixo:

GRÁFICO DE OTIMIZAÇÃO

Finalmente, o relatório de teste é mostrado abaixo:

RELATÓRIO FINAL DE TESTE


Conclusão

Neste artigo, discutimos o desenvolvimento de um Expert Advisor de Trading Rápido (EA) em MQL5, que executa negociações curtas e rápidas. A estratégia depende de dois indicadores técnicos principais: o Parabolic SAR, que sinaliza reversões de tendência, e a Média Móvel Simples (SMA), que avalia o momentum do mercado. Esses indicadores formam o núcleo da lógica de negociação do EA.

Abordamos os detalhes da implementação, incluindo a configuração dos indicadores, criação de identificadores de dados e gerenciamento de negociações para garantir que o EA interaja efetivamente com o mercado. Por fim, enfatizamos a importância de testar e otimizar o EA usando o Testador de Estratégias do MetaTrader 5 para garantir que ele atenda aos nossos objetivos de negociação. Apesar de ser um sistema automatizado, o processo de desenvolvimento espelha de perto o das estratégias de negociação manuais.

Aviso Legal: As informações ilustradas neste artigo são apenas para fins educacionais. Elas têm como objetivo mostrar como criar um Expert Advisor de Estratégia de Trading Rápido (EA) baseado na abordagem de Price Action e, assim, devem ser usadas como base para criar um melhor expert advisor com mais otimização e extração de dados. As informações apresentadas não garantem quaisquer resultados de negociação.

Esperamos que você tenha achado o artigo útil, divertido e fácil de entender, de uma forma que possa usar o conhecimento apresentado no desenvolvimento de futuros expert advisors. Tecnicamente, isso facilita sua forma de analisar o mercado com base na abordagem de Price Action e, particularmente, na estratégia de Trading Rápido. Aproveite.


Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/15698

Arquivos anexados |
Redes neurais em trading: Modelo hiperbólico de difusão latente (Conclusão) Redes neurais em trading: Modelo hiperbólico de difusão latente (Conclusão)
A aplicação de processos de difusão anisotrópicos para codificação dos dados brutos no espaço latente hiperbólico, conforme proposto no framework HypDiff, contribui para a preservação das características topológicas da situação atual do mercado e melhora a qualidade de sua análise. No artigo anterior, iniciamos a implementação das abordagens propostas usando MQL5. Hoje, continuaremos esse trabalho iniciado, levando-o até sua conclusão lógica.
Técnicas do MQL5 Wizard que você deve conhecer (Parte 35): Regressão por Vetores de Suporte Técnicas do MQL5 Wizard que você deve conhecer (Parte 35): Regressão por Vetores de Suporte
A Regressão por Vetores de Suporte é uma maneira idealista de encontrar uma função ou 'hiperplano' que melhor descreva a relação entre dois conjuntos de dados. Tentamos explorar isso na previsão de séries temporais dentro das classes personalizadas do MQL5 wizard.
Algoritmo de Busca Orbital Atômica — Atomic Orbital Search (AOS) Algoritmo de Busca Orbital Atômica — Atomic Orbital Search (AOS)
O artigo aborda o algoritmo AOS (Atomic Orbital Search), que utiliza conceitos do modelo orbital atômico para simular a busca por soluções. O algoritmo se baseia em distribuições probabilísticas e na dinâmica das interações dentro de um átomo. O artigo discute detalhadamente os aspectos matemáticos do AOS, incluindo a atualização das posições dos candidatos a soluções e os mecanismos de absorção e emissão de energia. O AOS abre novos caminhos para a aplicação de princípios quânticos em tarefas computacionais, oferecendo uma abordagem inovadora para a otimização.
Métodos de otimização da biblioteca Alglib (Parte II) Métodos de otimização da biblioteca Alglib (Parte II)
Neste artigo, continuaremos a análise dos métodos de otimização restantes da biblioteca ALGLIB, com foco especial em seus testes em funções complexas e multidimensionais. Isso nos permitirá não apenas avaliar a eficiência de cada algoritmo, mas também identificar seus pontos fortes e fracos em diferentes condições.