Desenvolvimento de um Kit de Ferramentas para Análise da Ação do Preço (Parte 25): Rompimento de Fractais com EMA Dupla
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.
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/18297
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.
Aprendizado de Máquina e Data Science (Parte 43): Identificação de padrões ocultos em indicadores com modelos de misturas gaussianas latentes (LGMM)
Repensando as estratégias clássicas (Parte 13): Atualização da estratégia de cruzamento de médias móveis (Parte 2)
Desenvolvimento de ferramentas para análise de Price Action (Parte 28): Ferramenta para operar rompimentos da faixa de abertura
A arte de trabalhar com logs (Parte 8): Registros de erros com tradução automática
- 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
Artigo interessante, e obrigado pelo código-fonte do EA. Vou testá-lo e enviar meus comentários.