English Русский 中文 Español Deutsch 日本語
preview
Construa Expert Advisors Auto-Otimizáveis em MQL5 (Parte 2): Estratégia de Scalping USDJPY

Construa Expert Advisors Auto-Otimizáveis em MQL5 (Parte 2): Estratégia de Scalping USDJPY

MetaTrader 5Exemplos |
108 3
Gamuchirai Zororo Ndawana
Gamuchirai Zororo Ndawana

Em nossa última discussão sobre a construção de Expert Advisors Auto-Otimizáveis em MQL5, construímos um modelo de regressão linear para criar sinais de entrada e saída para nosso aplicativo de trading. Um link para o artigo anterior pode ser encontrado, aqui. Em retrospecto, talvez não precisemos de todas as partes móveis presentes em um modelo de aprendizado de máquina. Em vez disso, podemos observar modelos de aprendizado de máquina como um exemplo de como resolver problemas do mundo real por meio de regras dinâmicas. Podemos então usar os mesmos princípios simples de pensamento e lógica para potencialmente guiar nossas aplicações de trading para níveis mais altos de lucratividade sem necessariamente criar uma base de código monstruosa para manter.

Para nossa discussão de hoje, nosso objetivo é negociar o par USDJPY de forma lucrativa no time frame diário. Nossa estratégia de negociação será baseada em padrões de candles. Em particular, negociaremos padrões de reversão formados por candles de engolfo. Nossas regras para um candle de engolfo altista serão satisfeitas se o preço de abertura for menor que o fechamento do dia anterior e o preço de fechamento for maior que a abertura do dia anterior. Um exemplo é mostrado na Fig. 1 abaixo. Acredita-se que esses padrões de candles indiquem que determinado nível de preço foi rejeitado com força considerável.

Fig 1: Identificamos um exemplo do nosso padrão de candlestick de alta

Os traders acreditam que padrões de candles de engolfo são um sinal de que uma nova tendência está se formando no mercado. Se forem identificados corretamente, geralmente são seguidos por movimentos consistentes de preço na direção da nova tendência, veja a Fig 2 abaixo. Isso cria a base para a estratégia de trading, tentando identificar corretamente o padrão de negociação. Candles de engolfo de baixa podem ser usados para identificar o início de tendências de baixa, usamos as mesmas regras que acabamos de descrever, mas de forma oposta.

Fig 2: Nosso padrão de candlestick foi confiável neste exemplo em particular

Normalmente, acredita-se que essas estratégias funcionam em todos os períodos de tempo. No entanto, acredito que o gráfico diário pode ser o mais confiável e o selecionei como nosso período de tempo preferido para este exercício. Vamos tentar implementar uma estratégia para negociar sinais de entrada gerados por nossa compreensão desses padrões específicos de mercado. Também estaremos interessados em ver se podemos aumentar nossa lucratividade fazendo ajustes na estratégia original.



Introdução ao MQL5

Nosso programa terá 6 partes principais que precisamos para alcançar nosso objetivo de negociar padrões de candlestick de forma lucrativa.

Parte
Objetivo
Inicialização
Esta parte do nosso sistema será responsável por carregar e definir variáveis globais.

Desinicialização

Liberar recursos que nosso aplicativo não está mais usando, para garantir uma experiência estável ao usuário final.
OnTick
Atualizar variáveis do sistema e escanear o gráfico atual em busca dos nossos padrões de candlestick.
Funções Personalizadas
Executar tarefas especializadas necessárias para alcançar nosso objetivo.
Constantes do Sistema
Constantes que não devem ser alteradas pelo usuário final.
Variáveis Globais
Acompanhar o último tipo de ordem que colocamos, os preços de mercado atuais e os níveis de volatilidade. Variáveis como “trade” e “bid” foram criadas para isso. O Average True Range ajudará a definir stop losses e take profits para nossas posições.

Inicialmente, nossa estratégia só executará operações quando nosso padrão de candlestick for encontrado. Se o padrão for identificado e não tivermos posições abertas, seguiremos o sinal e usaremos o ATR para então definir e ajustar nosso stop loss. Caso contrário, nosso sistema irá gerenciar quaisquer operações que tenhamos aberto. Portanto, as variáveis globais do nosso sistema serão:

Variável
Descrição
trade
Destinada a nos informar o tipo de posição que temos atualmente aberta, isso tornará mais fácil atualizar nossos stops e quaisquer outras tarefas que possamos imaginar no futuro.
atr_handler
Importante para atualizar nossos stop losses consistentemente.
bid, ask
Acompanhando os preços de mercado.

Para começar, construiremos primeiro uma versão de referência da nossa estratégia de negociação. Vamos iniciar definindo as constantes do sistema. Essas constantes serão criadas usando a diretiva #define. A diretiva #define instrui o pré-processador incorporado ao nosso editor MQL5 a substituir qualquer ocorrência do identificador de macro especificado, colocando em seu lugar o valor atribuído à direita desse identificador.

A primeira constante do sistema que definimos é “SYMBOL”. Quando compilarmos nossa aplicação, o pré-processador substituirá todas as ocorrências de “SYMBOL” no código pelo valor “USDJPY”. Esse recurso simples nos oferece controle completo e previsível sobre o sistema e nos garante consistência em nossos testes, atributos que consideramos vantajosos.

//+------------------------------------------------------------------+
//|                                      Dynamic Stops Benchmark.mq5 |
//|                                        Gamuchirai Zororo Ndawana |
//|                          https://www.mql5.com/en/gamuchiraindawa |
//+------------------------------------------------------------------+
#property copyright "Gamuchirai Zororo Ndawana"
#property link      "https://www.mql5.com/en/gamuchiraindawa"
#property version   "1.00"
//+------------------------------------------------------------------+
//| This trading application is intended to serve as our benchmark.  |
//| Our goal is to learn what it will take to surpass the benchmark. |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| System constants                                                 |
//+------------------------------------------------------------------+
#define SYMBOL          "USDJPY"    //--- System pair
#define DAILY           PERIOD_D1   //--- Daily  time frame
#define VOL             0.1         //--- Trading volume
#define ATR_PERIOD      14          //--- Technical Indicator ATR Period
#define ATR_MULTIPLE    2           //--- Stop loss ATR multiple

Também precisaremos carregar a biblioteca de negociação.

//+------------------------------------------------------------------+
//| Libraries                                                        |
//+------------------------------------------------------------------+
#include <Trade/Trade.mqh>
CTrade Trade;

Agora vamos definir nossas variáveis globais. Essas variáveis nos ajudarão a acompanhar nossa posição aberta e as cotações atuais do mercado.

//+------------------------------------------------------------------+
//| Global variables                                                 |
//+------------------------------------------------------------------+
int    trade = 0;
int    atr_handler;
double atr[];
double bid,ask;

Durante a inicialização, chamaremos uma função especializada responsável por inicializar as variáveis do sistema.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   setup();
//---
   return(INIT_SUCCEEDED);
  }

Se não estivermos mais utilizando nossa aplicação de negociação, liberaremos os indicadores técnicos que não estivermos mais usando.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Release the indicator
   release();
  }

Atualizaremos nossas variáveis do sistema uma vez ao final do dia. Isso pode ser ajustado conforme sua preferência para melhorar o gerenciamento de risco. Estou optando por atualizar as variáveis do sistema apenas uma vez ao dia para que os backtests sejam concluídos de forma mais ágil, facilitando a comparação das alterações realizadas.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   update();
  }
//+------------------------------------------------------------------+

A primeira função personalizada que construiremos será responsável por liberar os recursos do sistema que não estivermos mais utilizando.

//+------------------------------------------------------------------+
//| Custom Functions                                                 |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Release variables we don't need                                  |
//+------------------------------------------------------------------+
void release(void)
  {
   IndicatorRelease(atr_handler);
  }

Atualizar nossas variáveis do sistema uma vez ao dia.

//+------------------------------------------------------------------+
//| Update system                                                    |
//+------------------------------------------------------------------+
void update(void)
  {
   static datetime daily_timestamp;
   datetime daily_time = iTime(SYMBOL,DAILY,0);
   if(daily_timestamp != daily_time)
     {
      //--- Update the time
      daily_timestamp = daily_time;
      //--- Update system variables
      daily_update();
      //--- Do we have an oppurtunity to trade?
      if((PositionsTotal() == 0))
         find_setup();
      //--- Do we have positions to manage?
      if(PositionsTotal() > 0)
         manage_setup();
     }
  }

