English Русский 中文 Español Deutsch 日本語
preview
Desenvolvimento de um Kit de Ferramentas para Análise da Ação do Preço (Parte 25): Rompimento de Fractais com EMA Dupla

Desenvolvimento de um Kit de Ferramentas para Análise da Ação do Preço (Parte 25): Rompimento de Fractais com EMA Dupla

MetaTrader 5 — Indicadores |
25 3
Christian Benjamin
Christian Benjamin

Conteúdo



Introdução

Este artigo tem como objetivo apresentar o desenvolvimento de uma ferramenta projetada para auxiliar na análise da ação do preço, oferecendo uma avaliação mais aprofundada e detalhada por meio do indicador Fractals, originalmente desenvolvido por Bill Williams.

Bill M. Williams (1932–2019) foi um influente trader e autor norte-americano, reconhecido por suas contribuições à psicologia do trading, à análise técnica e à teoria do caos aplicada aos mercados financeiros. Ao longo de sua carreira, Williams estudou os mercados de ações, commodities e câmbio (Forex), desenvolvendo uma série de ferramentas inovadoras de análise técnica para identificar tendências e possíveis pontos de reversão. Entre seus indicadores mais conhecidos estão o Accelerator/Decelerator Oscillator, o indicador Alligator, o Awesome Oscillator, o indicador Fractals, o Gator Oscillator e o Market Facilitation Index. Atualmente, esses indicadores são amplamente utilizados nos mercados Forex, de ações e em outros mercados financeiros devido à sua eficácia na análise do comportamento do mercado.

O indicador Fractals, um dos principais componentes da metodologia de Williams, é combinado em nossa abordagem com as Médias Móveis Exponenciais (EMAs) de 14 e 200 períodos. Ao integrar os padrões fractais a esses filtros dinâmicos de tendência, nosso Expert Advisor (EA) foi desenvolvido para identificar com precisão possíveis reversões do mercado, mantendo o alinhamento com a direção da tendência predominante. Essa estratégia combinada aprimora a tomada de decisões de negociação ao permitir a identificação antecipada de sinais de reversão e a confirmação da força da tendência, proporcionando pontos de entrada mais confiáveis e com maior probabilidade de sucesso. A combinação entre a análise de fractais e as médias móveis oferece aos traders uma ferramenta poderosa para interpretar a ação do preço de maneira mais aprofundada, ajudando a otimizar o momento das entradas e melhorar os resultados das operações.


Entendendo a Estratégia

Nosso Expert Advisor (EA) utiliza três indicadores técnicos principais: o indicador Fractals, a EMA 14 e a EMA 200. O indicador Fractals, desenvolvido por Bill Williams, é uma ferramenta bastante utilizada na análise técnica para identificar possíveis reversões de tendência. Ele detecta padrões específicos de preços, chamados fractais, que aparecem como máximas ou mínimas locais, sinalizando possíveis pontos de inflexão no mercado. Esses fractais funcionam como níveis de suporte ou resistência, oferecendo aos traders referências visuais que ajudam a determinar com maior precisão os momentos de entrada e saída das operações.

A Média Móvel Exponencial (EMA) difere fundamentalmente da Média Móvel Simples (SMA) por atribuir maior peso aos dados de preços mais recentes, tornando-se um indicador mais sensível às movimentações do mercado. Essa ponderação é obtida por meio de um fator de suavização que enfatiza exponencialmente os preços recentes, permitindo que a EMA reaja mais rapidamente às mudanças do mercado. Consequentemente, as EMAs são bastante eficazes para identificar tendências emergentes e fornecer sinais antecipados de mudanças de tendência, especialmente em períodos mais curtos.

A EMA 14 reflete o momentum de curto prazo do mercado em nossa configuração, reagindo rapidamente aos movimentos recentes dos preços, o que a torna adequada para identificar entradas oportunas nas operações. Por outro lado, a EMA 200 é um indicador de tendência de longo prazo, que suaviza as oscilações de curto prazo para revelar a direção predominante do mercado. Quando o preço é negociado acima da EMA 200, isso indica uma tendência de alta de longo prazo; quando está abaixo, sugere uma tendência de baixa. Além disso, a EMA 200 frequentemente atua como um nível dinâmico de suporte ou resistência, ajudando os traders a filtrar sinais falsos e confirmar a validade da tendência.

Sinal de Compra (Rompimento de Alta):

