Desenvolvimento de ferramentas para análise de Price Action (Parte 33): Ferramenta baseada na Teoria da Amplitude das Velas
Sumário
Introdução
A volatilidade é a principal linguagem do mercado. Antes mesmo de qualquer oscilador mudar de direção ou de a maioria dos filtros de tendência reagir, o preço já terá deixado clara sua intenção pela amplitude do movimento registrado em uma única barra. Uma expansão repentina da amplitude costuma indicar uma atuação agressiva dos grandes participantes do mercado. Já uma compressão prolongada sugere uma redução da liquidez enquanto o mercado aguarda o próximo movimento. Da mesma forma, uma barra cujo intervalo de preços fica inteiramente contido no intervalo da barra anterior indica uma indecisão temporária, enquanto uma barra que abrange todo o intervalo de preços da barra anterior reflete um fluxo agressivo de ordens. Esses comportamentos são facilmente reconhecíveis, mas raramente são formalizados em um procedimento robusto que permita seu processamento automatizado.
Neste artigo, apresentamos o sistema Candle-Range Theory (CRT), um framework compacto que classifica cada vela fechada em uma das quatro categorias mutuamente exclusivas:
- Large-Range (LR): a amplitude verdadeira da vela supera um múltiplo predefinido do Average True Range (ATR) recente;
- Small-Range (SR): a amplitude da vela é inferior ao ATR multiplicado pelo fator inferior predefinido, indicando compressão;
- Inside Bar (IB): todo o intervalo de preços da vela permanece entre a mínima e a máxima da barra imediatamente anterior;
- Outside Bar (OB): durante sua formação, a vela registra uma máxima superior à máxima da barra anterior e uma mínima inferior à mínima anterior, abrangendo todo o intervalo de preços da barra anterior.
Em vez de apresentar mais um indicador cujo funcionamento interno é pouco transparente, o CRT reúne esses conceitos claramente definidos em um conjunto compacto de ferramentas para MetaTrader 5, pronto para uso prático:
- CRangePattern.mqh: classe implementada inteiramente em um arquivo de cabeçalho, capaz de classificar cada vela em tempo constante. Utiliza apenas quatro arrays de preços (open, high, low, close), retorna sinalizadores booleanos para cada padrão e não utiliza alocação dinâmica de memória.
- CRT Indicator.mq5: indicador sobreposto ao gráfico que destaca as velas LR, SR, IB e OB por meio de retângulos semitransparentes e, opcionalmente, setas. As cores, a transparência, os símbolos das setas e suas dimensões são totalmente configuráveis, permitindo integrar a representação visual a qualquer template de gráfico existente, sem esbarrar no limite de oito buffers da plataforma.
- CRT Expert Advisor.mq5: módulo de alertas que opera exclusivamente com barras fechadas, garantindo sinais que não repintam. Permite selecionar quais padrões devem acionar alertas em janelas pop-up, sinais sonoros ou notificações push. Opcionalmente, também pode carregar o indicador de forma automática, mantendo os alertas visuais e sonoros sincronizados durante a negociação em ambiente real ou os testes em modo visual.
Todos os componentes são compilados sem avisos no MetaTrader 5 a partir da build 4180 e seguem as exigências da diretiva #property strict. Eles copiam apenas um pequeno trecho do histórico, suficiente para calcular o ATR, mantendo baixa a carga sobre o processador mesmo em gráficos de alta frequência. Como o sistema processa os dados exclusivamente no fechamento de cada vela, os resultados permanecem estáveis em diferentes timeframes, símbolos e modos de teste.
Este guia tem quatro objetivos:
- apresentar as definições matemáticas precisas dos padrões LR, SR, IB e OB;
- mostrar como integrar a classe CRangePattern a qualquer indicador, EA ou script;
- explicar as decisões de implementação que mantêm o indicador leve, sem cintilação dos elementos gráficos e compatível com templates de gráficos complexos;
- demonstrar como o EA gera alertas que funcionam corretamente no testador, permitindo avaliar os sinais CRT tanto em dados históricos quanto em tempo real.
Ao final do artigo, você terá um sistema compacto, mas extensível, capaz de transformar medidas básicas de volatilidade em informações claras e úteis na prática, que poderão ser utilizadas na análise discricionária, na negociação automatizada ou em estudos posteriores.
Vantagens do conjunto de ferramentas Candle-Range Theory:
| Vantagem | Descrição | Benefício prático |
|---|---|---|
| Definições precisas | Os padrões LR, SR, IB e OB são calculados por fórmulas explícitas baseadas no ATR e nas relações entre os preços. | Elimina ambiguidades: cada vela é classificada em uma única categoria. |
| Lógica sem repainting | Todos os cálculos são realizados com base na barra que acaba de fechar, sem recálculo posterior dos valores. | Os sinais permanecem estáveis durante a atualização do gráfico, a otimização e a negociação em ambiente real. |
| Volume mínimo de dados | O indicador copia apenas ATR_Period + 3 barras, e o EA também copia essa mesma quantidade. | Reduz o consumo de memória RAM e acelera as execuções no Strategy Tester. |
| Exibição sem buffers | Os elementos visuais são desenhados por meio de objetos gráficos, em vez de buffers do indicador. | Permite contornar o limite de oito buffers do MetaTrader e mantém a compatibilidade com templates de gráficos complexos. |
| Flexibilidade de configuração | O usuário pode definir as cores, a transparência, os símbolos das setas, o período do ATR e os multiplicadores largeMult e smallMult. | Facilita a adaptação a qualquer padrão visual de gráficos, seja pessoal ou corporativo. |
| Arquitetura modular | A classe, o indicador e o EA são arquivos independentes que se comunicam por interfaces bem definidas. | Os desenvolvedores podem incorporar a classe a outros projetos ou substituir o indicador sem precisar refatorar o código. |
| Conformidade com o modo estrito (#property strict) | Todos os arquivos de código-fonte são compilados sem erros com a diretiva #property strict nas builds 4180 e posteriores. | Proporciona máxima compatibilidade com futuras builds do MetaTrader. |
| Normalização pelo ATR | Os limites de amplitude são ajustados automaticamente à volatilidade do ativo. | Permite utilizar as mesmas configurações de forma confiável em Forex, CFDs, criptomoedas, índices e futuros. |
Visão geral da estratégia
A Teoria da Amplitude das Velas classifica cada vela fechada em uma única categoria entre quatro possíveis. Uma vela cuja amplitude verdadeira supera significativamente a volatilidade recente é classificada como Large-Range (LR), enquanto uma vela cuja amplitude se reduz a uma fração do valor habitual é classificada como Small-Range (SR). Se todo o intervalo de preços da nova barra, entre sua máxima e sua mínima, estiver contido no intervalo da barra anterior, ela será classificada como Inside Bar (IB). Se, por outro lado, a nova barra registrar uma máxima superior à máxima anterior e uma mínima inferior à mínima anterior, será classificada como Outside Bar (OB). Nas seções seguintes, examinaremos os fundamentos estatísticos e os critérios exatos utilizados para identificar cada um desses quatro padrões.
Amplitude verdadeira (TR)
A amplitude verdadeira (True Range, TR) é uma medida básica de volatilidade proposta por Wilder. Ela considera toda a variação de preços registrada durante um período, incluindo eventuais gaps, e corresponde ao maior dos seguintes valores:
- máxima atual menos mínima atual;
- valor absoluto da diferença entre a máxima atual e o fechamento anterior;
- valor absoluto da diferença entre a mínima atual e o fechamento anterior.
TR = max( Highₜ – Lowₜ, │Highₜ – Closeₜ₋₁│, │Lowₜ – Closeₜ₋₁│ )
Ao utilizar o True Range em vez da simples diferença entre máxima e mínima, também consideramos integralmente os gaps noturnos, mantendo a avaliação da volatilidade consistente entre diferentes instrumentos e sessões de negociação.
Amplitude verdadeira média (Average True Range, ATR)
Isoladamente, o True Range oferece pouca informação sem um contexto de comparação: 25 pips no EURUSD representam um movimento expressivo, enquanto 25 pips no XAUUSD são praticamente insignificantes. A Teoria da Amplitude das Velas leva essa diferença em consideração ao normalizar o True Range de cada período pela média dos últimos N valores. Isso suaviza o impacto de picos repentinos e fornece uma referência estável para avaliar a volatilidade.
// Simple arithmetic ATR double ATR(const int shift,const int period, const double &H[],const double &L[],const double &C[]) { double sum = 0.0; for(int i = shift; i < shift + period; ++i) sum += MathMax(H[i]-L[i], MathMax(MathAbs(H[i]-C[i+1]), MathAbs(C[i+1]-L[i]))); return sum / period; }
Na prática, o CRT utiliza uma média aritmética simples, em vez da suavização exponencial de Wilder, pois esse método é mais rápido, transparente e suficiente para classificar o comportamento dos preços. Por padrão, o cálculo considera uma janela de 14 barras, correspondente à configuração tradicional do ATR.
Multiplicadores de amplitude: limites de classificação
Dois multiplicadores configuráveis pelo usuário permitem estabelecer os limites de classificação com base no ATR:- largeMult (padrão: 1,5);
- smallMult (padrão: 0,5).
// ---- User-defined ATR multipliers -------------------------------------- input double largeMult = 1.5; // Bars ≥ 1.5 × ATR are flagged “Large-Range” input double smallMult = 0.5; // Bars ≤ 0.5 × ATR are flagged “Small-Range”Esses parâmetros respondem a duas perguntas:
- Quanto a amplitude de uma barra precisa superar a média para ser considerada excepcionalmente grande?
- Qual deve ser a amplitude de uma barra para que ela seja considerada comprimida?
Ao expressar esses limites como múltiplos do ATR, o CRT pode ser aplicado a diferentes símbolos, timeframes e regimes de volatilidade.
Barras Large-Range: indício de atividade repentina dos participantes do mercado
Uma vela é classificada como Large-Range quando sua amplitude verdadeira é igual ou superior ao ATR atual multiplicado pelo fator configurado em largeMult.// ---- Large-Range (LR) test --------------------------------------------- bool isLargeRange = (trueRange >= largeMult * atrCurrent);
Uma amplitude tão elevada costuma surgir em períodos de intensa participação no mercado, muitas vezes provocada pela divulgação de notícias programadas ou por operações de grande volume. Essas barras de amplitude elevada geralmente antecedem o início de um movimento direcional sustentado ou a capitulação final da tendência anterior. Em ambos os casos, são eventos bastante informativos: "o que" aconteceu (uma amplitude excepcionalmente grande) é evidente, mesmo que "por que" aconteceu (divulgação de resultados financeiros, dados macroeconômicos ou liquidações forçadas) nem sempre esteja claro.
Barras Small-Range (SR): compressão da volatilidade
Por outro lado, uma vela é classificada como Small-Range quando sua amplitude verdadeira é igual ou inferior ao ATR atual multiplicado pelo fator configurado em smallMult. Uma compressão persistente costuma indicar redução da liquidez, operações de hedge realizadas por dealers ou equilíbrio no livro de ordens.
// ---- Small-Range (SR) test --------------------------------------------- bool isSmallRange = (trueRange <= smallMult * atrCurrent);
Os mercados raramente permanecem calmos indefinidamente. Agrupamentos de barras SR frequentemente indicam uma pausa antes de uma nova expansão da amplitude, o que os torna especialmente úteis em estratégias de rompimento e estratégias straddle.
Inside Bars (IB): compressão da amplitude e indecisão
Uma vela é classificada como Inside Bar quando todo o seu intervalo de preços permanece contido no intervalo da vela anterior, ou seja, quando sua máxima é inferior à máxima anterior e sua mínima é superior à mínima anterior.
// Inside-Bar test for the candle at 'shift' (e.g., shift = 1 → just-closed bar) bool isInsideBar = (High[shift] < High[shift + 1]) && // current high is lower than previous high (Low[shift] > Low[shift + 1]); // current low is higher than previous low
Já as velas Outside Bar indicam um fluxo intenso de ordens, frequentemente associado à caça aos stops, liquidações forçadas ou acumulação/distribuição agressiva. Como o preço ultrapassa os extremos da vela anterior em ambas as direções, as barras OB podem varrer vários níveis de ordens stop durante uma única sessão. Isso frequentemente resulta em uma reversão sustentada, quando predomina a absorção, ou na aceleração da tendência original, quando a liquidez do rompimento se esgota rapidamente.
Exclusividade mútua e hierarquia
As quatro categorias foram concebidas para serem mutuamente exclusivas: uma vela pode atender aos critérios de, no máximo, uma categoria.
- Se uma vela atender aos critérios de LR ou SR, as regras baseadas na amplitude terão prioridade.
- Se nenhuma das condições de LR ou SR for atendida, o sistema verificará a condição de IB.
- Somente se a condição de IB não for atendida, o sistema verificará a condição de OB.
Essa hierarquia resolve possíveis sobreposições nos critérios de classificação e torna inequívoca a lógica utilizada nas etapas seguintes, como a geração de alertas e a marcação visual dos padrões.
Critério temporal: processamento de barras fechadas
O CRT analisa apenas a última vela fechada (barra 1), ignorando a barra ainda em formação (barra 0). Isso garante sinais sem repainting: o que aparece em tempo real corresponde exatamente ao que seria apresentado em um teste com dados históricos.
Dos dados brutos aos sinais práticos
Ao classificar cada barra em um dos quatro estados, o CRT fornece:
- um fluxo de sinais binários para estratégias automatizadas (sinalizadores true/false para cada categoria);
- uma linguagem visual para a negociação discricionária (marcação das barras por cores e setas);
- um sistema de gatilhos para alertas e filtros adicionais (tendência, sessão, volume).
Análise do código
O conjunto de ferramentas Candle-Range Theory foi desenvolvido intencionalmente com uma arquitetura modular. Cada componente, seja o arquivo de cabeçalho, o indicador ou o EA, desempenha uma função bem definida e se comunica com os demais por meio de uma interface mínima. Nesta seção, analisaremos o código-fonte na mesma sequência em que o MetaTrader o executa, explicando a finalidade de cada bloco principal e as razões das escolhas de implementação.
CandleRangeTheory.mqh: mecanismo de classificação
O arquivo de cabeçalho começa com a diretiva #property strict, que ativa uma verificação de tipos mais rigorosa e elimina as regras de validação mais permissivas das versões antigas do compilador. Logo em seguida, é declarada a classe CRangePattern. Seus campos públicos, atrPeriod, largeMult e smallMult, funcionam como parâmetros configuráveis em tempo de execução, e não como constantes fixas. Assim, qualquer script que inclua esse arquivo de cabeçalho pode modificar o comportamento da classe sem precisar recompilá-la. Quatro sinalizadores booleanos, isLarge, isSmall, isInside e isOutside, constituem a interface de saída. Após a execução de Calculate(), exatamente um desses sinalizadores terá o valor true. Dessa forma, o código que chamou o método não precisará realizar cálculos adicionais para identificar o padrão observado na vela analisada.
#property strict // enforce modern type checking #ifndef __CANDLE_RANGE_THEORY_MQH__ #define __CANDLE_RANGE_THEORY_MQH__ class CRangePattern { public: int atrPeriod; // ATR length double largeMult,smallMult; // LR / SR thresholds bool isLarge,isSmall, isInside,isOutside; // output flags double atr,trueRange,bodyRange;
O construtor define valores padrão adequados ao uso prático: período de ATR igual a 14, multiplicador superior de 1,5 e multiplicador inferior de 0,5. Em seguida, chama o método auxiliar privado Reset(), que inicializa todos os campos de resultado com valores conhecidos. O uso desse método evita a duplicação de código, pois a mesma rotina é executada tanto no construtor quanto no início de cada cálculo.
private: void Reset() { isLarge=isSmall=isInside=isOutside=false; atr=trueRange=bodyRange=0.0; } public: CRangePattern() // default parameters { Reset(); atrPeriod=14; largeMult=1.5; smallMult=0.5; }
O método Calculate() foi mantido intencionalmente conciso. Primeiro, verifica se há histórico suficiente disponível (bars < atrPeriod + sh + 2), pois tanto o cálculo do ATR quanto o da amplitude verdadeira exigem pelo menos uma barra anterior àquela que está sendo avaliada. A amplitude verdadeira e a amplitude do corpo da vela são calculadas conforme a definição de Wilder, garantindo compatibilidade com valores de ATR calculados pelo método convencional, seja ele calculado pelo próprio script ou obtido de um indicador externo.
bool Calculate(const int sh, const double &H[],const double &L[], const double &O[],const double &C[], const int bars) { Reset(); if(bars < atrPeriod + sh + 2) // enough candles? return false; // true range of target candle trueRange = MathMax(H[sh]-L[sh], MathMax(MathAbs(H[sh]-C[sh+1]), MathAbs(C[sh+1]-L[sh]))); bodyRange = MathAbs(O[sh]-C[sh]);
O laço de cálculo do ATR executa exatamente atrPeriod iterações. Como a verificação anterior já garante que i + 1 permaneça dentro dos limites válidos do histórico, a condição adicional && i+1 < bars seria redundante e, por isso, foi omitida. A remoção dessa verificação simplifica a execução do código e elimina uma ramificação desnecessária, melhorando o desempenho no processamento de dados de alta frequência sem introduzir riscos de acesso fora dos limites dos arrays.
double sum = 0.0; for(int i = sh; i < sh + atrPeriod; ++i) // exactly atrPeriod { double tr = MathMax(H[i]-L[i], MathMax(MathAbs(H[i]-C[i+1]), MathAbs(C[i+1]-L[i]))); sum += tr; } atr = sum / atrPeriod;
Após calcular a média, a função classifica a vela. Se a amplitude verdadeira superar o limite superior definido pelo ATR multiplicado por largeMult, isLarge receberá o valor true. Se ficar abaixo do limite inferior definido pelo ATR multiplicado por smallMult, isSmall receberá true. Na segunda etapa da classificação, o sistema compara os extremos da vela com a máxima e a mínima da vela anterior, definindo isInside ou isOutside conforme o resultado. Como os quatro sinalizadores são mutuamente exclusivos, não são necessárias verificações adicionais, e a função retorna true para confirmar que o cálculo foi concluído com sucesso.
if(trueRange >= largeMult*atr) isLarge = true; else if(trueRange <= smallMult*atr) isSmall = true; if(H[sh] < H[sh+1] && L[sh] > L[sh+1]) isInside = true; else if(H[sh] > H[sh+1] && L[sh] < L[sh+1]) isOutside = true; return true; } #endif
CRT Indicator.mq5: representação visual
O arquivo do indicador não utiliza buffers, recorrendo exclusivamente a objetos gráficos. Essa abordagem permite contornar o limite de oito buffers do MetaTrader e dá ao trader a liberdade de combinar essa marcação visual com outros indicadores. Durante a inicialização, os valores definidos na janela Inputs são atribuídos diretamente aos campos públicos da instância interna de CRangePattern, chamada pat. Nenhum outro estado é mantido globalmente. Assim, qualquer alteração de parâmetros no MetaTrader provoca uma reinicialização completa, sem preservar parcialmente o estado anterior.
#property indicator_chart_window #include <CandleRangeTheory.mqh> input int ATR_Period = 14; ... CRangePattern pat; int OnInit() { pat.atrPeriod = ATR_Period; pat.largeMult = LargeXATR; pat.smallMult = SmallXATR; return(INIT_SUCCEEDED); }
A função OnCalculate() é chamada sempre que o MetaTrader identifica uma atualização dos dados disponíveis. Primeiro, verifica se há pelo menos atrPeriod + 3 barras disponíveis no gráfico. As duas barras adicionais são necessárias porque o laço de cálculo do ATR exige uma barra anterior à atual, enquanto o próprio Calculate() acessa uma vela com deslocamento adicional de +1. Em seguida, apenas um pequeno trecho do histórico, correspondente a essa quantidade de barras, é copiado para quatro arrays locais (H, L, O, C). Cada array é então configurado como série temporal, de modo que o índice 0 sempre corresponda à barra mais recente.
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { const int need = pat.atrPeriod + 3; if(rates_total < need) return rates_total; double H[],L[],O[],C[]; ArrayResize(H,need); ArraySetAsSeries(H,true); ArrayResize(L,need); ArraySetAsSeries(L,true); ArrayResize(O,need); ArraySetAsSeries(O,true); ArrayResize(C,need); ArraySetAsSeries(C,true); CopyHigh (_Symbol,_Period,0,need,H); CopyLow (_Symbol,_Period,0,need,L); CopyOpen (_Symbol,_Period,0,need,O); CopyClose(_Symbol,_Period,0,need,C);
Após a preparação dos dados, o indicador chama pat.Calculate(1, …). O deslocamento igual a 1 garante que a análise seja realizada sobre a última barra fechada, e não sobre a vela ainda em formação. Se a classificação não ativar nenhum sinalizador, ou seja, se a vela não corresponder a nenhum dos padrões large, small, inside ou outside, a função é encerrada imediatamente, sem modificar o gráfico. Quando um padrão é identificado, o indicador configura os elementos visuais: a cor do retângulo é definida por valores ARGB, permitindo controlar a transparência, enquanto o código do caractere gráfico da seta e sua cor são determinados pelas configurações do usuário.
if(!pat.Calculate(1,H,L,O,C,need)) return rates_total; uint rClr = 0; // rectangle colour (ARGB) int aCode = 221; // ● default arrow color aClr = clrYellow; if(pat.isLarge) { bool bull = (C[1] > O[1]); rClr = ColorToARGB(bull?clrLime:clrRed,Opacity); aCode = bull ? 233 /*▲*/ : 234 /*▼*/; aClr = bull ? clrLime : clrRed; } else if(pat.isSmall) { rClr = ColorToARGB(clrYellow,Opacity); } else if(pat.isInside) { rClr = ColorToARGB(clrAqua,Opacity); } else if(pat.isOutside) { rClr = ColorToARGB(clrMagenta,Opacity);} else return rates_total; // nothing to draw
Para criar o retângulo, são utilizadas duas coordenadas de tempo: o horário de abertura da barra com deslocamento 2 e o horário de abertura da barra com deslocamento 1. Dessa forma, o retângulo abrange toda a duração da vela analisada. A máxima e a mínima dessa vela determinam seus limites verticais. A propriedade OBJPROP_FILL recebe o valor true, fazendo com que o retângulo apareça como uma área preenchida e semitransparente, em vez de apenas um contorno. Opcionalmente, uma seta é posicionada um pouco acima ou abaixo da vela, com um afastamento proporcional ao ATR. Isso mantém a seta visível mesmo em instrumentos com tamanhos de tick muito diferentes. Tanto o retângulo quanto a seta recebem, em seus nomes, a marca de tempo de abertura da vela. Isso garante nomes exclusivos e permite que o indicador remova objetos anteriores com o mesmo nome antes de criar novos.
datetime tClosed = iTime(_Symbol,_Period,1); string tagR = "CRT_RECT_"+(string)tClosed; string tagA = "CRT_ARW_" +(string)tClosed; ObjectDelete(0,tagR); // avoid duplicates ObjectCreate(0,tagR,OBJ_RECTANGLE,0, iTime(_Symbol,_Period,2),H[1], tClosed,L[1]); ObjectSetInteger(0,tagR,OBJPROP_COLOR,rClr); ObjectSetInteger(0,tagR,OBJPROP_FILL,true); ObjectSetInteger(0,tagR,OBJPROP_BACK,true); double y = (aCode==233 ? H[1]+0.2*pat.atr : L[1]-0.2*pat.atr); ObjectCreate(0,tagA,OBJ_ARROW,0,tClosed,y); ObjectSetInteger(0,tagA,OBJPROP_ARROWCODE,aCode); ObjectSetInteger(0,tagA,OBJPROP_COLOR,aClr); return rates_total; }
CandleRangeTheory.mq5: geração de alertas
O EA utiliza o mesmo arquivo de cabeçalho e, consequentemente, a mesma lógica determinística de classificação. Durante a inicialização, ele atribui os parâmetros aos campos públicos de sua instância de CRangePattern, da mesma forma que o indicador. Além disso, verifica se está sendo executado no Strategy Tester em modo não visual. Nesse caso, funções de interface gráfica, como Alert() ou PlaySound(), não são chamadas, evitando erros em tempo de execução durante a otimização em lote.
#include <CandleRangeTheory.mqh> input bool Push_Alerts = false; ... CRangePattern pat; const bool NonVisualTest = (bool)MQLInfoInteger(MQL_TESTER) && !MQLInfoInteger(MQL_VISUAL_MODE); int OnInit() { pat.atrPeriod = ATR_Period; pat.largeMult = LargeXATR; pat.smallMult = SmallXATR; return INIT_SUCCEEDED; }
Quando o EA está anexado a um gráfico em ambiente real ou é executado em um teste visual, utiliza iCustom() para carregar automaticamente o indicador. O sucesso do carregamento ou eventuais erros são registrados no log da aba "Experts". Durante a desinicialização, todos os handles do indicador são liberados manualmente para evitar vazamentos de memória e o acúmulo de elementos no gráfico.
int indHndl = INVALID_HANDLE; int OnInit() { ... if(!NonVisualTest) { indHndl = iCustom(_Symbol,_Period,"CRT Indicator", ATR_Period,LargeXATR,SmallXATR); if(indHndl != INVALID_HANDLE) ChartIndicatorAdd(0,0,indHndl); } return INIT_SUCCEEDED; } void OnDeinit(const int reason) { if(indHndl != INVALID_HANDLE) IndicatorRelease(indHndl); }
A lógica principal está concentrada em OnTick(). O EA armazena o horário de abertura da vela com deslocamento 1 e não repete o processamento enquanto esse valor não mudar, garantindo exatamente uma verificação por vela fechada, independentemente da frequência dos ticks. Em seguida, copia um pequeno bloco de dados históricos. Dessa vez, os arrays são explicitamente configurados como séries temporais para atender aos requisitos de CRangePattern. Quando a classificação identifica um padrão ativo, o EA gera uma mensagem de texto clara, contendo o símbolo, o timeframe e a categoria identificada. Alertas em janelas pop-up, sinais sonoros e notificações push são enviados conforme as configurações do usuário, mas somente quando permitidos pelo ambiente de execução atual.
datetime lastDone = 0; void OnTick() { datetime tClosed = iTime(_Symbol,_Period,1); if(tClosed == lastDone) return; // already processed lastDone = tClosed; const int need = pat.atrPeriod + 3; double H[],L[],O[],C[]; ArrayResize(H,need); ArraySetAsSeries(H,true); ArrayResize(L,need); ArraySetAsSeries(L,true); ArrayResize(O,need); ArraySetAsSeries(O,true); ArrayResize(C,need); ArraySetAsSeries(C,true); CopyHigh (_Symbol,_Period,0,need,H); CopyLow (_Symbol,_Period,0,need,L); CopyOpen (_Symbol,_Period,0,need,O); CopyClose(_Symbol,_Period,0,need,C); if(!pat.Calculate(1,H,L,O,C,need)) return; string sig; if(pat.isLarge) sig="Large-Range bar"; else if(pat.isSmall) sig="Small-Range bar"; else if(pat.isInside) sig="Inside bar"; else if(pat.isOutside) sig="Outside bar"; if(sig=="") return; string msg = _Symbol+" "+EnumToString(_Period)+" "+sig; Print("[CRT-EA] ",msg); if(!NonVisualTest) Alert(msg); if(Push_Alerts) SendNotification(msg); }
O EA também dispõe de mensagens opcionais de depuração, distribuídas pelo código, que registram resumidamente eventos como o carregamento bem-sucedido do indicador ou a insuficiência de dados históricos. Como a emissão dessas mensagens é controlada pelo sinalizador DebugLog, a versão em produção pode operar sem registros desnecessários, enquanto a geração de informações completas de diagnóstico pode ser ativada durante o desenvolvimento ou a pesquisa.
input bool DebugLog = true; if(DebugLog) PrintFormat("[CRT-EA] Attached on %s %s (tester=%d)", _Symbol,EnumToString(_Period), (int)MQLInfoInteger(MQL_TESTER));
O conjunto de ferramentas não utiliza estado mutável estático ou global, exceto nos objetos explicitamente necessários ao seu funcionamento. Todos os objetos gráficos criados dinamicamente são removidos automaticamente pelo MetaTrader quando o indicador ao qual pertencem é removido, ou excluídos explicitamente pelo código. Não há arrays persistentes que aumentem de tamanho com o passar do tempo. A cada tick, é acionada a rotina de cópia e classificação de um volume fixo de dados, cuja complexidade temporal independe da quantidade de barras presentes no gráfico. Por isso, o sistema pode ser utilizado sem modificações em diferentes escalas temporais, desde gráficos semanais até barras com duração de segundos, sem risco de degradação progressiva do desempenho.
// inside any function needing history const int need = pat.atrPeriod + 3; double H[need], L[need], O[need], C[need]; // stack allocation in C++17 style // (or ArrayResize + quick release when the function exits)
Testes e resultados
Nesta seção, examinaremos os resultados dos testes em tempo real.
A animação GIF abaixo mostra o CRT_EA em execução em um gráfico de cinco minutos do Step Index, atualizado em tempo real. À medida que cada barra se fecha, retângulos coloridos, marcadores e setas aparecem no gráfico, indicando se a volatilidade está se comprimindo ou se expandindo e se a vela atual engloba completamente o intervalo de preços da barra anterior. Velas Inside Bar, caracterizadas por baixa volatilidade e amplitude estreita, formam agrupamentos até que surge uma vela de amplitude elevada, sinalizando um aumento repentino do momentum. A cada fechamento, a nova vela é imediatamente comparada ao ATR atual e classificada, criando uma representação visual contínua, codificada por cores, da intensidade dos movimentos de preço, sem repainting das barras anteriores. Essa visualização em tempo real facilita identificar quando o mercado entra em compressão, quando sai desse estado e como cada barra se encaixa em um ciclo mais amplo de volatilidade.

| Categoria | Cor do retângulo | Seta/marcador | Significado |
|---|---|---|---|
| Barra Large-Range (LR) | Contorno azul | Verde para sinais de alta e vermelho para sinais de baixa. | Amplitude excepcionalmente grande: amplitude ≥ largeMult × ATR |
| Barra Small-Range (SR) | Contorno amarelo | Pequeno ponto amarelo | Amplitude comprimida: amplitude ≤ smallMult × ATR |
| Barra Inside Bar (IB) | Contorno turquesa | Ponto turquesa | Máxima< máxima anterior e mínima > mínima anterior |
| Barra Outside Bar (OB) | Contorno púrpura | Ponto púrpura | Máxima > máxima anterior e mínima< mínima anterior |
- Gráfico do Step Index
- Gráfico do Crash 1000 Index
- Gráfico do Boom 1000 Index
Conclusão
O conjunto de ferramentas Candle-Range Theory oferece uma solução modular completa para a análise da amplitude das velas no MetaTrader 5.
- CRangePattern: classe compacta e independente que identifica barras Large-Range, Small-Range, Inside Bar e Outside Bar sem repainting.
- CRT_Indicator: apresenta os sinais no gráfico por meio de contornos coloridos e setas, permitindo identificá-los rapidamente.
- CRT_EA: transforma os mesmos sinais em alertas ou ordens enviadas automaticamente.
Todos os parâmetros, incluindo o período do ATR, os multiplicadores inferior e superior de amplitude e as regras de alerta, são totalmente configuráveis, permitindo adaptar o sistema a qualquer símbolo, timeframe ou regime de volatilidade. Como a lógica de identificação dos padrões é independente dos componentes de visualização e execução, ela pode ser ampliada ou integrada a scanners, painéis de controle e sistemas completos de negociação com alterações mínimas no código.
O conjunto de ferramentas foi desenvolvido para fins educacionais e deve ser testado em uma conta de demonstração antes de qualquer utilização em uma conta real. Combine os sinais objetivos baseados na amplitude das velas com suas próprias regras de seleção de operações e gestão de risco, de modo que essa abordagem esteja alinhada à sua estratégia geral.
Quando utilizado dessa forma, o sistema Candle-Range Theory permite identificar, visualizar e reagir aos eventos de volatilidade com rapidez, clareza e confiança.
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/18911
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.
Caminhe em novos trilhos: Personalize indicadores no MQL5
Ferramentas de trading em MQL5 (Parte 6): Painel holográfico dinâmico com animação pulsante e controles
Está chegando o novo MetaTrader 5 e MQL5
Introdução ao MQL5 (Parte 19): Automação da detecção de ondas de Wolfe
- 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