Gerenciar nossas operações atualizando o stop loss e o take profit apenas se a nova posição desses níveis for mais lucrativa.

//+------------------------------------------------------------------+
//| Manage our trades                                                |
//+------------------------------------------------------------------+
void manage_setup(void)
  {
//--- Select the position
   if(PositionSelect(SYMBOL))
     {
      //--- Get ready to update the SL/TP
      double initial_sl  = PositionGetDouble(POSITION_SL);
      double initial_tp  = PositionGetDouble(POSITION_TP);
      double buy_sl      = (ask - (ATR_MULTIPLE * atr[0]));
      double sell_sl     = (bid + (ATR_MULTIPLE * atr[0]));
      double buy_tp      = (ask + (ATR_MULTIPLE * atr[0]));
      double sell_tp     = (bid - (ATR_MULTIPLE * atr[0]));
      double new_sl      = ((trade == 1) && (initial_sl <  buy_sl))? (buy_sl) : ((trade == -1) && (initial_sl > sell_sl)) ? (sell_sl) : (initial_sl);
      double new_tp      = ((trade == 1) && (initial_tp <  buy_tp))? (buy_tp) : ((trade == -1) && (initial_tp > sell_tp)) ? (sell_tp) : (initial_tp);
      //--- Update the position
      Trade.PositionModify(SYMBOL,new_sl,new_tp);
     }
  }

Configurar os indicadores técnicos. Até agora, temos apenas 1 indicador técnico para gerenciar.

//+------------------------------------------------------------------+
//| Get our technical indicators ready                               |
//+------------------------------------------------------------------+
void setup(void)
  {
   atr_handler         = iATR(SYMBOL,DAILY,ATR_PERIOD);
  }

Atualizar o estado do sistema.

//+------------------------------------------------------------------+
//| Daily update routine                                             |
//+------------------------------------------------------------------+
void daily_update(void)
  {
//--- Get current prices
   ask = SymbolInfoDouble(SYMBOL,SYMBOL_ASK);
   bid = SymbolInfoDouble(SYMBOL,SYMBOL_BID);
//--- Update Technical Indicators
   CopyBuffer(atr_handler,0,0,1,atr);
//--- Check for engulfing candles.
   int candles_state = check_candles();
//--- Give feedback
   Comment("Candle State: ",candles_state);
  }

Verificar nosso padrão de candlestick. Se o padrão for encontrado, retornaremos 1 ou -1 e abriremos uma operação de compra ou venda. Caso contrário, aguardaremos.

//+------------------------------------------------------------------+
//| Check if we have any engulfing candles                           |
//+------------------------------------------------------------------+
int check_candles(void)
  {
//--- Return 1 if we have a bullish engulfing candle
   if((iOpen(SYMBOL,DAILY,0) < iClose(SYMBOL,DAILY,1)) && (iClose(SYMBOL,DAILY,0) > iOpen(SYMBOL,DAILY,1)))
      return(1);

//--- Return -1 if we have a bearish engulfing candle
   if((iOpen(SYMBOL,DAILY,0) > iClose(SYMBOL,DAILY,1)) && (iClose(SYMBOL,DAILY,0) < iOpen(SYMBOL,DAILY,1)))
      return(-1);

//--- Otherwise return 0
   return(0);
  }

Nosso sistema saberá que encontrou um setup de negociação se o estado do candle não for 0. Caso contrário, não há mais nada a ser feito no momento.

//+------------------------------------------------------------------+
//| Find setup                                                       |
//+------------------------------------------------------------------+
void find_setup(void)
  {
//--- Our sentiment is bullish
   int candles_state = check_candles();
   if(candles_state == 1)
     {
      Trade.Buy(VOL,SYMBOL,ask,(ask - (ATR_MULTIPLE * atr[0])),(ask + (ATR_MULTIPLE * atr[0])),"");
      trade = 1;
     }

//--- Our sentiment is bearish
   if(candles_state == -1)
     {
      Trade.Sell(VOL,SYMBOL,bid,(bid + (ATR_MULTIPLE * atr[0])),(bid - (ATR_MULTIPLE * atr[0])),"");
      trade = -1;
     }
  }