Um sinal de compra é acionado quando diversas condições são atendidas simultaneamente, indicando um forte movimento de alta. Primeiramente, o EA monitora o nível do fractal de mínima mais recente (nível de suporte). Ele procura uma situação em que o preço atual do mercado cruze esse nível de suporte fractal de baixo para cima, sinalizando um possível rompimento. Para confirmar que o mercado está em tendência de alta, o EA verifica se o preço atual está acima tanto da EMA 14 quanto da EMA 200, com a EMA 14 posicionada acima da EMA 200, indicando uma tendência de alta. Quando essas condições estão alinhadas, um sinal de compra é gerado. Elementos visuais, como uma seta apontando para cima e um rótulo, são inseridos no gráfico, e um alerta pode ser acionado para notificar o trader.

  • O preço cruza de baixo para cima o nível de suporte fractal mais recente.
  • O preço atual está acima da EMA 14 e da EMA 200.
  • A EMA 14 está acima da EMA 200, confirmando uma tendência de alta.

Fig. 1. Rompimento de Alta

Sinal de Venda (Rompimento de Baixa):

Por outro lado, um sinal de venda é gerado quando o preço cruza de cima para baixo uma máxima fractal significativa (nível de resistência), indicando um possível movimento de queda. O EA observa a máxima fractal mais recente e aguarda até que o preço de mercado rompa esse nível para baixo. Para verificar se o mercado está em tendência de baixa, ele confirma que o preço atual está abaixo de ambas as EMAs, com a EMA 14 posicionada abaixo da EMA 200, indicando uma tendência de baixa. Quando esses critérios são atendidos, ou seja, quando o preço rompe o nível de resistência fractal para baixo enquanto a tendência permanece baixista, um sinal de venda é emitido. Elementos visuais semelhantes, como setas apontando para baixo e rótulos, são exibidos no gráfico, e alertas também podem ser ativados.

  • O preço cruza de cima para baixo o nível de resistência fractal mais recente.
  • O preço atual está abaixo da EMA 14 e da EMA 200.
  • A EMA 14 está abaixo da EMA 200, confirmando uma tendência de baixa.

Fig. 2. Rompimento de Baixa


Análise dos Componentes do Código

Este EA integra a análise de fractais com filtros de tendência baseados em médias móveis para identificar e visualizar possíveis pontos de rompimento no mercado. Ao traçar níveis horizontais nas máximas e mínimas fractais recentes, ele destaca zonas importantes de suporte e resistência. Quando o preço cruza esses níveis na direção confirmada pela tendência das EMAs, o EA gera sinais visuais (setas e rótulos) e sinais visuais (…) e alertas sonoros/pop-up, simplificando o processo de tomada de decisão do trader. Sua estrutura modular, com funções específicas para desenho, geração de sinais e gerenciamento de dados, permite adaptá-lo a diferentes estilos e preferências de negociação. Além disso, a atenção ao gerenciamento de recursos e à limpeza dos elementos utilizados garante estabilidade e clareza durante a execução. De modo geral, essa combinação sofisticada de indicadores e elementos visuais oferece uma ferramenta abrangente para traders que buscam aproveitar oportunidades de rompimento de fractais em mercados com tendências definidas.

Cabeçalho e Metadados

A seção inicial do código contém metadados que descrevem a autoria do script, sua versão e as informações de licenciamento. Os comentários delimitados por //+------------------------------------------------------------------+ servem para identificar a finalidade do script e fornecer os devidos créditos. As diretivas #property especificam o detentor dos direitos autorais, um hiperlink para o perfil do autor na comunidade MetaTrader, o número da versão e a aplicação de regras rigorosas de compilação. A diretiva #property strict é particularmente importante porque instrui o compilador a seguir padrões de codificação mais rigorosos, identificando possíveis erros, como variáveis não declaradas ou incompatibilidades de tipos. Esses metadados e diretivas não influenciam a lógica de execução em tempo de execução, mas servem como documentação e ajudam a garantir a qualidade do código durante a compilação.

//+------------------------------------------------------------------+
//|                              Fractal Breakout, EMA 14 and EMA 200|
//|                                   Copyright 2025, MetaQuotes Ltd.|
//|                           https://www.mql5.com/en/users/lynnchris|
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com/en/users/lynnchris"
#property version   "1.0"
#property strict

Parâmetros de Entrada

Esta seção define todos os parâmetros configuráveis que o usuário pode modificar sem alterar o código principal. Essas entradas incluem o timeframe utilizado na análise (InpTimeframe), o número de barras a serem examinadas (InpHistoryBars) e os períodos das duas EMAs, que funcionam como filtros de tendência (InpEMA14Period e InpEMA200Period).

Os parâmetros de cor (InpBullColor e InpBearColor) permitem personalizar visualmente as setas e linhas que indicam os rompimentos. Os rótulos de texto (InpBullText e InpBearText) fornecem anotações descritivas para os sinais, tornando o gráfico mais claro. O deslocamento das setas (InpArrowOffset) e o tamanho da fonte (InpArrowFontSize) oferecem maior controle sobre a apresentação visual, permitindo que o trader posicione os rótulos de maneira conveniente.

