Construa Expert Advisors Auto-Otimizáveis em MQL5 (Parte 2): Estratégia de Scalping USDJPY
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.

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.

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. 
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.

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?

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.

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.

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.

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.

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.

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.

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
Aviso: Todos os direitos sobre esses materiais pertencem à MetaQuotes Ltd. É proibida a reimpressão total ou parcial.
Esse artigo foi escrito por um usuário do site e reflete seu ponto de vista pessoal. A MetaQuotes Ltd. não se responsabiliza pela precisão das informações apresentadas nem pelas possíveis consequências decorrentes do uso das soluções, estratégias ou recomendações descritas.
Do básico ao intermediário: Filas, Listas e Árvores (VIII)
Redes neurais em trading: Ator–Diretor–Crítico (Actor–Director–Critic)
Simulação de mercado: Position View (XIX)
Otimização de recifes de coral — Coral Reefs Optimization (CRO)
- 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
Posso testar o EA? Fiz o download, mas, por algum motivo, ele não está aparecendo em EA. Qualquer ajuda é muito bem-vinda. Obrigado.