//+------------------------------------------------------------------+

A Fig. 3 abaixo permite visualizar como o sistema é estruturado. Nosso sistema acompanha a presença ou ausência do padrão de candlestick e executa operações caso o padrão seja identificado. Na configuração atual, as posições de stop loss e take profit serão ajustadas uma vez por dia, no final do dia.

Nossa estratégia visualizada

Fig 3: Visualizando nossa estratégia de trading no time frame diário do USDJPY

Testaremos nossa nova estratégia ao longo de 4 anos de dados históricos, de 1º de janeiro de 2020 até o final de novembro de 2024. Se você quiser acompanhar e desejar fazer alterações nessas configurações, certifique-se de também realizar as alterações apropriadas nas variáveis do sistema. Caso contrário, nosso sistema continuará operando o USDJPY no time frame diário, independentemente dos símbolos e time frames que especificarmos.

Configurações do sistema

Fig 4: As configurações primárias para nosso backtest

O atraso aleatório é o mais próximo de cenários reais de negociação e nos permite realizar testes de estresse em nosso sistema. Certifique-se de ajustar o “Depósito” e a alavancagem da conta para corresponder ao setup de negociação desejado, caso esteja considerando utilizar a estratégia na prática.

Nosso segundo conjunto de configurações

Fig 5: Selecionando o tipo de modelagem e o tamanho da conta para nosso backtest

A curva de capital produzida pela estratégia é promissora. Nossa estratégia de scalping aumentou o tamanho da conta em aproximadamente 4% neste backtest. Como em qualquer estratégia de negociação, ela passou por períodos prolongados de perda. Mas o que é bastante notável nesta estratégia é sua capacidade de se recuperar desses períodos de perda.

A lucratividade do nosso sistema

Fig 6: Visualizando o saldo da nossa conta de trading ao longo do tempo

Vamos agora analisar mais de perto o desempenho da nossa estratégia. Em sua forma atual, nossa estratégia teve um índice de Sharpe de 1,12 e uma taxa de sucesso de 44,68%. O que será necessário para reduzir o tamanho da perda média de US$133,22 e aproximá-la de 0, minimizando o impacto sobre o lucro médio?

Nossos resultados do backtest

Fig 7: Uma análise detalhada do desempenho do nosso backtest



Aprimorando nossos resultados

Nosso sistema é lucrativo em seu estado atual. Há alguma alteração que possamos fazer que nos permita exercer mais controle sobre as operações perdedoras? Proponho algumas mudanças para a estratégia original:

Mudança Proposta
 Finalidade Pretendida
Confirmação Adicional
Ao usar uma estratégia de confirmação adicional juntamente com nossa estratégia já lucrativa, podemos potencialmente filtrar mais operações não lucrativas.
Adicionar margem extra ao Stop Loss
Queremos minimizar o número de vezes em que somos retirados de operações vencedoras.
Considerar a Volatilidade do Mercado
Cada mercado possui, potencialmente, níveis únicos de volatilidade. Nossa estratégia de negociação deve tentar considerar os níveis históricos de volatilidade para analisar os níveis de preço atuais com algum contexto, como traders humanos profissionais fazem.

Com sorte, ao implementar essas mudanças, reduziremos nossa proporção de operações não lucrativas. Sempre existe um tradeoff ao tomar essas decisões. Em última análise, nossa nova estratégia ocasionalmente deixará de aproveitar operações lucrativas que nossa antiga estratégia teria executado facilmente.

É lógico que, eventualmente, não exercer controle sobre o tamanho da perda média pode potencialmente nos custar todo o lucro que trabalhamos para acumular. Para realizar as mudanças desejadas, precisaremos introduzir alterações na versão atual do aplicativo.