O sistema de alertas é controlado por InpAlertsEnabled, que ativa ou desativa as notificações pop-up, e por InpAlertSoundFile, que especifica o arquivo de som reproduzido quando um sinal é detectado. Esses parâmetros tornam o EA flexível e adaptável a diferentes estilos de negociação e preferências visuais, permitindo que os usuários o ajustem às suas necessidades específicas.

input ENUM_TIMEFRAMES InpTimeframe      = PERIOD_CURRENT;  // chart TF
input int             InpHistoryBars    = 200;             // bars back to scan
input int             InpEMA14Period    = 14;              // fast EMA
input int             InpEMA200Period   = 200;             // slow EMA
input color           InpBullColor      = clrLime;         // bullish arrow color
input color           InpBearColor      = clrRed;          // bearish arrow color
input string          InpBullText       = "BULL Break";    // bullish label
input string          InpBearText       = "BEAR Break";    // bearish label
input int             InpArrowOffset    = 20;              // offset in points for label
input int             InpArrowFontSize  = 12;              // size of the arrow glyph
input bool            InpAlertsEnabled  = true;            // show pop-up alerts
input string          InpAlertSoundFile = "alert.wav";     // sound file in /Sounds/

Variáveis Globais e Handles dos Indicadores

As variáveis declaradas fora das funções são utilizadas para armazenar os handles dos indicadores e os arrays de dados dos fractais. Os handles (hFractals, hEMA14, hEMA200) são referências às instâncias dos indicadores criadas durante a inicialização. Eles são essenciais porque permitem que o EA interaja com os buffers dos indicadores, obtendo dados históricos e em tempo real. Os arrays fractalUp[] e fractalDown[] são buffers alocados dinamicamente que armazenam, respectivamente, os pontos de máxima e mínima dos fractais. O gerenciamento desses elementos como variáveis globais garante que possam ser acessados em todo o código, especialmente durante o processamento da função OnTick, na qual ocorre a análise em tempo real.

int  hFractals, hEMA14, hEMA200;
double fractalUp[], fractalDown[];

Inicialização (OnInit)

Durante a inicialização, a função OnInit é chamada para configurar os recursos necessários. Ela cria os handles dos indicadores Fractals e EMAs utilizando funções como iFractals e iMA, especificando o símbolo e o timeframe utilizado na análise. A criação bem-sucedida desses handles é fundamental. Se algum deles for inválido, por exemplo, devido a parâmetros incorretos ou à indisponibilidade de dados, a inicialização falhará, impedindo que o EA seja executado de maneira inadequada.

Em seguida, o código configura os arrays de dados dos fractais para operarem como séries temporais, o que significa que os dados mais recentes estarão no índice 0, simplificando a análise retrospectiva. O redimensionamento desses arrays de acordo com o número de barras especificado garante que os buffers de dados tenham o tamanho adequado para um processamento eficiente. De modo geral, essa etapa estabelece a base para uma recuperação confiável dos dados, essencial para a identificação precisa dos rompimentos.

int OnInit()
  {
   hFractals = iFractals(_Symbol, InpTimeframe);
   hEMA14    = iMA(_Symbol, InpTimeframe, InpEMA14Period, 0, MODE_EMA, PRICE_CLOSE);
   hEMA200   = iMA(_Symbol, InpTimeframe, InpEMA200Period,0, MODE_EMA, PRICE_CLOSE);
   if(hFractals==INVALID_HANDLE || hEMA14==INVALID_HANDLE || hEMA200==INVALID_HANDLE)
      return(INIT_FAILED);

   ArraySetAsSeries(fractalUp,   true);
   ArraySetAsSeries(fractalDown, true);
   ArrayResize(fractalUp,   InpHistoryBars);
   ArrayResize(fractalDown, InpHistoryBars);
   return(INIT_SUCCEEDED);
  }

Desinicialização (OnDeinit)

Quando o EA é removido do gráfico ou o terminal é fechado, a função OnDeinit é executada para liberar os recursos utilizados. Ela libera os handles dos indicadores por meio de IndicatorRelease, liberando a memória associada e evitando vazamentos de memória. Além disso, percorre todos os objetos presentes no gráfico, identificando e excluindo aqueles cujo nome começa com o prefixo "FB_", que corresponde aos sinais visuais (setas, rótulos e linhas) criados durante a execução. Essa limpeza garante que nenhum objeto residual permaneça no gráfico após a desativação do EA, mantendo o ambiente visual organizado e evitando possíveis conflitos ou confusões em análises posteriores.

void OnDeinit(const int reason)
  {
   if(hFractals!=INVALID_HANDLE)
      IndicatorRelease(hFractals);
   if(hEMA14   !=INVALID_HANDLE)
      IndicatorRelease(hEMA14);
   if(hEMA200  !=INVALID_HANDLE)
      IndicatorRelease(hEMA200);

   for(int i=ObjectsTotal(0)-1; i>=0; i--)
     {
      string n = ObjectName(0,i);
      if(StringFind(n,"FB_")>=0)
         ObjectDelete(0,n);
     }
  }

