Desenvolvimento do Toolkit de Análise de Price Action (Parte 16): Introduzindo a Teoria dos Quartis (II) — Intrusion Detector EA
Introdução
Em nosso artigo anterior, apresentamos o Quarters Drawer Script, uma ferramenta projetada para plotar níveis de quartis visualmente no gráfico, tornando a análise de mercado mais intuitiva. Esse conceito é derivado da Teoria dos Quartis, originalmente introduzida por Ilian Yotov. Desenhar esses quartis com sucesso provou ser um método poderoso para simplificar a análise de price action. No entanto, monitorar manualmente esses níveis enquanto o preço interage com eles exige tempo e atenção significativos.
Para resolver esse desafio, tenho o prazer de apresentar o Intrusion Detector EA, uma solução projetada para automatizar o processo de monitoramento. Este EA monitora continuamente os gráficos, detectando quando o preço atinge qualquer nível de quartil, sejam níveis pequenos, grandes, principais, de overshoot ou undershoot. Além disso, ele fornece comentários instantâneos e insights com base na Teoria dos Quartis de Ilian Yotov, ajudando cada trader a antecipar possíveis reações do mercado. Neste artigo, começaremos revisando a ferramenta Quarters Drawer, depois exploraremos o conceito da estratégia e a implementação em MQL5, analisaremos os resultados dos testes e concluiremos com os principais aprendizados. Veja o índice abaixo para uma visão estruturada.
Conteúdo
- Introdução
- Conteúdo
- Revisão do Artigo Anterior
- Conceito da Estratégia e Implementação em MQL5
- Resultados
- Conclusão
Revisão do Artigo Anterior
Não vou me alongar muito nesta seção, pois o Quarters Drawer Script foi amplamente discutido em nosso artigo anterior. No entanto, se você ainda não o leu, recomendo fortemente seguir os links fornecidos para obter uma compreensão completa dos conceitos fundamentais. Esse artigo focou principalmente na automação do desenho dos níveis de quartis, tornando a análise de mercado mais estruturada e eficiente.
Como mencionado anteriormente, a Teoria dos Quartis foi descoberta por Ilian Yotov e posteriormente apresentada à comunidade de trading. Um ponto crucial, talvez não enfatizado o suficiente no último artigo, é que essa teoria é altamente aplicável a pares de moedas, tornando-se uma ferramenta essencial para traders de forex. Para obter uma compreensão mais clara de como esses níveis de quartis funcionam, observe o diagrama abaixo, que representa visualmente a estrutura da teoria.

Fig 1. Níveis de Quartis
Nossa ferramenta Quarters Drawer apresentou resultados notáveis, plotando com sucesso quartis grandes, overshoots, undershoots e quartis menores. Mais importante ainda, observamos que o preço interagiu e respondeu consistentemente a esses níveis, reforçando a legitimidade e a eficácia da teoria de Yotov. Isso não foi apenas um exercício teórico — a ferramenta validou o poder dos níveis de quartis em condições reais de mercado. Agora, vamos analisar o diagrama abaixo para revisitar algumas de nossas principais descobertas e insights.