Mudança no Sistema
Descrição
Novas Variáveis do Sistema
Para considerar a volatilidade do mercado, precisamos primeiro decidir quanto de dados do passado devemos buscar. Isso será tratado por uma nova variável do sistema, apropriadamente chamada de “fetch”. Além disso, precisaremos definir os parâmetros de quaisquer indicadores técnicos que utilizaremos.
Indicadores Técnicos
Podemos obter confirmação adicional utilizando estratégias de negociação baseadas em indicadores técnicos. Hoje, empregaremos uma estratégia de canal de médias móveis. Portanto, criaremos novos manipuladores de indicadores e buffers para armazenar essas novas informações.
Confluência de Sinais
Criaremos uma nova variável global chamada “sentiment”. Seu valor será 1 ou -1 quando tanto nosso padrão de candles quanto nossos indicadores técnicos forem ambos altistas (1) ou ambos baixistas (-1). Caso contrário, seu valor será 0. Nosso sistema somente abrirá operações quando o valor de sentiment for diferente de 0.
Funções Personalizadas
Para alcançar o comportamento desejado do nosso sistema, teremos que estender algumas das funções personalizadas que já criamos, além de desenvolver algumas novas funções.


Visão Geral da Estratégia de Confirmação

Nossa estratégia de confirmação será baseada em estratégias de canal de médias móveis. Essa estratégia é criada por 2 médias móveis que seguem, respectivamente, os preços máximos e mínimos. As 2 médias móveis formam um canal. Observe que as médias móveis não se cruzam. Assim, nossos sinais de entrada são gerados quando um candle se forma totalmente fora da região entre as 2 médias móveis.

A lógica por trás dessa estratégia é que os níveis de preço entre a média móvel superior e inferior são considerados estáveis. Por outro lado, quando os níveis de preço se formam além da região entre as 2 médias, percebemos um desequilíbrio no mercado. A estratégia sugere que isso representa a formação de uma nova tendência na direção do desequilíbrio. A Fig. 8 abaixo mostra como usaríamos a estratégia.

A seta vermelha representa uma região ideal para ter assumido uma posição de venda segundo a estratégia. O setup geralmente é considerado válido até que os níveis de preço retornem ao canal. Nesse ponto, nossas posições podem ser encerradas, e aguardaremos até que o próximo desequilíbrio seja detectado. Esse segundo desequilíbrio é marcado pela seta azul. Como o desequilíbrio ocorreu acima do canal de médias móveis, interpretaríamos isso como um sinal de compra.

Fig 8: Nossa estratégia de canal de médias móveis para identificar pontos de entrada e saída

Ampliaremos a ideia considerando também máximas e mínimas históricas do mercado. Calcularemos o ponto médio formado pelo último ano de máximas e mínimas históricas oferecidas no mercado. Além disso, usaremos essas informações para restringir nosso aplicativo a abrir posições compradas apenas quando o preço de fechamento estiver acima do ponto médio histórico entre máxima e mínima, sendo o oposto verdadeiro para posições vendidas.

A linha horizontal vermelha na Fig. 9 simboliza a média dos preços máximos e mínimos ao longo do último ano. Esse ponto médio é atualizado diariamente pelo nosso sistema e servirá como referência para que o aplicativo interprete os níveis de preço.

Marcando o ponto médio

Fig 9: O ponto médio histórico do último ano até a data, considerando os preços máximos e mínimos oferecidos no mercado.

Tipo de Posição
Novo Critério de Posição
Long
Formou-se um candle de engolfo altista acima do canal de médias móveis e os níveis de preço estão elevados acima dos níveis médios de volatilidade anual.
Short
Formou-se um candle de engolfo baixista acima do canal de médias móveis e os níveis de preço estão elevados acima dos níveis médios de volatilidade anual.

Com sorte, ao usarmos nossas 2 estratégias juntas, poderemos filtrar as operações não lucrativas que atrapalhavam nosso antigo sistema, mantendo ao mesmo tempo as operações lucrativas que desejamos preservar. Vamos começar a implementar essas mudanças para ver o quão eficazes elas serão. Primeiro, devemos definir novas variáveis do sistema que fixarão os períodos do nosso canal de médias móveis e a quantidade de dados históricos que buscaremos para calcular nosso ponto médio.

//+------------------------------------------------------------------+
//|                                  USDJPY Price Action Benchmark 2 |
//|                                        Gamuchirai Zororo Ndawana |
//|                          https://www.mql5.com/en/gamuchiraindawa |
//+------------------------------------------------------------------+
#property copyright "Gamuchirai Zororo Ndawana"
#property link      "https://www.mql5.com/en/gamuchiraindawa"
#property version   "1.00"
//+------------------------------------------------------------------+
//| This trading application is intended to surpass our benchmark.   |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| System constants                                                 |
//+------------------------------------------------------------------+
//--- I have intentionally omitted parts of the system that remained unchanged
#define FETCH           365            //--- How much should we fetch?
#define MA_PERIOD       90             //--- Moving average period