Processamento Principal (OnTick)

A lógica principal está na função OnTick, executada sempre que um novo tick de mercado é recebido. Ela começa obtendo os valores mais recentes das duas EMAs por meio de CopyBuffer. Esses valores das EMAs funcionam como filtros de tendência: suas posições relativas indicam se o mercado está em tendência de alta ou de baixa, auxiliando na decisão sobre o rompimento. Se a recuperação dos dados das EMAs falhar, a função será encerrada antecipadamente para evitar a geração de sinais incorretos. Em seguida, a função recupera os buffers de dados dos fractais de máxima e mínima mais recentes, novamente realizando verificações de erros. O código então percorre esses buffers retrospectivamente para encontrar os fractais válidos mais recentes, ignorando quaisquer valores de preenchimento EMPTY_VALUE. Ao identificar os pontos fractais significativos mais recentes, o EA determina os níveis críticos de suporte ou resistência que podem desencadear rompimentos. Em seguida, desenha linhas horizontais nesses níveis para servir como referência visual, utilizando uma função auxiliar. As mensagens de depuração exibidas no terminal fornecem informações em tempo real sobre os níveis, os preços e as condições das EMAs, ajudando os traders a verificar a lógica utilizada.

Por fim, o EA verifica as condições de rompimento: um rompimento de baixa ocorre quando o fechamento anterior estava acima do nível inferior, o fechamento atual cruza esse nível para baixo e o preço está abaixo de ambas as EMAs, em uma tendência de baixa. Por outro lado, um rompimento de alta é identificado quando o fechamento anterior estava abaixo do nível superior, o fechamento/preço atual rompe esse nível para cima e o preço está acima de ambas as EMAs, em uma tendência de alta. A identificação dessas condições aciona a função de geração de sinais.

void OnTick()
  {
   // 1) Read current EMAs
   double ema14Arr[1], ema200Arr[1];
   if(CopyBuffer(hEMA14,0,0,1,ema14Arr)<=0 || CopyBuffer(hEMA200,0,0,1,ema200Arr)<=0)
      return;
   double ema14_now  = ema14Arr[0];
   double ema200_now = ema200Arr[0];

   // 2) Read fractal history (skip current bar)
   if(CopyBuffer(hFractals,0,1,InpHistoryBars,fractalUp)<=0 ||
      CopyBuffer(hFractals,1,1,InpHistoryBars,fractalDown)<=0)
      return;

   // 3) Find most recent valid fractals (ignore EMPTY_VALUE)
   int upShift=-1, downShift=-1;
   for(int i=1; i<InpHistoryBars; i++)
     {
      if(fractalUp[i]   != EMPTY_VALUE && upShift<0)
         upShift   = i+1;
      if(fractalDown[i] != EMPTY_VALUE && downShift<0)
         downShift = i+1;
      if(upShift>0 && downShift>0)
         break;
     }

   // 4) Levels
   double lvlUp   = (upShift>0)   ? fractalUp[upShift-1]     : 0.0;
   double lvlDown = (downShift>0) ? fractalDown[downShift-1] : 0.0;

   // 5) Draw level lines
   DrawHLine("FB_LevelUp",   lvlUp,   InpBullColor);
   DrawHLine("FB_LevelDown", lvlDown, InpBearColor);

   // 6) DEBUG print
   double prevC = iClose(_Symbol,InpTimeframe,1);
   double currC = iClose(_Symbol,InpTimeframe,0);
   PrintFormat(
      "DBG lvlUp=%.5f lvlDown=%.5f prevC=%.5f currC=%.5f EMA14=%.5f EMA200=%.5f",
      lvlUp, lvlDown, prevC, currC, ema14_now, ema200_now
   );

   // 7) Breakouts on the last closed candle (shift=1)

   // Bearish breakout detection
   if(lvlDown>0
      && prevC>=lvlDown && currC<lvlDown
      && currC<ema14_now && currC<ema200_now
      && ema200_now>ema14_now)
     {
      Print(">>> Bear breakout triggered");
      Signal(false, 1, lvlDown, ema14_now, ema200_now);
     }

   // Bullish breakout detection
   if(lvlUp>0
      && prevC<=lvlUp && currC>lvlUp
      && currC>ema14_now && currC>ema200_now
      && ema14_now>ema200_now)
     {
      Print(">>> Bull breakout triggered");
      Signal(true, 1, lvlUp, ema14_now, ema200_now);
     }
  }

Desenhando Linhas Horizontais (DrawHLine)