Fig 2. Resultados
Conceito da Estratégia e Implementação em MQL5
Lógica Central
O Intrusion Detector EA é totalmente voltado para mapear níveis psicológicos-chave de preço usando a teoria dos quartis. Ele divide o mercado em intervalos de 1000 pips, com Números Inteiros Principais atuando como base estrutural. Dentro desses intervalos, ele marca Quartis Grandes (zonas de 250 pips) e, se ativado, Quartis Pequenos para uma granularidade ainda mais refinada. O EA também plota áreas de overshoot e undershoot, capturando extensões de preço que podem enganar traders. A cada tick, ele analisa o preço atual, verifica se está se aproximando desses níveis-chave dentro de uma tolerância definida (ou seja, margem de erro) e dispara alertas caso algo esteja acontecendo.
O objetivo principal aqui é identificar possíveis pontos de reversão, breakouts ou falsos breakouts antes que se tornem evidentes para todos. Se o preço estiver próximo de um Número Inteiro Principal, o EA o sinaliza como uma zona-chave de suporte ou resistência. Se estiver em torno de um nível de Quartil Grande, ele indica que um movimento de 250 pips pode estar prestes a ocorrer. E as zonas de overshoot e undershoot? Elas ajudam a identificar armadilhas onde o preço pode reverter com força. O EA garante que não haverá excesso de alertas ao rastrear intrusões e atualiza um painel de comentários em tempo real para que você sempre saiba o que está acontecendo. Tudo isso foi desenvolvido para manter você à frente da maioria, tornando a teoria dos quartis prática e acionável.
Implementação
Neste EA, começamos com um cabeçalho que inclui metadados sobre o EA, como seu nome ("Intrusion Detector"), detalhes de copyright e um link para o perfil do desenvolvedor. As diretivas #property especificam esses detalhes e impõem regras de compilação rigorosas, garantindo que o código esteja em conformidade com os padrões modernos do MQL5.
//+------------------------------------------------------------------+ //| Intrusion Detector | //| Copyright 2025, Christian Benjamin | //| https://www.mql5.com/en/users/lynnchris | //+------------------------------------------------------------------+ #property copyright "Christian Benjamin" #property link "https://www.mql5.com/en/users/lynnchris" #property version "1.0" #property strict
Em seguida, definimos um conjunto de parâmetros de entrada que permitem personalizar o comportamento do EA sem modificar o código. Os parâmetros incluem valores numéricos como MajorStep, que determina o intervalo entre os níveis principais (efetivamente definindo um intervalo de 1000 PIPs), e AlertTolerance, que define o limite de proximidade para detectar quando o preço “toca” um nível específico. Entradas booleanas controlam se o EA desenha linhas adicionais, como linhas de quartis grandes e pequenos, bem como áreas de overshoot em torno desses níveis principais.
Além disso, as configurações de cores são definidas usando valores hexadecimais (ou cores predefinidas) para garantir que cada tipo de linha — seja principal, quartil grande, quartil pequeno ou overshoot — apareça com o estilo visual pretendido no gráfico. As configurações de estilo e espessura das linhas vêm em seguida, permitindo personalizar ainda mais a aparência dessas linhas desenhadas.
Configurações de Parâmetros
input double MajorStep = 0.1000; // Difference between Major Whole Numbers (defines the 1000-PIP Range) input bool DrawLargeQuarters = true; // Draw intermediate Large Quarter lines. input bool DrawSmallQuarters = false; // Draw Small Quarter lines. input bool DrawOvershootAreas = true; // Mark overshoot/undershoot areas for Large Quarter lines. input double AlertTolerance = 0.0025; // Tolerance for detecting a "touch"
- MajorStep: Define o intervalo entre os níveis principais (por exemplo, um intervalo de 1000 PIPs).
- DrawLargeQuarters & DrawSmallQuarters: Booleanos que controlam se o EA deve desenhar linhas adicionais dentro do intervalo.
- DrawLargeQuarters & <s1>DrawSmallQuarters</s1>: Booleanos que controlam se o EA deve desenhar linhas adicionais dentro do intervalo.
- AlertTolerance: Especifica o quão próximo o preço deve chegar de um nível (dentro de 0.0025) para ser considerado um “toque”.
Configurações de Cores
input color MajorColor = 0x2F4F4F; // Dark Slate Gray for Major lines. input color LargeQuarterColor = 0x8B0000; // Dark Red for Large Quarter lines. input color SmallQuarterColor = 0x00008B; // Dark Blue for Small Quarter lines. input color OvershootColor = clrRed; // Red for overshoot/undershoot lines.
As cores são definidas para cada tipo de linha, de modo que, ao serem desenhadas no gráfico, correspondam visualmente à sua descrição.
Configurações de Estilo e Espessura das Linhas
input ENUM_LINE_STYLE MajorLineStyle = STYLE_SOLID; input int MajorLineWidth = 4; input ENUM_LINE_STYLE LargeQuarterLineStyle = STYLE_DOT; input int LargeQuarterLineWidth = 3; input ENUM_LINE_STYLE OvershootLineStyle = STYLE_DASH; input int OvershootLineWidth = 1; input ENUM_LINE_STYLE SmallQuarterLineStyle = STYLE_SOLID; input int SmallQuarterLineWidth = 1;
Cada tipo de linha (principal, quartil grande, overshoot, quartil pequeno) possui suas próprias configurações de estilo (sólido, pontilhado, tracejado) e largura.
Mensagens de Comentário Personalizáveis
Essas mensagens descrevem a importância de cada nível quando o preço o “toca”. Elas são usadas posteriormente para construir uma tabela de comentários.
- MajorSupportReason: Isso indica que há um nível de suporte significativo no mercado. Se o preço cair abaixo desse nível, sugere que pode ocorrer uma mudança no intervalo de negociação, potencialmente levando a novas quedas de preço.
- MajorResistanceReason: Isso indica um nível crítico de resistência. Se o preço romper acima dessa resistência, pode sinalizar o início de um novo intervalo de negociação, potencialmente resultando em um movimento de alta.
- LargeQuarterReason: Esta afirmação destaca que uma quebra decisiva do preço nesse nível pode levar a um movimento significativo, potencialmente de até 250 pips. Isso implica que os traders devem prestar atenção a esse nível para possíveis oportunidades de negociação.
- OvershootReason: Isso implica que o preço está testando um nível de rompimento e, se não conseguir manter o momentum, é provável que ocorra uma reversão na direção do preço. Isso significa que os traders devem ter cautela se o preço ultrapassar um nível-chave sem forte suporte comprador.
- UndershootReason: Isso indica que não houve interesse comprador suficiente no mercado, sugerindo que uma reversão para uma tendência de baixa pode ser possível. Os traders devem observar esse sinal atentamente para possíveis oportunidades de venda.
- SmallQuarterReason: Isso se refere a uma pequena flutuação de preço dentro do mercado. Sugere que o preço está se movendo em incrementos pequenos e pode não indicar oportunidades significativas de negociação ou mudanças de tendência.
input string MajorSupportReason = "Key support level. Quebrar abaixo sinais de mudança de faixa."; input string MajorResistanceReason = "Resistência pivotal. Breakout above may start new range."; input string LargeQuarterReason = "Decisive break could trigger next 250-PIP move."; input string OvershootReason = "Test of breakout; reversal likely if momentum fails."; input string UndershootReason = "Insufficient bullish force; possible bearish reversal."; input string SmallQuarterReason = "Minor fluctuation.";
Uma variável booleana global, intrusionAlerted, é utilizada para garantir que os alertas sejam acionados apenas uma vez por evento de intrusão, evitando notificações repetidas quando o preço permanece próximo de um nível.
// Global flag to avoid repeated alerts while price lingers at a level bool intrusionAlerted = false;
A função DrawHorizontalLine está no núcleo da saída visual do EA. Essa função recebe parâmetros como o nome da linha, preço, cor, largura e estilo, e primeiro verifica se já existe uma linha com esse nome — caso exista, a linha é excluída. Em seguida, ela cria uma nova linha horizontal no preço especificado e define suas propriedades adequadamente, garantindo que a linha se estenda até o lado direito do gráfico. Essa abordagem modular facilita a reutilização da função sempre que um novo nível precisa ser desenhado.
void DrawHorizontalLine(string name, double price, color lineColor, int width, ENUM_LINE_STYLE style) { if(ObjectFind(0, name) != -1) ObjectDelete(0, name); if(!ObjectCreate(0, name, OBJ_HLINE, 0, 0, price)) { Print("Failed to create line: ", name); return; } ObjectSetInteger(0, name, OBJPROP_COLOR, lineColor); ObjectSetInteger(0, name, OBJPROP_STYLE, style); ObjectSetInteger(0, name, OBJPROP_WIDTH, width); ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, true); }
A função DrawQuarters utiliza DrawHorizontalLine para desenhar os limites principais do intervalo de 1000 PIPs (calculados com base no preço atual), bem como linhas adicionais dentro desse intervalo. Se ativado, o EA desenha linhas de “Quartis Grandes” dividindo o intervalo em quatro segmentos. Para cada uma dessas linhas, se as áreas de overshoot estiverem habilitadas, a função também desenha linhas ligeiramente acima e abaixo do nível principal para indicar possíveis overshoots ou undershoots. Quando a opção está ativada, o EA ainda subdivide o intervalo em linhas ainda mais detalhadas de “Quartis Pequenos”, fornecendo sinais visuais mais precisos sobre a estrutura de preço.
void DrawQuarters(double currentPrice) { // Calculate the boundaries of the current 1000-PIP Range double lowerMajor = MathFloor(currentPrice / MajorStep) * MajorStep; double upperMajor = lowerMajor + MajorStep; // Draw Major Whole Number lines (defining the 1000-PIP Range) DrawHorizontalLine("MajorLower", lowerMajor, MajorColor, MajorLineWidth, MajorLineStyle); DrawHorizontalLine("MajorUpper", upperMajor, MajorColor, MajorLineWidth, MajorLineStyle); // Draw Large Quarter lines and their overshoot/undershoot areas if enabled if(DrawLargeQuarters) { double LQIncrement = MajorStep / 4.0; for(int i = 1; i < 4; i++) { double level = lowerMajor + i * LQIncrement; string objName = "LargeQuarter_" + IntegerToString(i); DrawHorizontalLine(objName, level, LargeQuarterColor, LargeQuarterLineWidth, LargeQuarterLineStyle); if(DrawOvershootAreas) { double offset = MajorStep / 40.0; // approximately 25 pips if MajorStep=0.1000 DrawHorizontalLine("Overshoot_" + IntegerToString(i) + "_up", level + offset, OvershootColor, OvershootLineWidth, OvershootLineStyle); DrawHorizontalLine("Undershoot_" + IntegerToString(i) + "_down", level - offset, OvershootColor, OvershootLineWidth, OvershootLineStyle); } } } // Draw Small Quarter lines if enabled (optional, finer divisions) if(DrawSmallQuarters) { double segStep = MajorStep / 10.0; double smallQuarter = segStep / 4.0; for(int seg = 0; seg < 10; seg++) { double segStart = lowerMajor + seg * segStep; for(int j = 1; j < 4; j++) { double level = segStart + j * smallQuarter; string objName = "SmallQuarter_" + IntegerToString(seg) + "_" + IntegerToString(j); DrawHorizontalLine(objName, level, SmallQuarterColor, SmallQuarterLineWidth, SmallQuarterLineStyle); } } } }
Outra função essencial é CreateOrUpdateLabel, que gerencia a exibição de texto no gráfico. Essa função verifica se um rótulo já existe e o cria caso não exista. Em seguida, atualiza o texto, a cor, o tamanho da fonte e outras propriedades do rótulo, utilizando uma fonte monoespaçada (Courier New) para garantir que quaisquer dados tabulares permaneçam bem alinhados. Essa função é particularmente importante para atualizar os comentários que explicam as condições do mercado.
void CreateOrUpdateLabel(string name, string text, int corner, int xdist, int ydist, color txtColor, int fontSize) { if(ObjectFind(0, name) == -1) { ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, name, OBJPROP_CORNER, corner); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, xdist); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, ydist); // Set a monospaced font for tabular display (Courier New) ObjectSetString(0, name, OBJPROP_FONT, "Courier New"); } ObjectSetString(0, name, OBJPROP_TEXT, text); ObjectSetInteger(0, name, OBJPROP_COLOR, txtColor); ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize); }
Quando o EA é inicializado (na função OnInit), ele cria um rótulo persistente no canto superior esquerdo do gráfico com a mensagem “Intrusion Detector Inicializado.” Por outro lado, quando o EA é removido (por meio da função OnDeinit), ele realiza a limpeza excluindo esse rótulo para manter o gráfico organizado.
int OnInit() { // Create a persistent commentary label in the top-left corner CreateOrUpdateLabel("IntrusionCommentary", "Intrusion Detector Initialized", CORNER_LEFT_UPPER, 10, 10, clrWhite, 14); return(INIT_SUCCEEDED); }
O coração do EA está na função OnTick, que é executada a cada novo tick de mercado. Quando o EA recebe um novo tick, a função OnTick é acionada. O primeiro passo nessa função é inicializar uma flag chamada intrusionDetected como false e recuperar o preço bid atual do mercado usando SymbolInfoDouble(_Symbol, SYMBOL_BID). Se o preço retornado for 0 (indicando um valor inválido ou indisponível), a função é encerrada imediatamente.
void OnTick() { bool intrusionDetected = false; double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); if(currentPrice == 0) return;
Em seguida, o EA chama a função DrawQuarters com o preço atual. Essa chamada é responsável por desenhar todos os níveis-chave no gráfico, incluindo níveis principais, linhas de quartis grandes e, se habilitado, as linhas de quartis menores, fornecendo a estrutura visual que define nosso intervalo. Logo após isso, o EA recalcula os limites do intervalo atual de 1000 PIPs determinando o nível lowerMajor usando MathFloor(currentPrice / MajorStep) * MajorStep e, em seguida, adicionando MajorStep para encontrar o nível upperMajor.
// Draw the quarter lines first DrawQuarters(currentPrice);
Para fornecer um comentário claro sobre o que o EA está detectando, é construída uma string em formato de tabela. Essa tabela começa com um cabeçalho que define três colunas: Zona, Preço e Motivo. Essas colunas são usadas para listar a relevância de cada nível quando o preço se aproxima deles.
double lowerMajor = MathFloor(currentPrice / MajorStep) * MajorStep; double upperMajor = lowerMajor + MajorStep;
O próximo passo envolve verificar se o preço está próximo de níveis-chave. O EA primeiro testa se o preço está dentro da tolerância especificada em relação ao limite inferior (Suporte Principal) ou ao limite superior (Resistência Principal). Se qualquer uma dessas condições for atendida, a função adiciona uma linha à tabela de comentários com a mensagem apropriada (usando mensagens predefinidas como "Nível-chave de suporte. Rompimento abaixo sinaliza mudança de faixa." para suporte, e uma mensagem semelhante para resistência) e define intrusionDetected como true.
// Check for Major Support if(MathAbs(currentPrice - lowerMajor) <= AlertTolerance) { table += StringFormat("%-18s | %-8s | %s\n", "Major Support", DoubleToString(lowerMajor,4), MajorSupportReason); intrusionDetected = true; } // Check for Major Resistance if(MathAbs(currentPrice - upperMajor) <= AlertTolerance) { table += StringFormat("%-18s | %-8s | %s\n", "Major Resistance", DoubleToString(upperMajor,4), MajorResistanceReason); intrusionDetected = true; }
Se o desenho das linhas de quartis grandes estiver habilitado, o EA então divide o intervalo em quartis e itera por esses níveis intermediários. Para cada quartil grande, ele verifica se o preço está dentro da tolerância; se estiver, adiciona uma linha correspondente (com uma mensagem como "Uma quebra decisiva pode acionar o próximo movimento de 250 PIPs.") à tabela. Além disso, se as áreas de overshoot estiverem habilitadas, a função calcula um pequeno deslocamento acima e abaixo de cada nível de quartil grande e verifica se o preço toca essas zonas de overshoot ou undershoot, novamente adicionando uma linha à tabela se a condição for atendida.
if(DrawLargeQuarters) { double LQIncrement = MajorStep / 4.0; for(int i = 1; i < 4; i++) { double level = lowerMajor + i * LQIncrement; if(MathAbs(currentPrice - level) <= AlertTolerance) { table += StringFormat("%-18s | %-8s | %s\n", "Large Quarter", DoubleToString(level,4), LargeQuarterReason); intrusionDetected = true; } if(DrawOvershootAreas) { double offset = MajorStep / 40.0; // ~25 pips double overshootUp = level + offset; double undershootDown = level - offset; if(MathAbs(currentPrice - overshootUp) <= AlertTolerance) { table += StringFormat("%-18s | %-8s | %s\n", "Overshoot", DoubleToString(overshootUp,4), OvershootReason); intrusionDetected = true; } if(MathAbs(currentPrice - undershootDown) <= AlertTolerance) { table += StringFormat("%-18s | %-8s | %s\n", "Undershoot", DoubleToString(undershootDown,4), UndershootReason); intrusionDetected = true; } } } }
Opcionalmente, se o EA estiver configurado para desenhar linhas de quartis pequenos, o intervalo é subdividido ainda mais. A função itera sobre essas divisões mais refinadas e realiza verificações de proximidade semelhantes, adicionando linhas com a mensagem "Flutuação menor" sempre que o preço se aproxima de um desses níveis de quartil pequeno.
if(DrawSmallQuarters) { double segStep = MajorStep / 10.0; double smallQuarter = segStep / 4.0; for(int seg = 0; seg < 10; seg++) { double segStart = lowerMajor + seg * segStep; for(int j = 1; j < 4; j++) { double level = segStart + j * smallQuarter; if(MathAbs(currentPrice - level) <= AlertTolerance) { table += StringFormat("%-18s | %-8s | %s\n", "Small Quarter", DoubleToString(level,4), SmallQuarterReason); intrusionDetected = true; } } } }
Se nenhum dos níveis acionar uma intrusão (ou seja, intrusionDetected permanecer false), o EA constrói uma mensagem padrão. Essa mensagem informa ao usuário que nenhuma intrusão significativa foi detectada e que o mercado aparenta estar em consolidação, ao mesmo tempo em que exibe o preço atual.
// If no zones were triggered, still provide full information if(!intrusionDetected) { table = StringFormat("No significant intrusion detected.\nCurrent Price: %s\nMarket consolidating within established quarters.\n", DoubleToString(currentPrice,4)); }
Após construir a tabela de comentários, o EA atualiza um rótulo no gráfico usando a função CreateOrUpdateLabel, garantindo que a análise mais recente seja exibida claramente no gráfico. Por fim, se uma intrusão for detectada e nenhum alerta tiver sido enviado anteriormente (controlado pela flag intrusionAlerted), o EA dispara um alerta com o conteúdo da tabela e define a flag como true para evitar notificações repetidas. Para garantir que todos os novos objetos e atualizações sejam imediatamente visíveis, a função termina chamando ChartRedraw.
// Update the label with the commentary table. CreateOrUpdateLabel("IntrusionCommentary", table, CORNER_LEFT_UPPER, 10, 10, clrWhite, 14); // Trigger an alert only once per intrusion event. if(intrusionDetected && !intrusionAlerted) { Alert(table); intrusionAlerted = true; } if(!intrusionDetected) intrusionAlerted = false; ChartRedraw(); }
Código Completo em MQL5
//+------------------------------------------------------------------+ //| Intrusion Detector | //| Copyright 2025, Christian Benjamin | //| https://www.mql5.com/en/users/lynnchris | //+------------------------------------------------------------------+ #property copyright "Christian Benjamin" #property link "https://www.mql5.com/en/users/lynnchris" #property version "1.0" #property strict //---- Input parameters ------------------------------------------------- input double MajorStep = 0.1000; // Difference between Major Whole Numbers (defines the 1000-PIP Range) input bool DrawLargeQuarters = true; // Draw intermediate Large Quarter lines. input bool DrawSmallQuarters = false; // Draw Small Quarter lines. input bool DrawOvershootAreas = true; // Mark overshoot/undershoot areas for Large Quarter lines. input double AlertTolerance = 0.0025; // Tolerance for detecting a "touch" (e.g., ~25 pips for a pair where 1 pip=0.0001) //---- Color settings --------------------------------------------------- input color MajorColor = 0x2F4F4F; // Dark Slate Gray for Major lines. input color LargeQuarterColor = 0x8B0000; // Dark Red for Large Quarter lines. input color SmallQuarterColor = 0x00008B; // Dark Blue for Small Quarter lines. input color OvershootColor = clrRed; // Red for overshoot/undershoot lines. //---- Line style and thickness settings ------------------------------- input ENUM_LINE_STYLE MajorLineStyle = STYLE_SOLID; input int MajorLineWidth = 4; input ENUM_LINE_STYLE LargeQuarterLineStyle = STYLE_DOT; input int LargeQuarterLineWidth = 3; input ENUM_LINE_STYLE OvershootLineStyle = STYLE_DASH; input int OvershootLineWidth = 1; input ENUM_LINE_STYLE SmallQuarterLineStyle = STYLE_SOLID; input int SmallQuarterLineWidth = 1; //---- Commentary Messages (customizable) ----------------------------- input string MajorSupportReason = "Key support level. Break below signals range shift."; input string MajorResistanceReason = "Pivotal resistance. Breakout above may start new range."; input string LargeQuarterReason = "Decisive break could trigger next 250-PIP move."; input string OvershootReason = "Test of breakout; reversal likely if momentum fails."; input string UndershootReason = "Insufficient bullish force; possible bearish reversal."; input string SmallQuarterReason = "Minor fluctuation."; // Global flag to avoid repeated alerts while price lingers at a level bool intrusionAlerted = false; //+------------------------------------------------------------------+ //| DrawHorizontalLine: Creates or replaces a horizontal line | //+------------------------------------------------------------------+ void DrawHorizontalLine(string name, double price, color lineColor, int width, ENUM_LINE_STYLE style) { if(ObjectFind(0, name) != -1) ObjectDelete(0, name); if(!ObjectCreate(0, name, OBJ_HLINE, 0, 0, price)) { Print("Failed to create line: ", name); return; } ObjectSetInteger(0, name, OBJPROP_COLOR, lineColor); ObjectSetInteger(0, name, OBJPROP_STYLE, style); ObjectSetInteger(0, name, OBJPROP_WIDTH, width); ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, true); } //+------------------------------------------------------------------+ //| DrawQuarters: Draws all quarter lines based on the current price | //+------------------------------------------------------------------+ void DrawQuarters(double currentPrice) { // Calculate the boundaries of the current 1000-PIP Range double lowerMajor = MathFloor(currentPrice / MajorStep) * MajorStep; double upperMajor = lowerMajor + MajorStep; // Draw Major Whole Number lines (defining the 1000-PIP Range) DrawHorizontalLine("MajorLower", lowerMajor, MajorColor, MajorLineWidth, MajorLineStyle); DrawHorizontalLine("MajorUpper", upperMajor, MajorColor, MajorLineWidth, MajorLineStyle); // Draw Large Quarter lines and their overshoot/undershoot areas if enabled if(DrawLargeQuarters) { double LQIncrement = MajorStep / 4.0; for(int i = 1; i < 4; i++) { double level = lowerMajor + i * LQIncrement; string objName = "LargeQuarter_" + IntegerToString(i); DrawHorizontalLine(objName, level, LargeQuarterColor, LargeQuarterLineWidth, LargeQuarterLineStyle); if(DrawOvershootAreas) { double offset = MajorStep / 40.0; // approximately 25 pips if MajorStep=0.1000 DrawHorizontalLine("Overshoot_" + IntegerToString(i) + "_up", level + offset, OvershootColor, OvershootLineWidth, OvershootLineStyle); DrawHorizontalLine("Undershoot_" + IntegerToString(i) + "_down", level - offset, OvershootColor, OvershootLineWidth, OvershootLineStyle); } } } // Draw Small Quarter lines if enabled (optional, finer divisions) if(DrawSmallQuarters) { double segStep = MajorStep / 10.0; double smallQuarter = segStep / 4.0; for(int seg = 0; seg < 10; seg++) { double segStart = lowerMajor + seg * segStep; for(int j = 1; j < 4; j++) { double level = segStart + j * smallQuarter; string objName = "SmallQuarter_" + IntegerToString(seg) + "_" + IntegerToString(j); DrawHorizontalLine(objName, level, SmallQuarterColor, SmallQuarterLineWidth, SmallQuarterLineStyle); } } } } //+------------------------------------------------------------------+ //| CreateOrUpdateLabel: Creates or updates a label with given text | //+------------------------------------------------------------------+ void CreateOrUpdateLabel(string name, string text, int corner, int xdist, int ydist, color txtColor, int fontSize) { if(ObjectFind(0, name) == -1) { ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, name, OBJPROP_CORNER, corner); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, xdist); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, ydist); // Set a monospaced font for tabular display (Courier New) ObjectSetString(0, name, OBJPROP_FONT, "Courier New"); } ObjectSetString(0, name, OBJPROP_TEXT, text); ObjectSetInteger(0, name, OBJPROP_COLOR, txtColor); ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize); } //+------------------------------------------------------------------+ //| OnInit: Initialization function for the EA | //+------------------------------------------------------------------+ int OnInit() { // Create a persistent commentary label in the top-left corner CreateOrUpdateLabel("IntrusionCommentary", "Intrusion Detector Initialized", CORNER_LEFT_UPPER, 10, 10, clrWhite, 14); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| OnDeinit: Deinitialization function for the EA | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Remove the commentary label on exit ObjectDelete(0, "IntrusionCommentary"); } //+------------------------------------------------------------------+ //| OnTick: Main function called on every tick | //+------------------------------------------------------------------+ void OnTick() { bool intrusionDetected = true; double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); if(currentPrice == 0) return; // Draw the quarter lines first DrawQuarters(currentPrice); // Calculate boundaries of the current 1000-PIP Range double lowerMajor = MathFloor(currentPrice / MajorStep) * MajorStep; double upperMajor = lowerMajor + MajorStep; // Build a tabular commentary string with a header. string header = StringFormat("%-18s | %-8s | %s\n", "Zone", "Price", "Reason"); string separator = "----------------------------------------------\n"; string table = header + separator; // Check for Major Support if(MathAbs(currentPrice - lowerMajor) <= AlertTolerance) { table += StringFormat("%-18s | %-8s | %s\n", "Major Support", DoubleToString(lowerMajor,4), MajorSupportReason); intrusionDetected = true; } // Check for Major Resistance if(MathAbs(currentPrice - upperMajor) <= AlertTolerance) { table += StringFormat("%-18s | %-8s | %s\n", "Major Resistance", DoubleToString(upperMajor,4), MajorResistanceReason); intrusionDetected = true; } // Check Large Quarter Levels and Overshoot/Undershoot Zones if(DrawLargeQuarters) { double LQIncrement = MajorStep / 4.0; for(int i = 1; i < 4; i++) { double level = lowerMajor + i * LQIncrement; if(MathAbs(currentPrice - level) <= AlertTolerance) { table += StringFormat("%-18s | %-8s | %s\n", "Large Quarter", DoubleToString(level,4), LargeQuarterReason); intrusionDetected = true; } if(DrawOvershootAreas) { double offset = MajorStep / 40.0; // ~25 pips double overshootUp = level + offset; double undershootDown = level - offset; if(MathAbs(currentPrice - overshootUp) <= AlertTolerance) { table += StringFormat("%-18s | %-8s | %s\n", "Overshoot", DoubleToString(overshootUp,4), OvershootReason); intrusionDetected = true; } if(MathAbs(currentPrice - undershootDown) <= AlertTolerance) { table += StringFormat("%-18s | %-8s | %s\n", "Undershoot", DoubleToString(undershootDown,4), UndershootReason); intrusionDetected = true; } } } } // Check Small Quarter Levels (if enabled) if(DrawSmallQuarters) { double segStep = MajorStep / 10.0; double smallQuarter = segStep / 4.0; for(int seg = 0; seg < 10; seg++) { double segStart = lowerMajor + seg * segStep; for(int j = 1; j < 4; j++) { double level = segStart + j * smallQuarter; if(MathAbs(currentPrice - level) <= AlertTolerance) { table += StringFormat("%-18s | %-8s | %s\n", "Small Quarter", DoubleToString(level,4), SmallQuarterReason); intrusionDetected = true; } } } } // If no zones were triggered, still provide full information if(!intrusionDetected) { table = StringFormat("No significant intrusion detected.\nCurrent Price: %s\nMarket consolidating within established quarters.\n", DoubleToString(currentPrice,4)); } // Update the label with the commentary table. CreateOrUpdateLabel("IntrusionCommentary", table, CORNER_LEFT_UPPER, 10, 10, clrWhite, 14); // Trigger an alert only once per intrusion event. if(intrusionDetected && !intrusionAlerted) { Alert(table); // Alternatively, you could use: PlaySound("alert.wav"); intrusionAlerted = true; } if(!intrusionDetected) intrusionAlerted = false; ChartRedraw(); } //+------------------------------------------------------------------+
Resultados
Aqui, apresentarei os resultados que obtive após testar a ferramenta em um ambiente de mercado real, embora tenha utilizado uma conta demo para esse propósito. Abaixo está um diagrama representando o Dólar Neozelandês (NZD) em relação ao Dólar dos Estados Unidos (USD). O preço se aproximou do nível de undershoot, acionando um alerta.
O alerta forneceu informações críticas, incluindo a zona identificada, que neste caso foi a zona de undershoot. O nível de preço específico em que essa zona foi detectada é 0.5725. Além disso, o alerta incluiu uma análise das condições de mercado nesse nível, indicando impulso comprador insuficiente e a possibilidade de uma reversão para baixa.

Fig 3. NZD vs USD
Abaixo está a informação registrada na aba Experts do MetaTrader 5.
2025.02.25 16:55:37.188 Intrusion Detector EA (NZDUSD,H1) Alert: Zone | Price | Reason 2025.02.25 16:55:37.188 Intrusion Detector EA (NZDUSD,H1) ---------------------------------------------- 2025.02.25 16:55:37.188 Intrusion Detector EA (NZDUSD,H1) Undershoot | 0.5725 | Insufficient bullish force; possible bearish reversal. 2025.02.25 16:55:37.188 Intrusion Detector EA (NZDUSD,H1)
Vamos analisar a operação que executei após essa detecção e análise adicional.

Fig 3. Teste de Trading
Abaixo está a posição final do mercado, embora eu tenha encerrado minhas operações rapidamente.

Fig 5. Movimento do Mercado
A Figura 6 abaixo é um GIF que demonstra um teste que conduzi no par de moedas USD/CAD, no qual duas zonas foram identificadas onde o preço reagiu ao overshoot e ao nível de quartil grande.

Fig 6. USDCAD
Conclusão
Nosso expert advisor atua como um poderoso assistente de análise, projetado especificamente para monitorar zonas de preço em conformidade com a Teoria dos Quartis. Essa ferramenta é particularmente valiosa para traders que incorporam a Teoria dos Quartis em sua análise de mercado. Com base em nossos testes extensivos, o EA se destaca na detecção de zonas-chave de preço, emissão de alertas oportunos e fornecimento de monitoramento eficiente do mercado em segundo plano. Este desenvolvimento representa um avanço significativo na automação da análise de mercado utilizando a Teoria dos Quartis. Anteriormente, focamos na automação do desenho dos quartis, e agora avançamos para o monitoramento em tempo real desses níveis. Essa melhoria garante que os traders sejam prontamente informados sempre que o preço interagir com esses níveis críticos, acompanhados de uma explicação concisa sobre possíveis mudanças no mercado.
No entanto, este não é o estágio final da nossa jornada. Espere por mais inovações na aplicação da Teoria dos Quartis na automação de mercado. Dito isso, encorajo todos os traders que utilizam esta ferramenta a integrarem suas próprias estratégias, em vez de depender exclusivamente dos sinais fornecidos. Uma abordagem equilibrada, combinando automação com experiência pessoal, leva a decisões de trading mais informadas.
| Data | Nome da Ferramenta | Descrição | Versâo | Notas | |
|---|---|---|---|---|---|
| 01/10/24 | Projetor de gráficos | Script para sobrepor a ação de preço do dia anterior com efeito fantasma. | 1.0 | Lançamento Inicial | Ferramenta número 1 |
| 18/11/24 | Comentário Analítico | Ele fornece informações do dia anterior em formato tabular, além de antecipar a direção futura do mercado. | 1.0 | Lançamento Inicial | Ferramenta número 2 |
| 27/11/24 | Mestre em Análise | Atualização regular das métricas de mercado a cada duas horas | 1.01 | Segunda Versão | Ferramenta número 3 |
| 02/12/24 | Previsor Analítico | Atualização regular das métricas de mercado a cada duas horas com integração ao Telegram | 1.1 | Terceira Edição | Ferramenta número 4 |
| 09/12/24 | Navegador de Volatilidade | O EA analisa as condições de mercado utilizando os indicadores Bollinger Bands, RSI e ATR | 1.0 | Lançamento Inicial | Ferramenta número 5 |
| 19/12/24 | Reversão à Média Ceifador de Sinal | Analisa o mercado utilizando estratégia de reversão à média e fornece sinal | 1.0 | Lançamento Inicial | Ferramenta número 6 |
| 9/01/25 | Pulso de sinal | Analisador de múltiplos timeframes | 1.0 | Lançamento Inicial | Ferramenta número 7 |
| 17/01/25 | Quadro de Métricas | Painel com botão para análise | 1.0 | Lançamento Inicial | Ferramenta número 8 |
| 21/01/25 | Fluxo externo | Análises por meio de bibliotecas externas | 1.0 | Lançamento Inicial | Ferramenta número 9 |
| 27/01/25 | VWAP | Preço médio ponderado por volume | 1.3 | Lançamento Inicial | Ferramenta número 10 |
| 02/02/25 | Heikin Ashi | Suavização de tendências e identificação de sinais de reversão | 1.0 | Lançamento Inicial | Ferramenta número 11 |
| 04/02/25 | FibVWAP | Geração de sinais por meio de análise em Python | 1.0 | Lançamento Inicial | Ferramenta número 12 |
| 14/02/25 | DIVERGÊNCIA RSI | Divergências entre price action e RSI | 1.0 | Lançamento Inicial | Ferramenta número 13 |
| 17/02/25 | Parada e Reversão Parabólicas (PSAR) | Automação da estratégia PSAR | 1.0 | Lançamento Inicial | Ferramenta número 14 |
| 20/02/25 | Quarters Drawer Script | Desenho dos níveis de quartis no gráfico | 1.0 | Lançamento Inicial | Ferramenta número 15 |
| 27/02/25 | Detector de intrusão | Detectar e alertar quando o preço atingir os níveis trimestrais. | 1.0 | Lançamento Inicial | Ferramenta número 16 |
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/17321
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.
Otimização por Comunidade de Cientistas - Community of Scientist Optimization (CoSO): Teoria
Algoritmo de Aprendizagem Competitiva - Competitive Learning Algorithm (CLA)
Está chegando o novo MetaTrader 5 e MQL5
Redes neurais em trading: Modelo multidimensional de ponta a ponta para previsão de séries temporais (Conclusão)
- 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