Também precisaremos de algumas variáveis globais adicionais para acompanhar os estados de mercado que definimos.

//+------------------------------------------------------------------+
//| Global variables                                                 |
//+------------------------------------------------------------------+
int    sentiment = 0;
int    trade = 0;
int    ma_high_handler, ma_low_handler;
double ma_high[],ma_low[];

O corpo do nosso aplicativo permanecerá o mesmo. Entretanto, algumas das funções que estão sendo chamadas foram alteradas.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Setup our system varaibles
   setup();
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Release any resources 
   release();
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Update system variables
   update();
  }
//+------------------------------------------------------------------+

Vamos agora revisar as alterações feitas nas funções personalizadas. As duas primeiras mudanças serão o carregamento de nossos indicadores técnicos e sua liberação posteriormente.

//+------------------------------------------------------------------+
//| Custom Functions                                                 |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Release our technical indicators                                 |
//+------------------------------------------------------------------+
void release(void)
  {
   IndicatorRelease(atr_handler);
   IndicatorRelease(ma_low_handler);
   IndicatorRelease(ma_high_handler);
  }

Essas mudanças em nossa base de código caminham lado a lado e são simples de entender.

//+------------------------------------------------------------------+
//| Get our technical indicators ready                               |
//+------------------------------------------------------------------+
void setup(void)
  {
   atr_handler         = iATR(SYMBOL,DAILY,ATR_PERIOD);
   ma_high_handler     = iMA(SYMBOL,DAILY,MA_PERIOD,0,MODE_EMA,PRICE_HIGH);
   ma_low_handler      = iMA(SYMBOL,DAILY,MA_PERIOD,0,MODE_EMA,PRICE_LOW);
  }

Nossa rotina de atualização diária também precisa ser estendida. Agora também nos interessa saber como os níveis atuais de preço se comparam aos níveis históricos de ruído esperados deste mercado. Se nossos padrões de candles e níveis de preço fornecerem um sentimento correspondente, então buscaremos validação de nosso canal de médias móveis para determinar se este é um bom momento para executar nossa operação.

//+------------------------------------------------------------------+
//| Daily update routine                                             |
//+------------------------------------------------------------------+
void daily_update(void)
  {
//--- Get current prices
   ask = SymbolInfoDouble(SYMBOL,SYMBOL_ASK);
   bid = SymbolInfoDouble(SYMBOL,SYMBOL_BID);
//--- Update Technical Indicators
   CopyBuffer(atr_handler,0,0,1,atr);
   CopyBuffer(ma_high_handler,0,0,1,ma_high);
   CopyBuffer(ma_low_handler,0,0,1,ma_low);
//--- Check for engulfing candles.
   int candles_state = check_candles();
//--- Compare current price levels to historical price levels in the market
   int price_state  = check_price_levels();
//--- Check our tech
//--- What is our sentiment?
//--- Our sentiment is well defined.
   if(candles_state == price_state)
      sentiment = candles_state;
//--- Wait.
   if(candles_state != price_state)
      sentiment = 0;
//--- Give feedback
   Comment("Sentiment: ",sentiment,"\nCandle State: ",candles_state,"\nPrice State: ",price_state);
  }

Usaremos o tipo vetor do MQL5 para calcular e acompanhar nossas estatísticas de mercado dinamicamente com facilidade.

//+------------------------------------------------------------------+
//| Check if we are closer to the all time high or low               |
//+------------------------------------------------------------------+
int check_price_levels(void)
  {
//--- Get historical prices
   vector highs = vector::Zeros(FETCH);
   vector lows  = vector::Zeros(FETCH);
   highs.CopyRates(SYMBOL,DAILY,COPY_RATES_HIGH,0,FETCH);
   lows.CopyRates(SYMBOL,DAILY,COPY_RATES_LOW,0,FETCH);

//--- First we shall calculate the mid point between the all time high and low
   vector mid = ((highs + lows) / 2);

//--- Return 1 if we are above the mid point
   if(iClose(SYMBOL,DAILY,0) > mid.Mean())
      return(1);

//--- Return -1 if we are above the mid point
   if(iClose(SYMBOL,DAILY,0) < mid.Mean())
      return(-1);

//--- Otherwise return 0
   return(0);
  }