Essa função auxiliar gerencia a criação e a atualização de linhas horizontais no gráfico. Quando chamada, ela verifica se já existe uma linha com o nome especificado. Caso não exista, cria uma nova linha pontilhada no nível de preço informado, utilizando a cor definida. Se a linha já existir, a função simplesmente atualizará sua posição. Essa abordagem evita a sobreposição de várias linhas e garante que os níveis visuais permaneçam atualizados de acordo com a análise mais recente dos fractais. O estilo pontilhado ajuda a diferenciar essas linhas dos demais objetos do gráfico, destacando sua função como níveis de suporte ou resistência. Essas referências visuais são extremamente valiosas para os traders, pois permitem identificar rapidamente as zonas de rompimento e facilitam a tomada de decisões manuais ou automatizadas.

void DrawHLine(string name, double price, color clr)
  {
   if(price<=0)
      return;
   if(ObjectFind(0,name)<0)
     {
      ObjectCreate(0,name,OBJ_HLINE,0,0,price);
      ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
      ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT);
      ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
     }
   else
      ObjectSetDouble(0,name,OBJPROP_PRICE,price);
  }

Geração e Visualização de Sinais (Signal)

A função Signal reúne todas as ações relacionadas à sinalização de um evento de rompimento. Ela começa obtendo o registro de data e hora da barra em que o sinal ocorreu, garantindo o posicionamento preciso dos objetos visuais. Em seguida, cria um objeto de seta no nível do rompimento, apontando para cima ou para baixo, dependendo de o sinal ser de alta ou de baixa, com cores correspondentes à direção da tendência. A aparência da seta é personalizada por meio de parâmetros de largura e tamanho, garantindo maior clareza visual. Junto à seta, é adicionado um rótulo de texto com um pequeno deslocamento vertical, exibindo uma mensagem descritiva, como "BULL Break" ou "BEAR Break", reforçando a indicação visual.

A função registra uma mensagem detalhada na aba Experts, incluindo o horário exato, o nível, o preço de fechamento e os valores das EMAs, fornecendo um histórico completo dos sinais. Se os alertas estiverem ativados, uma mensagem pop-up será exibida e um arquivo de som será reproduzido para notificar imediatamente o trader. Essa combinação de sinais visuais, sonoros e registros de log garante que os traders sejam informados rapidamente sobre possíveis oportunidades de rompimento, permitindo que ajam no momento adequado.

void Signal(bool isBull, int shift, double level, double ema14, double ema200)
  {
   datetime t     = iTime(_Symbol,InpTimeframe,shift);
   double   price = level;
   string   side  = isBull ? "Bull" : "Bear";

   // Arrow
   string arrowName = StringFormat("FB_%sArrow_%d", side, (int)t);
   ObjectCreate(0, arrowName, OBJ_ARROW, 0, t, price);
   ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE,    isBull?233:234);
   ObjectSetInteger(0, arrowName, OBJPROP_COLOR,        isBull?InpBullColor:InpBearColor);
   ObjectSetInteger(0, arrowName, OBJPROP_WIDTH,        2);
   ObjectSetInteger(0, arrowName, OBJPROP_FONTSIZE,     InpArrowFontSize);

   // Label
   string lab = arrowName + "_L";
   double offset = (isBull ? InpArrowOffset : -InpArrowOffset) * _Point;
   ObjectCreate(0, lab, OBJ_TEXT, 0, t, price + offset);
   ObjectSetString(0, lab, OBJPROP_TEXT,    isBull?InpBullText:InpBearText);
   ObjectSetInteger(0, lab, OBJPROP_COLOR,  isBull?InpBullColor:InpBearColor);
   ObjectSetInteger(0, lab, OBJPROP_FONTSIZE, 11);

   // Log message
   string msg = StringFormat(
                   "%s breakout at %s | Level=%.5f | Close=%.5f | EMA14=%.5f | EMA200=%.5f",
                   side, TimeToString(t, TIME_DATE|TIME_SECONDS),
                   level, iClose(_Symbol,InpTimeframe,shift),
                   ema14, ema200
                );
   Print(msg);

   // Alert and sound
   if(InpAlertsEnabled)
     {
      Alert(msg);
      if(StringLen(InpAlertSoundFile)>0)
         PlaySound(InpAlertSoundFile);
     }
  }

Código em MQL5

//+------------------------------------------------------------------+
//|                              Fractal Breakout, EMA 14 and EMA 200|
//|                                   Copyright 2025, MetaQuotes Ltd.|
//|                           https://www.mql5.com/en/users/lynnchris|
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com/en/users/lynnchris"
#property version   "1.0"
#property strict

//---inputs
input ENUM_TIMEFRAMES InpTimeframe      = PERIOD_CURRENT;  // chart TF
input int             InpHistoryBars    = 200;             // bars back to scan
input int             InpEMA14Period    = 14;              // fast EMA
input int             InpEMA200Period   = 200;             // slow EMA
input color           InpBullColor      = clrLime;         // bullish arrow color
input color           InpBearColor      = clrRed;          // bearish arrow color
input string          InpBullText       = "BULL Break";    // bullish label
input string          InpBearText       = "BEAR Break";    // bearish label
input int             InpArrowOffset    = 20;              // offset in points for label
input int             InpArrowFontSize  = 12;              // size of the arrow glyph
input bool            InpAlertsEnabled  = true;            // show pop-up alerts
input string          InpAlertSoundFile = "alert.wav";     // sound file in /Sounds/

//---indicator handles & buffers
int  hFractals, hEMA14, hEMA200;
double fractalUp[], fractalDown[];

//+------------------------------------------------------------------+
//| Expert initialization                                            |
//+------------------------------------------------------------------+
int OnInit()
  {
   hFractals = iFractals(_Symbol, InpTimeframe);
   hEMA14    = iMA(_Symbol, InpTimeframe, InpEMA14Period, 0, MODE_EMA, PRICE_CLOSE);
   hEMA200   = iMA(_Symbol, InpTimeframe, InpEMA200Period,0, MODE_EMA, PRICE_CLOSE);
   if(hFractals==INVALID_HANDLE || hEMA14==INVALID_HANDLE || hEMA200==INVALID_HANDLE)
      return(INIT_FAILED);

   ArraySetAsSeries(fractalUp,   true);
   ArraySetAsSeries(fractalDown, true);
   ArrayResize(fractalUp,   InpHistoryBars);
   ArrayResize(fractalDown, InpHistoryBars);
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization                                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(hFractals!=INVALID_HANDLE)
      IndicatorRelease(hFractals);
   if(hEMA14   !=INVALID_HANDLE)
      IndicatorRelease(hEMA14);
   if(hEMA200  !=INVALID_HANDLE)
      IndicatorRelease(hEMA200);

   for(int i=ObjectsTotal(0)-1; i>=0; i--)
     {
      string n = ObjectName(0,i);
      if(StringFind(n,"FB_")>=0)
         ObjectDelete(0,n);
     }
  }

//+------------------------------------------------------------------+
//| Tick handler                                                     |
//+------------------------------------------------------------------+
void OnTick()
  {
// 1) Read current EMAs
   double ema14Arr[1], ema200Arr[1];
   if(CopyBuffer(hEMA14,0,0,1,ema14Arr)<=0 || CopyBuffer(hEMA200,0,0,1,ema200Arr)<=0)
      return;
   double ema14_now  = ema14Arr[0];
   double ema200_now = ema200Arr[0];

// 2) Read fractal history (skip current bar)
   if(CopyBuffer(hFractals,0,1,InpHistoryBars,fractalUp)<=0 ||
      CopyBuffer(hFractals,1,1,InpHistoryBars,fractalDown)<=0)
      return;

// 3) Find most recent valid fractals (ignore EMPTY_VALUE)
   int upShift=-1, downShift=-1;
   for(int i=1; i<InpHistoryBars; i++)
     {
      if(fractalUp[i]   != EMPTY_VALUE && upShift<0)
         upShift   = i+1;
      if(fractalDown[i] != EMPTY_VALUE && downShift<0)
         downShift = i+1;
      if(upShift>0 && downShift>0)
         break;
     }

// 4) Levels
   double lvlUp   = (upShift>0)   ? fractalUp[upShift-1]     : 0.0;
   double lvlDown = (downShift>0) ? fractalDown[downShift-1] : 0.0;

// 5) Draw level lines
   DrawHLine("FB_LevelUp",   lvlUp,   InpBullColor);
   DrawHLine("FB_LevelDown", lvlDown, InpBearColor);

// 6) DEBUG print
   double prevC = iClose(_Symbol,InpTimeframe,1);
   double currC = iClose(_Symbol,InpTimeframe,0);
   PrintFormat(
      "DBG lvlUp=%.5f lvlDown=%.5f prevC=%.5f currC=%.5f EMA14=%.5f EMA200=%.5f",
      lvlUp, lvlDown, prevC, currC, ema14_now, ema200_now
   );

// 7) Breakouts on the last closed candle (shift=1)

// Bearish breakout
   if(lvlDown>0
      && prevC>=lvlDown && currC<lvlDown
      && currC<ema14_now && currC<ema200_now
      && ema200_now>ema14_now)
     {
      Print(">>> Bear breakout triggered");
      Signal(false, 1, lvlDown, ema14_now, ema200_now);
     }
// Bullish breakout
   if(lvlUp>0
      && prevC<=lvlUp && currC>lvlUp
      && currC>ema14_now && currC>ema200_now
      && ema14_now>ema200_now)
     {
      Print(">>> Bull breakout triggered");
      Signal(true, 1, lvlUp, ema14_now, ema200_now);
     }
  }

//+------------------------------------------------------------------+
//| Draw or update a dotted HLine                                    |
//+------------------------------------------------------------------+
void DrawHLine(string name, double price, color clr)
  {
   if(price<=0)
      return;
   if(ObjectFind(0,name)<0)
     {
      ObjectCreate(0,name,OBJ_HLINE,0,0,price);
      ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
      ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT);
      ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
     }
   else
      ObjectSetDouble(0,name,OBJPROP_PRICE,price);
  }