Nossas novas regras para encontrar um setup de operação considerarão 2 filtros adicionais. O nível de preço relativo ao ponto médio anual e o nível de preço relativo ao canal de médias móveis. Se ambas as estratégias estiverem em harmonia, colocaremos nossa operação de acordo.
//+------------------------------------------------------------------+
//| Find setup                                                       |
//+------------------------------------------------------------------+
void find_setup(void)
  {
//--- Our sentiment is bullish
   if(sentiment == 1)
     {
      if((iOpen(SYMBOL,DAILY,0) > ma_high[0]) && (iClose(SYMBOL,DAILY,0) > ma_high[0]))
        {
         Trade.Buy(VOL,SYMBOL,ask,(ask - (ATR_MULTIPLE * atr[0])),(ask + (ATR_MULTIPLE * atr[0])),"");
         trade = 1;
        }
     }

//--- Our sentiment is bearish
   if(sentiment == -1)
     {
      if((iOpen(SYMBOL,DAILY,0) < ma_low[0]) && (iClose(SYMBOL,DAILY,0) < ma_low[0]))
        {
         Trade.Sell(VOL,SYMBOL,bid,(bid + (ATR_MULTIPLE * atr[0])),(bid - (ATR_MULTIPLE * atr[0])),"");
         trade = -1;
        }
     }
  }
//+------------------------------------------------------------------+

Podemos observar nossa estratégia em ação. Observe que nossa estratégia agora acompanha 3 condições que devem ser atendidas antes de assumirmos qualquer posição. Esperamos que, ao selecionar cuidadosamente as condições corretas, elas não sejam satisfeitas apenas por acaso.

Nossa nova estratégia aprimorada

Fig 10: Estamos realizando o backtest de nossa estratégia revisada de scalping no USDJPY usando dados históricos do mercado.

Como afirmado anteriormente, as configurações referentes à duração e ao período do backtest serão mantidas fixas para garantir consistência entre ambos os testes. Portanto, nossas datas correspondem às datas do teste anterior.

Testando nossa nova estratégia USDJPY

Fig 11: Nossas configurações para o backtest permanecerão fixas em ambos os testes

Lembre-se de que você pode ajustar essas configurações para refletir o ambiente no qual pretende utilizá-las.

Segundo conjunto de entradas para nossa estratégia de scalping do USDJPY

Fig 12: O segundo conjunto de configurações para nosso backtest

A curva de capital produzida por nossa nova estratégia apresenta menos períodos de rebaixamento quando comparada ao nosso primeiro backtest. Por exemplo, no período entre janeiro de 2020 e o final de 2023, a curva de capital produzida por nossa estratégia inicial permaneceu praticamente no mesmo nível, oscilando em torno do saldo inicial. Enquanto isso, nossa nova curva de capital não apresenta essa característica indesejável. Nossa curva de capital cresceu em uma tendência menos volátil de setembro de 2022 até o final do backtest.

A nova curva de capital produzida por nossa estratégia revisada de USDJPY

Fig 13: A curva de capital produzida por nossa estratégia revisada de trading

Após uma inspeção mais detalhada, observamos que atingimos nosso objetivo de reduzir a perda média e a proporção de operações perdedoras mais próximas de 0. Entretanto, reduzimos apenas marginalmente a proporção de operações perdedoras, de cerca de 55% para cerca de 54%. Além disso, nossas mudanças também reduziram a lucratividade da estratégia. Isso não é um problema significativo, pois podemos corrigir isso aumentando com segurança o tamanho do lote. Os mercados são ambientes dinâmicos, e as novas medidas de segurança que implementamos podem se mostrar valiosas no futuro.

Uma análise detalhada do desempenho de nossa nova estratégia de scalping USDJPY

Fig 14: Uma análise detalhada de nossa segunda estratégia de negociação



Conclusão

Neste artigo, abordamos o potencial a ser explorado ao negociar sinais gerados por padrões de candles. Embora existam muitas críticas contra tais estratégias — por exemplo, o fato de que é possível observar o padrão de candle se formar, mas nem sempre ele é seguido pela mesma ação de preço — isso pode gerar dúvidas sobre a validade da estratégia.