//+------------------------------------------------------------------+
//| Plot arrow, label, log & alert                                   |
//+------------------------------------------------------------------+
void Signal(bool isBull, int shift, double level, double ema14, double ema200)
  {
   datetime t     = iTime(_Symbol,InpTimeframe,shift);
   double   price = level;
   string   side  = isBull ? "Bull" : "Bear";

// Arrow
   string arrowName = StringFormat("FB_%sArrow_%d", side, (int)t);
   ObjectCreate(0, arrowName, OBJ_ARROW, 0, t, price);
   ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE,    isBull?233:234);
   ObjectSetInteger(0, arrowName, OBJPROP_COLOR,        isBull?InpBullColor:InpBearColor);
   ObjectSetInteger(0, arrowName, OBJPROP_WIDTH,        2);
   ObjectSetInteger(0, arrowName, OBJPROP_FONTSIZE,     InpArrowFontSize);

// Label
   string lab = arrowName + "_L";
   double offset = (isBull ? InpArrowOffset : -InpArrowOffset) * _Point;
   ObjectCreate(0, lab, OBJ_TEXT, 0, t, price + offset);
   ObjectSetString(0, lab, OBJPROP_TEXT,    isBull?InpBullText:InpBearText);
   ObjectSetInteger(0, lab, OBJPROP_COLOR,  isBull?InpBullColor:InpBearColor);
   ObjectSetInteger(0, lab, OBJPROP_FONTSIZE, 11);

// Expert log
   string msg = StringFormat(
                   "%s breakout at %s | Level=%.5f | Close=%.5f | EMA14=%.5f | EMA200=%.5f",
                   side, TimeToString(t, TIME_DATE|TIME_SECONDS),
                   level, iClose(_Symbol,InpTimeframe,shift),
                   ema14, ema200
                );
   Print(msg);

// Pop-up alert + optional sound
   if(InpAlertsEnabled)
     {
      Alert(msg);
      if(StringLen(InpAlertSoundFile)>0)
         PlaySound(InpAlertSoundFile);
     }
  }
//+------------------------------------------------------------------+


Resultados

Para testar o EA, primeiro compile o código utilizando o MetaEditor. Após a compilação, você poderá aplicá-lo a um gráfico no MetaTrader 5 para realizar testes em tempo real ou executá-lo diretamente no Testador de Estratégias para realizar backtests. Realizei testes desse EA tanto em condições reais de mercado quanto em backtests com dados históricos. Esse processo é essencial para ajustar os parâmetros do EA, obter o comportamento de negociação desejado e otimizar seu desempenho.

O gráfico apresentado na imagem abaixo demonstra como o EA identifica uma reversão significativa do mercado utilizando o indicador Fractals e as EMAs. Especificamente, o EA detecta um rompimento de baixa de um nível fractal em um suporte importante, que é destacado visualmente no gráfico. O movimento subsequente dos preços confirma a reversão, pois o mercado continua em queda, alinhando-se à tendência das EMAs, com a EMA 14 cruzando a EMA 200 de cima para baixo, indicando uma mudança para uma tendência baixista. As referências visuais, como o marcador “BEAR Break”, ajudam a tomar decisões disciplinadas de entrada e saída. Esse resultado demonstra a capacidade do EA de reconhecer sinais antecipados de reversão de tendência, permitindo que os traders aproveitem oportunidades com maior probabilidade de sucesso e, ao mesmo tempo, evitem sinais falsos.

Fig. 3. Rompimento de Baixa no Índice Step

O GIF abaixo demonstra o processo de identificação e confirmação, em tempo real, de uma reversão de tendência pelo EA. Ele destaca como o sistema de indicadores identifica um nível fractal de suporte ou resistência e sinaliza um possível rompimento, levando o trader a considerar uma entrada. À medida que o mercado se movimenta na direção prevista, os sinais do EA são confirmados pelo alinhamento das EMAs, com a EMA 14 cruzando a EMA 200 de cima para baixo, validando a tendência baixista. Os elementos visuais, como setas e alertas, demonstram como o EA facilita a tomada de decisões no momento adequado. Esse exemplo destaca a importância de combinar a identificação antecipada com a confirmação da tendência, aumentando a confiança nas operações e reduzindo a probabilidade de entradas incorretas.

Fig. 4. Backtest no V75 (1s)


Conclusão