No entanto, seguindo os ajustes discutidos nesta estratégia e adicionando sua própria compreensão do mercado, acredito que quaisquer dúvidas sobre a lucratividade da estratégia podem ser razoavelmente eliminadas. O desafio é que nem sempre é evidente para nós como as mudanças que fazemos afetarão a lucratividade da estratégia.

Arquivo
Descrição
Benchmark da Ação do Preço do USDJPY
Este aplicativo era a versão inicial e volátil de nossa estratégia de negociação; ela era mais lucrativa, mas também carregava mais risco.
Estratégia de Ação do Preço USDJPY 2
Esta é a versão refinada da estratégia que construímos juntos; ela é igualmente lucrativa e busca minimizar suas perdas.

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

Últimos Comentários | Ir para discussão (3)
Avijit Barua
Avijit Barua | 24 dez. 2024 em 17:54
Posso testar o EA? Fiz o download, mas, por algum motivo, ele não está aparecendo em EA. Qualquer ajuda é muito bem-vinda.
Gamuchirai Zororo Ndawana
Gamuchirai Zororo Ndawana | 24 dez. 2024 em 18:44
Avi B #:
Posso testar o EA? Fiz o download, mas, por algum motivo, ele não está aparecendo em EA. Qualquer ajuda é muito bem-vinda. Obrigado.
Ei, Avi B, você conseguiu compilá-lo com sucesso?
Juan Luis De Frutos Blanco
Juan Luis De Frutos Blanco | 20 set. 2025 em 23:00
Foi um prazer ver a programação concluída e ver os resultados positivos de outros pares.
Muito obrigado, Gamu, por esse ótimo desenvolvimento.
Do básico ao intermediário: Filas, Listas e Árvores (VIII) Do básico ao intermediário: Filas, Listas e Árvores (VIII)
Neste artigo veremos como implementar um algoritmo de balanceamento da árvore. O que será visto aqui, é a minha proposta para este tipo de mecanismo. Existem diversos outros mecanismos com o mesmo tipo de objetivo. Porém cada um tem seus problemas e suas vantagens. Depende de você, meu caro leitor, estudar e procurar encontrar o que melhor irá lhe atender.
Redes neurais em trading: Ator–Diretor–Crítico (Actor–Director–Critic) Redes neurais em trading: Ator–Diretor–Crítico (Actor–Director–Critic)
Propomos conhecer o framework Actor-Director-Critic, que combina aprendizado hierárquico e uma arquitetura com múltiplos componentes para criar estratégias de trading adaptativas. Neste artigo, analisamos em detalhe como o uso do Diretor para classificar as ações do Ator ajuda a otimizar decisões de trading de forma eficiente e a aumentar a robustez dos modelos nas condições dos mercados financeiros.
Simulação de mercado: Position View (XIX) Simulação de mercado: Position View (XIX)
Uma das coisas que mais tem me incomodado, é o fato da classe C_ElementsTrade, ter em seu código, coisas que permitem acessar as posições. Não entenda isto como uma falha, pois de fato não é. Apenas torna algumas partes do que precisaremos fazer no futuro, algo um tanto quanto sujeitas a erros. Todo o trabalho que tem sido feito, para implementar o indicador de posição. Tem sido feito, pensando em usar ele no replay/simulador. Porém, uma vez que ele esteja sendo usado no replay/simulador. Não teremos de forma alguma acesso a uma posição real. Sendo assim, qualquer chamada da biblioteca MQL5, cujo objetivo é acessar dados da posição. Não terão qualquer efeito no código.
Otimização de recifes de coral — Coral Reefs Optimization (CRO) Otimização de recifes de coral — Coral Reefs Optimization (CRO)
Neste artigo é apresentada uma análise abrangente do algoritmo de otimização de recifes de coral (CRO), um método meta-heurístico inspirado nos processos biológicos de formação e desenvolvimento de recifes de coral. Ele modela aspectos-chave da evolução dos corais: reprodução externa e interna, fixação de larvas, reprodução assexuada e competição por espaço limitado no recife. É dada atenção especial à versão aprimorada do algoritmo.