Este Expert Advisor utiliza o potencial do indicador Fractals, de Bill Williams, em conjunto com médias móveis exponenciais de curto e longo prazo para identificar pontos de entrada com alta probabilidade de sucesso. Ao combinar essas ferramentas, ele identifica sinais antecipados de reversão, que são confirmados em relação à tendência predominante do mercado, melhorando a precisão e a consistência na execução das operações. Backtests rigorosos e testes em condições reais de mercado demonstraram sua flexibilidade em diferentes cenários, e seus parâmetros podem ser ajustados para alcançar um desempenho otimizado. Com setas e rótulos intuitivos exibidos diretamente no gráfico, além da sinalização automatizada no gráfico, este EA proporciona mais disciplina e agilidade à sua rotina de negociação. Em essência, ele oferece uma estrutura sistemática, baseada em regras, para a análise da ação do preço, ideal para traders que desejam combinar rigor técnico e automação.

Confira nossas ferramentas em destaque na tabela abaixo.





   
Projetor de Gráfico
Comentário Analítico
Mestre Analítico
Previsor Analítico 
Navegador de Volatilidade
Coletor de Sinais de Reversão à Média
Pulso de Sinais 
Painel de Métricas 
Fluxo Externo
VWAP
Heikin Ashi   FibVWAP  
DIVERGÊNCIA DO RSI
Parabolic SAR (PSAR) 
Script Quarters Drawer
Detector de Intrusão
TrendLoom Tool  Painel de Quarters 
Analisador ZigZag  Explorador de Correlações  Ferramenta de Detecção de Inversão de Estrutura de Mercado
Painel de Correlações  Medidor de Força da Moeda 
Ferramenta de Análise PAQ 
Pin bar, Engolfo e divergência do RSI
Rompedor Fractal com EMA Dupla        

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

Arquivos anexados |
Últimos Comentários | Ir para discussão (3)
Delly
Delly | 4 jun. 2025 em 09:17
Artigo interessante, e obrigado pelo código-fonte do EA. Vou testá-lo e dar meu feedback.
Christian Benjamin
Christian Benjamin | 9 jun. 2025 em 19:54
Delly Kabongo #:
Artigo interessante, e obrigado pelo código-fonte do EA. Vou testá-lo e enviar meus comentários.
Obrigado por entrar em contato. Seu feedback é muito apreciado e sempre bem-vindo.
ABEL OLUFEMI FAMODU
ABEL OLUFEMI FAMODU | 11 jun. 2025 em 20:29
Artigo muito interessante. Vai ajudar bastante a simplificar a estratégia de negociação.
Aprendizado de Máquina e Data Science (Parte 43): Identificação de padrões ocultos em indicadores com modelos de misturas gaussianas latentes (LGMM) Aprendizado de Máquina e Data Science (Parte 43): Identificação de padrões ocultos em indicadores com modelos de misturas gaussianas latentes (LGMM)
Você já teve a sensação de que existe algo mais por trás de um gráfico, algum padrão que ainda não conseguiu identificar? Como se houvesse um código secreto que, uma vez decifrado, permitiria saber exatamente para onde os preços estão indo? Apresento o LGMM, uma ferramenta capaz de detectar padrões ocultos no mercado. Esse modelo de aprendizado de máquina ajuda a identificar regularidades que normalmente passam despercebidas.
Repensando as estratégias clássicas (Parte 13): Atualização da estratégia de cruzamento de médias móveis (Parte 2) Repensando as estratégias clássicas (Parte 13): Atualização da estratégia de cruzamento de médias móveis (Parte 2)
Vamos tentar incorporar novas melhorias à nossa estratégia de cruzamento de médias móveis, buscando reduzir a defasagem dos sinais e aumentar sua confiabilidade por meio de análises adicionais dos dados. Como sabemos, projetar dados em um espaço multidimensional pode, em alguns casos, melhorar o desempenho dos modelos de machine learning. Vamos entender o que isso significa na prática para nós, traders, e como podemos aplicar esse princípio no terminal MetaTrader 5.
Desenvolvimento de ferramentas para análise de Price Action (Parte 28): Ferramenta para operar rompimentos da faixa de abertura Desenvolvimento de ferramentas para análise de Price Action (Parte 28): Ferramenta para operar rompimentos da faixa de abertura
No início de cada sessão de negociação, a direção do mercado muitas vezes só fica clara quando o preço rompe os limites da faixa de abertura. Neste artigo, veremos como desenvolver um EA em MQL5 capaz de detectar e analisar automaticamente esses rompimentos, fornecendo sinais oportunos baseados em dados para embasar entradas intradiárias com maior confiança.
A arte de trabalhar com logs (Parte 8): Registros de erros com tradução automática A arte de trabalhar com logs (Parte 8): Registros de erros com tradução automática
Nesta oitava parte da série "A arte de trabalhar com logs", vamos explorar a implementação de mensagens de erro multilíngues no Logify, uma poderosa biblioteca de logging para MQL5. Você aprenderá a estruturar erros com informações de contexto, traduzir mensagens para vários idiomas e formatar logs dinamicamente conforme o nível de logging. Tudo isso com uma arquitetura limpa, extensível e pronta para produção.