Introdução ao MQL5 (Parte 19): Automação da detecção de ondas de Wolfe
Introdução
Sejam bem-vindos novamente à Parte 19 da série "Introdução à linguagem MQL5"! Na Parte 18, apresentei o padrão de ondas de Wolfe, uma estrutura única de cinco ondas utilizada para prever reversões de preço com precisão. Discutimos os dois principais tipos de ondas de Wolfe: o setup de baixa, que sinaliza uma possível queda do preço, e o setup de alta, que indica uma possível valorização. Você também aprendeu a obter dados de candles, essenciais para analisar a ação do preço, e conheceu a lógica necessária para identificar oportunidades válidas de negociação com base nesse padrão.
Nesta parte, passaremos da teoria à implementação. Veremos como detectar essas estruturas e executar operações a partir dos sinais identificados. Isso inclui localizar os principais pontos de swing, validar as regras do padrão e preparar o EA para operar de acordo com os sinais encontrados.
Neste artigo, você aprenderá:
- Como detectar a estrutura clássica de cinco ondas de Wolfe usando dados históricos de preços.
- Como identificar programaticamente os topos e fundos de swing para determinar os pontos das ondas.
- Como aplicar e ajustar os níveis de extensão de Fibonacci para validar as formações das ondas, especialmente as ondas 3 e 5.
- Como traçar três linhas de tendência importantes (1-3, 2-4 e 1-4), fundamentais para confirmar o padrão e tomar decisões de negociação.
- Como verificar a simetria e as relações de proporcionalidade entre os movimentos das ondas 1-2 e 3-4, aumentando a confiabilidade do padrão.
- Como identificar as ondas e desenhar objetos gráficos, como textos, retângulos e linhas de tendência, diretamente no gráfico usando MQL5.
- Como implementar uma lógica que aguarde a confirmação do sinal antes de abrir operações, evitando entradas falsas.
- Como programar o fechamento automático das operações quando o preço atingir a linha de tendência que conecta os pontos 1 e 4, contribuindo para a gestão de riscos.
Identificação de padrões de ondas de Wolfe de baixa
No artigo anterior, já discutimos detalhadamente a estrutura e as regras do padrão de ondas de Wolfe de baixa. Agora, vamos nos concentrar na implementação dessa lógica em código. Como vimos, o padrão de Wolfe de baixa é composto por cinco ondas que precisam seguir uma sequência específica e atender a determinados critérios estruturais. A onda 1 deve corresponder a um topo de swing, enquanto a onda 2 deve representar um fundo de swing abaixo da onda 1. Em seguida, a onda 3 é formada por um novo topo de swing, superior à onda 1 e situado dentro de uma faixa de extensão de Fibonacci definida a partir do movimento entre as ondas 1 e 2. Depois, identificamos a onda 4, um fundo de swing abaixo da onda 3, mas ainda acima da onda 2. Por fim, a onda 5 completa o padrão, formando um topo de swing acima da onda 3 e dentro de uma faixa de extensão de Fibonacci previamente definida, calculada a partir do movimento entre os pontos 3 e 4.
É importante lembrar que o movimento entre as ondas 1 e 2 deve ter amplitude comparável à do movimento entre as ondas 3 e 4. A amplitude do segmento 3-4 deve corresponder a pelo menos 70% da amplitude do segmento 1-2. Essa simetria torna a estrutura mais confiável e serve como um critério adicional para confirmar a validade do padrão. Nesta seção, identificaremos os cinco pontos do padrão usando funções de detecção de topos e fundos de swing e implementaremos verificações para garantir que as distâncias e as relações entre elas atendam aos requisitos do padrão de Wolfe.
Identificação das ondas 1 e 2
Identificar corretamente as ondas 1 e 2 é o primeiro passo para detectar um padrão de ondas de Wolfe de baixa. Sem essa base inicial, será difícil identificar as demais ondas com precisão. Nesta etapa, vamos nos concentrar na identificação de topos e fundos de swing válidos no gráfico, que atendam aos critérios das ondas 1 e 2. Depois de identificar essas duas ondas, vamos marcá-las claramente no gráfico para facilitar a visualização.
Também criaremos um objeto de extensão de Fibonacci com base nas ondas 1 e 2. Ao definir os níveis de preço correspondentes às regras do padrão, essa extensão servirá de referência para identificar as ondas 3 e 5. Com isso, estabelecemos desde o início uma base sólida para identificar as ondas restantes.
Exemplo:input ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT; int bars_check = 500; datetime time_bar; double total_symbol_bars; double open[]; double close[]; double low[]; double high[]; datetime time[]; double wv1; datetime wv1_time; string wv1_txt; double wv2; datetime wv2_time; string wv2_txt; string fib_ext_wv1_wv2; ulong chart_id = ChartID(); //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { ObjectsDeleteAll(chart_id); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { total_symbol_bars = Bars(_Symbol, timeframe); time_bar = iTime(_Symbol,timeframe,0); CopyOpen(_Symbol, timeframe, time_bar, bars_check, open); CopyClose(_Symbol, timeframe, time_bar, bars_check, close); CopyLow(_Symbol, timeframe, time_bar, bars_check, low); CopyHigh(_Symbol, timeframe, time_bar, bars_check, high); CopyTime(_Symbol, timeframe, time_bar, bars_check, time); if(total_symbol_bars >= bars_check) { for(int i = 7; i < bars_check - 7; i++) { if(IsSwingHigh(high, i, 7)) { wv1 = high[i]; wv1_time = time[i]; wv1_txt = StringFormat("WAVE 1 %d", i); for(int j = i; j < bars_check - 7; j++) { if(IsSwingLow(low, j, 7) && low[j] < wv1) { wv2 = low[j]; wv2_time = time[j]; wv2_txt = StringFormat("WAVE 2 %d", j); ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_time, wv1); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_time, wv2); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_time, wv2, wv1_time, wv1, wv2_time, wv2); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } break; } } } } } } //+------------------------------------------------------------------+ //| FUNCTION FOR SWING LOW | //+------------------------------------------------------------------+ bool IsSwingLow(const double &low_price[], int index, int lookback) { for(int i = 1; i <= lookback; i++) { if(low_price[index] > low_price[index - i] || low_price[index] > low_price[index + i]) return false; } return true; } //+------------------------------------------------------------------+ //| FUNCTION FOR SWING HIGH | //+------------------------------------------------------------------+ bool IsSwingHigh(const double &high_price[], int index, int lookback) { for(int i = 1; i <= lookback; i++) { if(high_price[index] < high_price[index - i] || high_price[index] < high_price[index + i]) return false; } return true; }
Saída:

Explicação:
Para armazenar as informações essenciais sobre as duas primeiras ondas e permitir a identificação e a representação gráfica de estruturas como o padrão de ondas de Wolfe de baixa, declaramos algumas variáveis. Para a onda 1, são utilizadas três variáveis: wv1, que armazena o nível de preço; wv1_time, que registra o momento exato em que esse preço foi atingido; e wv1_txt, que funciona como um rótulo de texto para identificar visualmente a onda no gráfico. As variáveis wv2, wv2_time e wv2_txt desempenham as mesmas funções para a onda 2.
Esses dados são essenciais porque permitem ao EA registrar os preços e as marcas de tempo exatas dos topos e fundos de swing relevantes, além de consultá-los posteriormente. Os rótulos de texto também facilitam a identificação das ondas destacadas no gráfico, tornando a visualização mais clara para o trader.
Além das variáveis que armazenam os dados das ondas, declaramos uma variável do tipo string chamada fib_ext_wv1_wv2, destinada a armazenar o nome do objeto de extensão de Fibonacci. Essa variável permite criar, modificar ou excluir corretamente o objeto que representa a extensão entre as ondas 1 e 2, conforme necessário, já que cada objeto do gráfico precisa ter um identificador único. Para distinguir cada instância, normalmente incluímos o índice da onda no nome do objeto, especialmente quando o EA gera vários padrões ao percorrer as barras históricas.
O código também utiliza a função ChartID() para obter o identificador único do gráfico atual, armazenando-o na variável chart_id para uso nas operações de criação de objetos. Isso é importante porque o MetaTrader 5 permite manter vários gráficos abertos simultaneamente. Para evitar conflitos ou posicionamentos incorretos, o programa utiliza explicitamente o identificador do gráfico correspondente ao criar ou modificar objetos gráficos.
A instrução ObjectsDeleteAll(chart_id);, presente na função OnDeinit(), executa a limpeza dos objetos gráficos. Ela remove todos os objetos anteriormente desenhados pelo EA quando ele é removido ou o gráfico é fechado. Isso evita o acúmulo de elementos visuais e impede que objetos desatualizados, como rótulos das ondas ou linhas de Fibonacci, permaneçam no gráfico após o encerramento do EA.
Antes de iniciar a lógica de detecção de padrões, o EA realiza uma verificação essencial para garantir que haja barras suficientes disponíveis. Para isso, compara a quantidade de barras que pretende analisar (bars_check) com o número total de barras do gráfico (total_symbol_bars). Após confirmar que há barras históricas suficientes carregadas no gráfico (if(total_symbol_bars >= bars_check)), o programa começa a percorrer os preços em busca dos primeiros indícios de um padrão de ondas de Wolfe de baixa.
A detecção começa com um laço for:
for(int i = 7; i < bars_check - 7; i++)
Para identificar os topos e fundos de swing com segurança, o laço começa no índice 7, e não no índice 0. As funções de detecção de swing, que serão apresentadas mais adiante, analisam sete barras anteriores e sete posteriores para determinar se determinado preço corresponde a um ponto de swing. Se o laço começasse no índice 0, ocorreria um erro de acesso fora dos limites do array, pois não haveria barras anteriores disponíveis para comparação. Da mesma forma, encerrar o laço em bars_check-7 garante que existam barras posteriores suficientes para realizar as comparações.
Esse laço externo procura um candidato à onda 1 do padrão de Wolfe, correspondente a um topo de swing. O código verifica se a máxima da barra no índice i corresponde a um máximo local, ou seja, se é superior às máximas dos candles ao redor. Cada índice i representa um candle do histórico.
if(IsSwingHigh(high, i, 7))
Se a função retornar true, confirmando que a barra corresponde a um topo de swing válido, o EA passa a considerá-la uma possível onda 1. Nesse momento, é criada uma string para o rótulo (wv1_txt), que será utilizado posteriormente no gráfico, enquanto o preço máximo e o horário correspondente são armazenados nas variáveis wv1 e wv1_time.
Depois de identificar uma onda 1 válida (topo de swing), o código inicia um laço interno para procurar, em um momento posterior à onda 1, um fundo de swing válido que represente a onda 2:
for(int j = i; j < bars_check - 7; j++)
Esse laço começa no mesmo índice do laço externo (i) e prossegue até encontrar uma barra que atenda a duas condições:
- A barra deve corresponder a um fundo de swing (mínimo local).
- Seu preço deve ser inferior ao preço da onda 1.
if(IsSwingLow(low, j, 7) && low[j] < wv1)
Quando os dois critérios da onda 2 são atendidos, o EA armazena o preço, o horário e o rótulo nas variáveis wv2, wv2_time e wv2_txt, respectivamente. Depois de identificar as ondas 1 e 2, a instrução break encerra o laço interno. Em seguida, é criado um objeto de extensão de Fibonacci entre as duas ondas, e são adicionados rótulos de texto aos respectivos pontos no gráfico. Nesse momento, o EA encerra a busca por outros pares para a onda 1 atual, deixando de procurar novos candidatos à onda 2.
Identificação das ondas 3 e 4
Para construir o padrão de ondas de Wolfe, o próximo passo é identificar as ondas 3 e 4, depois de confirmar que as ondas 1 e 2 atendem aos critérios estabelecidos. A disposição e a relação proporcional entre as ondas 1 e 2 influenciam significativamente a configuração das ondas seguintes. A onda 3, em particular, deve atender a dois requisitos principais: ultrapassar a máxima da onda 1 e terminar dentro de uma faixa de extensão de Fibonacci previamente definida, calculada com base nas ondas 1 e 2.
Para determinar essa faixa, traçamos uma extensão de Fibonacci a partir do movimento de preço entre as ondas 1 e 2. Essa ferramenta ajuda a projetar possíveis níveis futuros de preço com base na amplitude e no momentum da estrutura inicial. A faixa de extensão entre 127,2% e 161,8% representa a região em que se espera que o preço chegue antes de uma reversão, sendo normalmente considerada uma área válida para a onda 3. Se o preço formar um topo de swing dentro dessa faixa, teremos um bom candidato à onda 3.
Além de atender aos critérios de preço, a onda 3 deve respeitar a simetria do padrão. A estrutura e a amplitude do movimento entre as ondas 1 e 2 devem encontrar uma correspondência proporcional no movimento entre as ondas 3 e 4. É esse equilíbrio geométrico que caracteriza os padrões válidos de ondas de Wolfe. Para este estudo, vamos adotar um critério simples e mensurável de simetria. Especificamente, a amplitude total do movimento entre as ondas 1 e 2 deve corresponder a pelo menos 70% da amplitude do movimento entre as ondas 3 e 4. À medida que avançamos no desenvolvimento do EA, essa relação percentual oferece uma base consistente para validar os padrões e preservar a coerência estrutural e visual das ondas de Wolfe.
Cálculo de 70% da distância entre as ondas 1 e 2
Primeiro, vamos determinar 70% da distância entre as ondas 1 e 2.
Exemplo:
double wv1_wv2_size; double wv1_wv2_70p;
if(total_symbol_bars >= bars_check) { for(int i = 7; i < bars_check - 7; i++) { if(IsSwingHigh(high, i, 7)) { wv1 = high[i]; wv1_time = time[i]; wv1_txt = StringFormat("WAVE 1 %d", i); for(int j = i; j < bars_check - 7; j++) { if(IsSwingLow(low, j, 7) && low[j] < wv1) { wv2 = low[j]; wv2_time = time[j]; wv2_txt = StringFormat("WAVE 2 %d", j); ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_time, wv1); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_time, wv2); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_time, wv2, wv1_time, wv1, wv2_time, wv2); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } wv1_wv2_size = MathAbs(wv1 - wv2); wv1_wv2_70p = (wv1_wv2_size / 100) * 70; string luh = StringFormat("bb 2 %d", j); ObjectCreate(chart_id, luh, OBJ_TREND, 0, wv1_time, wv1 - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); break; } } } } }
Saída:

Explicação:
Além de atender aos critérios de preço, a onda 3 deve respeitar a simetria do padrão. A estrutura e a amplitude do movimento entre as ondas 1 e 2 devem encontrar uma correspondência proporcional no movimento entre as ondas 3 e 4. É esse equilíbrio geométrico que caracteriza os padrões válidos de ondas de Wolfe. Para este estudo, vamos adotar um critério simples e mensurável de simetria. Especificamente, a amplitude total do movimento entre as ondas 1 e 2 deve corresponder a pelo menos 70% da amplitude do movimento entre as ondas 3 e 4. À medida que avançamos no desenvolvimento do EA, essa relação percentual oferece uma base consistente para validar os padrões e preservar a coerência estrutural e visual das ondas de Wolfe.
Para facilitar a visualização desse critério, traçamos uma linha de tendência horizontal no gráfico, desde o horário da onda 1 até o horário da onda 2, no nível de preço situado 70% da distância entre as duas ondas abaixo da máxima da onda 1. Essa linha serve como referência para verificar se as ondas seguintes atendem ao requisito de amplitude mínima.
Independentemente da ordem das ondas 1 e 2, utilizamos a função MathAbs para garantir que a amplitude calculada seja sempre positiva. Embora essa função não seja tecnicamente necessária neste caso, já que no padrão de baixa a onda 1 deve estar acima da onda 2, seu uso funciona como uma medida preventiva. Isso ajuda a evitar possíveis erros caso as amplitudes das ondas sejam subestimadas ou suas posições sejam invertidas.
Extensão de Fibonacci para as ondas 1 e 2
Utilizando a função IsSwingHigh, o algoritmo identifica a onda 3 como um topo de swing posterior à onda 2, situado entre os níveis de 127,2% e 161,8% da extensão de Fibonacci calculada a partir das ondas 1 e 2. Se atender a esses critérios, a onda 3 será registrada. Para garantir que estamos trabalhando com um padrão válido, desenhamos no gráfico apenas os objetos de Fibonacci, a linha de 70% e os rótulos das ondas. Em seguida, o algoritmo procura a onda 4, que deve corresponder a um fundo de swing formado após a terceira onda.
Exemplo:
input ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT; input double max_fib_ext_wv12 = 161.8; input double min_fib_ext_wv12 = 127.2; int bars_check = 500; datetime time_bar; double total_symbol_bars; double open[]; double close[]; double low[]; double high[]; datetime time[]; double wv1; datetime wv1_time; string wv1_txt; double wv2; datetime wv2_time; string wv2_txt; string fib_ext_wv1_wv2; ulong chart_id = ChartID(); double wv1_wv2_size; double wv1_wv2_70p; string perc_70; double fib_ext_1_2_161_8; double fib_ext_1_2_127_2; string fib_ext_range; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { ObjectsDeleteAll(chart_id); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { total_symbol_bars = Bars(_Symbol, timeframe); time_bar = iTime(_Symbol, timeframe, 0); CopyOpen(_Symbol, timeframe, time_bar, bars_check, open); CopyClose(_Symbol, timeframe, time_bar, bars_check, close); CopyLow(_Symbol, timeframe, time_bar, bars_check, low); CopyHigh(_Symbol, timeframe, time_bar, bars_check, high); CopyTime(_Symbol, timeframe, time_bar, bars_check, time); if(total_symbol_bars >= bars_check) { for(int i = 7; i < bars_check - 7; i++) { if(IsSwingHigh(high, i, 7)) { wv1 = high[i]; wv1_time = time[i]; wv1_txt = StringFormat("WAVE 1 %d", i); for(int j = i; j < bars_check - 7; j++) { if(IsSwingLow(low, j, 7) && low[j] < wv1) { wv2 = low[j]; wv2_time = time[j]; wv2_txt = StringFormat("WAVE 2 %d", j); ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_time, wv1); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_time, wv2); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_time, wv2, wv1_time, wv1, wv2_time, wv2); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } wv1_wv2_size = MathAbs(wv1 - wv2); wv1_wv2_70p = (wv1_wv2_size / 100) * 70; perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_time, wv1 - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_1_2_127_2 = MathAbs((((wv1 - wv2) / 100) * (min_fib_ext_wv12 - 100)) + wv1); fib_ext_1_2_161_8 = MathAbs((((wv1 - wv2) / 100) * (max_fib_ext_wv12 - 100)) + wv1); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_time, fib_ext_1_2_161_8, wv2_time, fib_ext_1_2_127_2); break; } } } } } } //+------------------------------------------------------------------+ //| FUNCTION FOR SWING LOW | //+------------------------------------------------------------------+ bool IsSwingLow(const double &low_price[], int index, int lookback) { for(int i = 1; i <= lookback; i++) { if(low_price[index] > low_price[index - i] || low_price[index] > low_price[index + i]) return false; } return true; } //+------------------------------------------------------------------+ //| FUNCTION FOR SWING HIGH | //+------------------------------------------------------------------+ bool IsSwingHigh(const double &high_price[], int index, int lookback) { for(int i = 1; i <= lookback; i++) { if(high_price[index] < high_price[index - i] || high_price[index] < high_price[index + i]) return false; } return true; }
Saída:

Identificação da onda 3
O código avança a partir da onda 2 em busca de um topo de swing situado entre os níveis de 127,2% e 161,8% da extensão de Fibonacci das ondas 1 e 2. Essa condição permite identificar a onda 3 do padrão de Wolfe de baixa. Se um topo de swing válido for encontrado nessa faixa, ele será identificado como a onda 3.
Exemplo:double wv3; datetime wv3_time; string wv3_txt;
if(total_symbol_bars >= bars_check) { for(int i = 7; i < bars_check - 7; i++) { if(IsSwingHigh(high, i, 7)) { wv1 = high[i]; wv1_time = time[i]; wv1_txt = StringFormat("WAVE 1 %d", i); for(int j = i; j < bars_check - 7; j++) { if(IsSwingLow(low, j, 7) && low[j] < wv1) { wv2 = low[j]; wv2_time = time[j]; wv2_txt = StringFormat("WAVE 2 %d", j); wv1_wv2_size = MathAbs(wv1 - wv2); wv1_wv2_70p = (wv1_wv2_size / 100) * 70; fib_ext_1_2_127_2 = MathAbs((((wv1 - wv2) / 100) * (min_fib_ext_wv12 - 100)) + wv1); fib_ext_1_2_161_8 = MathAbs((((wv1 - wv2) / 100) * (max_fib_ext_wv12 - 100)) + wv1); for(int k = j; k < bars_check - 7; k++) { if(IsSwingHigh(high, k, 7) && time[k] > wv2_time) { wv3 = high[k]; wv3_time = time[k]; wv3_txt = StringFormat("WAVE 3 %d", k); if(wv3 >= fib_ext_1_2_127_2 && wv3 <= fib_ext_1_2_161_8) { ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_time, wv1); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_time, wv2); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_time, wv2, wv1_time, wv1, wv2_time, wv2); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_time, wv1 - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_time, fib_ext_1_2_161_8, wv2_time, fib_ext_1_2_127_2); ObjectCreate(chart_id, wv3_txt, OBJ_TEXT, 0, wv3_time, wv3); ObjectSetString(chart_id, wv3_txt, OBJPROP_TEXT, "WV3"); ObjectSetInteger(chart_id, wv3_txt, OBJPROP_COLOR, clrBlue); } break; } } break; } } } } }
Saída:

Explicação:
O código utiliza três variáveis para identificar a onda 3: wv3, que armazena o nível de preço; wv3_time, que registra o horário; e wv3_txt, que armazena o rótulo. A função IsSwingHigh permite localizar topos de swing válidos após a onda 2. Assim, podemos identificar a onda 3 percorrendo os candles posteriores ao extremo da onda 2. Anteriormente, todos os objetos gráficos eram desenhados assim que wv2 era identificada. Agora, esses objetos só serão exibidos quando wv3 estiver dentro da faixa de extensão de Fibonacci definida a partir de wv1 e wv2.
Identificação da onda 4
O próximo passo é localizar a onda 4, representada por um fundo de swing formado após a onda 3. Para confirmar que o padrão continua válido, precisamos verificar se o movimento de preço entre as ondas 3 e 4 mantém uma simetria adequada em relação ao movimento entre as ondas 1 e 2. Neste projeto, adotamos um critério simples de simetria: a amplitude do movimento entre as ondas 3 e 4 deve corresponder a pelo menos 70% da amplitude do movimento entre as ondas 1 e 2. Esse requisito ajuda a preservar o equilíbrio estrutural do padrão de Wolfe, descartando retrações muito pequenas ou desproporcionais. Na próxima etapa, vamos aplicar esse critério ao código, procurando um fundo de swing válido após a onda 3 e verificando se o movimento atende ao requisito de amplitude mínima.
Exemplo:double wv4; datetime wv4_time; string wv4_txt; double wv3_wv4_size;
if(total_symbol_bars >= bars_check) { for(int i = 7; i < bars_check - 7; i++) { if(IsSwingHigh(high, i, 7)) { wv1 = high[i]; wv1_time = time[i]; wv1_txt = StringFormat("WAVE 1 %d", i); for(int j = i; j < bars_check - 7; j++) { if(IsSwingLow(low, j, 7) && low[j] < wv1) { wv2 = low[j]; wv2_time = time[j]; wv2_txt = StringFormat("WAVE 2 %d", j); wv1_wv2_size = MathAbs(wv1 - wv2); wv1_wv2_70p = (wv1_wv2_size / 100) * 70; fib_ext_1_2_127_2 = MathAbs((((wv1 - wv2) / 100) * (min_fib_ext_wv12 - 100)) + wv1); fib_ext_1_2_161_8 = MathAbs((((wv1 - wv2) / 100) * (max_fib_ext_wv12 - 100)) + wv1); for(int k = j; k < bars_check - 7; k++) { if(IsSwingHigh(high, k, 7) && time[k] > wv2_time) { wv3 = high[k]; wv3_time = time[k]; wv3_txt = StringFormat("WAVE 3 %d", k); if(wv3 >= fib_ext_1_2_127_2 && wv3 <= fib_ext_1_2_161_8) { for(int l = k; l < bars_check - 7; l++) { if(IsSwingLow(low, l, 7) && time[l] > wv3_time) { wv4 = low[l]; wv4_time = time[l]; wv4_txt = StringFormat("WAVE 4 %d", l); wv3_wv4_size = MathAbs(wv3 - wv4); if(wv3_wv4_size >= wv1_wv2_size && wv4 > wv2 && wv4 < wv3) { ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_time, wv1); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_time, wv2); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_time, wv2, wv1_time, wv1, wv2_time, wv2); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_time, wv1 - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_time, fib_ext_1_2_161_8, wv2_time, fib_ext_1_2_127_2); ObjectCreate(chart_id, wv3_txt, OBJ_TEXT, 0, wv3_time, wv3); ObjectSetString(chart_id, wv3_txt, OBJPROP_TEXT, "WV3"); ObjectSetInteger(chart_id, wv3_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv4_txt, OBJ_TEXT, 0, wv4_time, wv4); ObjectSetString(chart_id, wv4_txt, OBJPROP_TEXT, "WV4"); ObjectSetInteger(chart_id, wv4_txt, OBJPROP_COLOR, clrBlue); } break; } } } break; } } break; } } } } }
Saída:

Explicação:
Depois de identificar wv3, o próximo passo é localizar wv4. O programa calcula a distância entre wv3 e wv4 e armazena o resultado em wv3_wv4_size. Ao encontrar um fundo de swing, registra o horário da barra e o preço nas variáveis wv4_time e wv4. Para manter a estrutura correta do padrão, o programa verifica se o movimento entre wv3 e wv4 apresenta proporções compatíveis com o movimento entre wv1 e wv2, além de garantir que a onda 4 permaneça acima da onda 2 e abaixo da onda 3. Também verifica se wv3 está dentro da faixa de extensão de Fibonacci estabelecida. Após todas as verificações, a onda 4 é marcada no gráfico, completando o setup do padrão com base na detecção de swings, nos filtros de Fibonacci e nos critérios de simetria.


Como podemos observar na primeira imagem (Figura 11), a onda 3 não representa a maior máxima registrada no movimento entre as ondas 3 e 4. A onda 3 deveria corresponder ao topo mais alto antes da queda até a onda 4, mas isso não acontece neste exemplo. Nosso mecanismo de detecção não conseguiu identificar corretamente a estrutura porque, após o ponto marcado como onda 3, o preço formou uma máxima ainda mais alta. A segunda imagem (Figura 12) também mostra que a onda 1 não corresponde à maior máxima no trecho entre as ondas 1 e 2.
Isso também viola as regras do padrão, pois a onda 1 deve representar o topo de swing dominante nesse trecho. Se o algoritmo continuar selecionando pontos estruturalmente incorretos para as ondas, não conseguiremos obter resultados confiáveis na identificação dos padrões de Wolfe. Portanto, precisamos corrigir esse problema para tornar a lógica de detecção mais robusta.
Para resolver os problemas demonstrados nos exemplos anteriores, vamos adicionar uma etapa de validação para cada onda. A onda 3 deve corresponder à maior máxima registrada entre os pontos das ondas 3 e 4, garantindo que represente corretamente o topo anterior à queda. A onda 2 deve corresponder à menor mínima entre as ondas 2 e 3, identificando corretamente o fundo anterior à próxima tendência de alta. Da mesma forma, a onda 1 deve representar a maior máxima entre as ondas 1 e 2, confirmando que se trata de um topo de swing significativo nesse trecho do padrão.
Exemplo:
int wv3_wv4_bars; int wv3_highest_index; double wv3_hh; datetime wv3_hh_t; int wv2_wv3_bars; int wv2_lowest_index; double wv2_ll; datetime wv2_ll_t; int wv1_wv2_bars; int wv1_highest_index; double wv1_hh; datetime wv1_hh_t;
for(int l = k; l < bars_check - 7; l++) { if(IsSwingLow(low, l, 7) && time[l] > wv3_time) { wv4 = low[l]; wv4_time = time[l]; wv4_txt = StringFormat("WAVE 4 %d", l); wv3_wv4_bars = Bars(_Symbol, timeframe, wv3_time, wv4_time); wv3_highest_index = ArrayMaximum(high, k, wv3_wv4_bars); wv3_hh = high[wv3_highest_index]; wv3_hh_t = time[wv3_highest_index]; wv2_wv3_bars = Bars(_Symbol, timeframe, wv2_time, wv3_time); wv2_lowest_index = ArrayMinimum(low, j, wv2_wv3_bars); wv2_ll = low[wv2_lowest_index]; wv2_ll_t = time[wv2_lowest_index]; wv1_wv2_bars = Bars(_Symbol, timeframe, wv1_time, wv2_time); wv1_highest_index = ArrayMaximum(high, i, wv1_wv2_bars); wv1_hh = high[wv1_highest_index]; wv1_hh_t = time[wv1_highest_index]; wv1_wv2_size = MathAbs(wv1_hh - wv2_ll); wv1_wv2_70p = (wv1_wv2_size / 100) * 70; fib_ext_1_2_127_2 = MathAbs((((wv1_hh - wv2_ll) / 100) * (min_fib_ext_wv12 - 100)) + wv1_hh); fib_ext_1_2_161_8 = MathAbs((((wv1_hh - wv2_ll) / 100) * (max_fib_ext_wv12 - 100)) + wv1_hh); wv3_wv4_size = MathAbs(wv3_hh - wv4); if(wv3_wv4_size >= wv1_wv2_size && wv4 > wv2_ll && wv4 < wv3_hh && wv3_hh >= fib_ext_1_2_127_2 && wv3_hh <= fib_ext_1_2_161_8) { ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_hh_t, wv1_hh); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_ll_t, wv2_ll); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_ll_t, wv2_ll, wv1_hh_t, wv1_hh, wv2_ll_t, wv2_ll); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_hh_t, wv1_hh - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_hh_t, fib_ext_1_2_161_8, wv2_ll_t, fib_ext_1_2_127_2); ObjectCreate(chart_id, wv3_txt, OBJ_TEXT, 0, wv3_hh_t, wv3_hh); ObjectSetString(chart_id, wv3_txt, OBJPROP_TEXT, "WV3"); ObjectSetInteger(chart_id, wv3_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv4_txt, OBJ_TEXT, 0, wv4_time, wv4); ObjectSetString(chart_id, wv4_txt, OBJPROP_TEXT, "WV4"); ObjectSetInteger(chart_id, wv4_txt, OBJPROP_COLOR, clrBlue); } break; } }
Saída:

Explicação:
Vamos introduzir novos cálculos para validar a estrutura das ondas de Wolfe e garantir que cada ponto corresponda à máxima ou mínima mais relevante do respectivo trecho. Para identificar os extremos de preço (a maior máxima ou a menor mínima) em cada segmento, começamos declarando algumas variáveis. A variável wv3_wv4_bars armazena a quantidade de barras entre as ondas 3 e 4. Em seguida, utilizamos a função ArrayMaximum para localizar a maior máxima nesse intervalo, analisando wv3_wv4_bars barras a partir do índice k, onde está localizada a onda 3. O resultado é armazenado na variável wv3_highest_index. Com esse índice, obtemos o maior preço registrado nesse intervalo (wv3_hh) e sua marca de tempo (wv3_hh_t).
A variável wv2_wv3_bars armazena a quantidade de barras entre as ondas 2 e 3, seguindo a mesma lógica. Nesse caso, utilizamos a função ArrayMinimum, que retorna o índice do menor preço, para localizar a menor mínima. Depois de armazenar esse índice na variável wv2_lowest_index, obtemos o preço mínimo correspondente (wv2_ll) e sua marca de tempo (wv2_ll_t). A variável wv1_wv2_bars determina a quantidade de barras entre as ondas 1 e 2. Como a onda 1 deve representar o topo dominante nesse trecho, utilizamos novamente a função ArrayMaximum para encontrar a maior máxima do intervalo. A partir do índice obtido, armazenado em wv1_highest_index, extraímos o preço máximo (wv1_hh) e sua marca de tempo correspondente (wv1_hh_t).
A variável wv3_wv4_bars armazena a quantidade de barras entre as ondas 3 e 4. Para localizar a maior máxima nesse intervalo, utilizamos a função ArrayMaximum, analisando wv3_wv4_bars barras a partir do índice k, que corresponde à posição da onda 3. O resultado é armazenado na variável wv3_highest_index. Esse índice permite obter a marca de tempo (wv3_hh_t) e o maior preço registrado no intervalo (wv3_hh). Ao incorporar essas restrições ao código, aumentamos a precisão da detecção das ondas de Wolfe e reduzimos a possibilidade de identificar padrões fracos ou estruturalmente incorretos. Essa validação adicional garante que o padrão atenda aos requisitos técnicos e seja adequado para analisar operações em condições reais de mercado.
A partir de agora, utilizaremos as máximas e mínimas validadas para desenhar os objetos no gráfico, em vez dos pontos das ondas selecionados inicialmente. Para a onda 1, especificamente, substituiremos os valores wv1_hh_t e wv1_hh pelos valores wv1_time e wv1. Para a onda 2, substituiremos wv2_ll_t e wv2_ll por wv2_time e wv2. Da mesma forma, para a onda 3, substituiremos wv3_hh_t e wv3_hh por wv3_time e wv3. Com essa alteração, buscamos utilizar os verdadeiros extremos estruturais de cada trecho, em vez dos pontos de swing identificados inicialmente. Ao desenhar os objetos gráficos com base nesses extremos validados, melhoramos significativamente a precisão e a confiabilidade da representação visual do padrão de ondas de Wolfe, permitindo que os traders tomem decisões mais fundamentadas a partir de uma estrutura mais precisa.
A extensão de Fibonacci, os objetos gráficos das ondas 1 a 4 e os demais elementos visuais serão criados somente após o cumprimento dos seguintes critérios:
if(wv3_wv4_size >= wv1_wv2_size && wv4 > wv2_ll && wv4 < wv3_hh && wv3_hh >= fib_ext_1_2_127_2 && wv3_hh <= fib_ext_1_2_161_8)Essa condição garante que todos os requisitos de preço e estrutura necessários para validar um padrão de ondas de Wolfe de baixa sejam atendidos. Ela confirma que a distância vertical entre as ondas 3 e 4 é pelo menos igual à distância entre as ondas 1 e 2, preservando a simetria. Também verifica se a onda 4 está acima da menor mínima registrada entre as ondas 2 e 3 e abaixo da maior máxima registrada entre as ondas 3 e 4. Além disso, a onda 3 deve estar dentro da faixa de extensão de Fibonacci de 127,2% a 200%, calculada com base nas ondas 1 e 2.
O programa só adicionará os rótulos das ondas, criará a extensão de Fibonacci e traçará as linhas de tendência necessárias no gráfico depois que todos esses critérios forem atendidos. Essa validação rigorosa aumenta a precisão da detecção das ondas de Wolfe e ajuda a evitar que padrões incorretos ou incompletos sejam desenhados no gráfico.
Identificação da onda 5
O próximo passo na detecção das ondas de Wolfe é identificar a onda 5. Essa onda é fundamental porque indica um possível ponto de reversão do padrão. Na análise técnica, ela é uma referência importante, pois os traders costumam procurá-la para antecipar mudanças na direção do mercado. No entanto, antes de identificá-la corretamente, precisamos traçar três linhas de tendência essenciais para confirmar sua formação.
A primeira linha de tendência conecta as ondas 1 e 3. Em geral, ela representa o limite superior do padrão de ondas de Wolfe de baixa. Essa linha ajuda a definir a estrutura e a direção do padrão, além de funcionar como um nível de resistência que tende a limitar o avanço do preço durante a formação da onda 4 e o desenvolvimento da onda 5. A segunda linha de tendência conecta as ondas 2 e 4. Ela é importante porque ajuda a definir a estrutura do canal e a simetria do padrão de Wolfe. À medida que o preço se aproxima do possível ponto de reversão, essa linha oferece uma referência para a trajetória esperada da onda 5.
A terceira linha de tendência, que conecta as ondas 1 e 4, desempenha uma função diferente das duas anteriores. Ela costuma ser utilizada para determinar o momento de encerrar a operação. No padrão de Wolfe de baixa, a linha entre as ondas 1 e 4 funciona como alvo de realização de lucro após a identificação da onda 5, quando o preço começa a se mover na direção esperada. Assim que o preço cruzar essa linha de tendência, a operação será encerrada, indicando que o movimento previsto ocorreu e que o padrão foi concluído.
Exemplo:string tline_1_3; string tline_2_4; string tline_1_4;
if(wv3_wv4_size >= wv1_wv2_size && wv4 > wv2_ll && wv4 < wv3_hh && wv3_hh >= fib_ext_1_2_127_2 && wv3_hh <= fib_ext_1_2_161_8) { ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_hh_t, wv1_hh); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_ll_t, wv2_ll); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_ll_t, wv2_ll, wv1_hh_t, wv1_hh, wv2_ll_t, wv2_ll); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_hh_t, wv1_hh - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_hh_t, fib_ext_1_2_161_8, wv2_ll_t, fib_ext_1_2_127_2); ObjectCreate(chart_id, wv3_txt, OBJ_TEXT, 0, wv3_hh_t, wv3_hh); ObjectSetString(chart_id, wv3_txt, OBJPROP_TEXT, "WV3"); ObjectSetInteger(chart_id, wv3_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv4_txt, OBJ_TEXT, 0, wv4_time, wv4); ObjectSetString(chart_id, wv4_txt, OBJPROP_TEXT, "WV4"); ObjectSetInteger(chart_id, wv4_txt, OBJPROP_COLOR, clrBlue); tline_1_3 = StringFormat("TREND LINE WAVE 1 AND 3 %d", i); ObjectCreate(chart_id, tline_1_3, OBJ_TREND, 0, wv1_hh_t, wv1_hh, wv3_hh_t, wv3_hh); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_COLOR, clrBlue); tline_2_4 = StringFormat("TREND LINE WAVE 2 AND 4 %d", i); ObjectCreate(chart_id, tline_2_4, OBJ_TREND, 0, wv2_ll_t, wv2_ll, wv4_time, wv4); ObjectSetInteger(chart_id, tline_2_4, OBJPROP_COLOR, clrBlue); tline_1_4 = StringFormat("TREND LINE WAVE 1 AND 4 %d", i); ObjectCreate(chart_id, tline_1_4, OBJ_TREND, 0, wv1_hh_t, wv1_hh, wv4_time, wv4); ObjectSetInteger(chart_id, tline_1_4, OBJPROP_COLOR, clrBlue); }
Saída:

Explicação:
As variáveis do tipo string tline_1_3, tline_2_4 e tline_1_4 são declaradas inicialmente para atribuir identificadores únicos às linhas de tendência do gráfico. A variável tline_1_3 armazena o nome da linha de tendência que conecta as ondas 1 e 3, representando o limite superior do padrão de ondas de Wolfe de baixa. A função ObjectCreate() é utilizada para traçar essa linha com base nas máximas validadas das ondas 1 e 3. Para facilitar a visualização, a linha é desenhada em azul. A segunda linha de tendência, que conecta as ondas 2 e 4, é identificada pela variável tline_2_4. Também desenhada em azul, ela é traçada entre a menor mínima da onda 2 (wv2_ll_t, wv2_ll) e o ponto da onda 4 (wv4_time, wv4). A terceira linha de tendência, tline_1_4, conecta as ondas 1 e 4.
Uma limitação dessa abordagem é que as linhas de tendência são desenhadas apenas entre dois pontos de ancoragem previamente definidos. Em um padrão de ondas de Wolfe válido, cada linha deve se prolongar além do segundo ponto de ancoragem para permitir a análise de possíveis interações futuras com o preço. Por exemplo, a linha de tendência que conecta as ondas 1 e 3 não deve se limitar ao segmento entre esses dois pontos. Espera-se que o mercado continue se movimentando após a onda 3, a menos que ultrapasse essa linha e depois recue. Esse prolongamento oferece uma visão mais clara da relação entre o preço e o limite superior do padrão ao longo do tempo.
Para preservar a simetria das ondas de Wolfe e prever a provável posição da onda 5, a linha de tendência entre as ondas 2 e 4 deve ter o mesmo comprimento e a mesma direção da linha que conecta as ondas 1 e 3. A linha de tendência que funciona como alvo de saída da operação também precisa se prolongar além da onda 4, permitindo que o preço a alcance e indique o momento de encerrar a operação. Em outras palavras, as três linhas de tendência devem ser prolongadas adequadamente para o futuro, permitindo confirmar o padrão com precisão e planejar a operação.
Exemplo:
tline_1_3 = StringFormat("TREND LINE WAVE 1 AND 3 %d", i); ObjectCreate(chart_id,tline_1_3,OBJ_TREND,0,wv1_hh_t,wv1_hh,wv3_hh_t,wv3_hh); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_RAY_RIGHT, true); tline_2_4 = StringFormat("TREND LINE WAVE 2 AND 4 %d", i); ObjectCreate(chart_id,tline_2_4,OBJ_TREND,0,wv2_ll_t,wv2_ll,wv4_time,wv4); ObjectSetInteger(chart_id, tline_2_4, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_RAY_RIGHT, true); tline_1_4 = StringFormat("TREND LINE WAVE 1 AND 4 %d", i); ObjectCreate(chart_id,tline_1_4,OBJ_TREND,0,wv1_hh_t,wv1_hh,wv4_time,wv4); ObjectSetInteger(chart_id, tline_1_4, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_RAY_RIGHT, true);

A propriedade OBJPROP_RAY_RIGHT faz com que as linhas de tendência se prolonguem além dos pontos de ancoragem, mas isso também apresenta um problema. Embora esse recurso seja útil para manter as linhas visíveis, seu comportamento não corresponde exatamente ao que precisamos na análise das ondas de Wolfe. Neste caso, não queremos que as linhas de tendência se estendam indefinidamente. Precisamos que elas terminem em um ponto específico, principalmente quando determinada condição for atendida.
Por exemplo, a linha de tendência que conecta as ondas 1 e 3 deve se estender somente até o momento em que o preço ultrapasse essa linha e, posteriormente, volte a cair abaixo dela. Dessa forma, mantemos a precisão da análise e evitamos sobrecarregar o gráfico com linhas de tendência desnecessárias ou que já não sejam relevantes. Ao definir o ponto final de cada linha com base na interação efetiva do preço com ela, temos maior controle sobre sua representação e conseguimos visualizar a estrutura do padrão de ondas de Wolfe com mais precisão e clareza.
Exemplo:tline_1_3 = StringFormat("TREND LINE WAVE 1 AND 3 %d", i); if(ObjectCreate(chart_id,tline_1_3,OBJ_TREND,0,wv1_hh_t,wv1_hh,wv3_hh_t,wv3_hh)) { ObjectSetInteger(chart_id, tline_1_3, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_RAY_RIGHT, true); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } tline_2_4 = StringFormat("TREND LINE WAVE 2 AND 4 %d", i); if(ObjectCreate(chart_id,tline_2_4,OBJ_TREND,0,wv2_ll_t,wv2_ll,wv4_time,wv4)) { ObjectSetInteger(chart_id, tline_2_4, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_2_4, OBJPROP_RAY_RIGHT, true); ObjectSetInteger(chart_id, tline_2_4, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } tline_1_4 = StringFormat("TREND LINE WAVE 1 AND 4 %d", i); if(ObjectCreate(chart_id,tline_1_4,OBJ_TREND,0,wv1_hh_t,wv1_hh,wv4_time,wv4)) { ObjectSetInteger(chart_id, tline_1_4, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_4, OBJPROP_RAY_RIGHT, true); ObjectSetInteger(chart_id, tline_1_4, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); }

Explicação:
Esse código cria uma linha de tendência invisível, que pode ser utilizada internamente sem aparecer no gráfico, pois sua propriedade de exibição está configurada para ocultá-la em todos os timeframes. Em seguida, o algoritmo monitora swings de preço relevantes, como um fechamento de candle acima da linha de tendência 1-3, seguido por um fechamento abaixo dela.
Exemplo:double t_1_3_values; double t_2_4_values; string tline_1_3_visible; string tline_2_4_visible;
for(int m = l; m < bars_check - 2; m++) { t_1_3_values = ObjectGetValueByTime(chart_id, tline_1_3, time[m], 0); t_2_4_values = ObjectGetValueByTime(chart_id, tline_2_4, time[m], 0); if(close[m] > open[m] && open[m] < t_1_3_values && close[m] > t_1_3_values && time[m] > time[l+4]) { tline_1_3_visible = StringFormat("TREND LINE WAVE 1 AND 3 V %d", i); ObjectCreate(chart_id,tline_1_3_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[m],t_1_3_values); ObjectSetInteger(chart_id, tline_1_3_visible, OBJPROP_COLOR, clrBlue); tline_2_4_visible = StringFormat("TREND LINE WAVE 2 AND 4 V %d", i); ObjectCreate(chart_id,tline_2_4_visible,OBJ_TREND,0,wv2_ll_t,wv2_ll,time[m],t_2_4_values); ObjectSetInteger(chart_id, tline_2_4_visible, OBJPROP_COLOR, clrBlue); break; } }
Saída:

Explicação:
Esse trecho de código detecta o rompimento da linha de tendência que conecta as ondas 1 e 3, analisando as barras posteriores à onda 4. Para isso, utiliza variáveis que permitem obter o nível de preço da linha de tendência no horário de cada barra e procura um candle de alta que abra abaixo da linha e feche acima dela. Esse comportamento sinaliza um rompimento, que deve ocorrer pelo menos quatro barras após a onda 4. Quando o rompimento é identificado, o código cria duas novas linhas de tendência visíveis, cujos nomes são gerados dinamicamente pela função StringFormat. Essas linhas são então desenhadas no gráfico: uma conecta a onda 1 ao ponto de rompimento, enquanto a outra conecta a onda 2 a esse mesmo ponto. Isso facilita a visualização e a análise do desenvolvimento do padrão de ondas de Wolfe, permitindo identificar claramente o candle exato em que o preço rompe a linha de tendência 1-3 para cima.
Mas esse ainda não é o resultado que buscamos. Embora ajudem a identificar o rompimento, as linhas de tendência visíveis criadas quando o preço cruza a linha 1-3 e fecha acima dela ainda não representam a conclusão da estrutura das ondas de Wolfe. O objetivo é manter essas linhas prolongadas até que o preço volte a cruzar a linha de tendência 1-3 e feche abaixo dela.
Exemplo:double t_1_3_values_2;for(int m = l; m < bars_check - 2; m++) { t_1_3_values = ObjectGetValueByTime(chart_id, tline_1_3, time[m], 0); if(close[m] > open[m] && open[m] < t_1_3_values && close[m] > t_1_3_values && time[m] > time[l+4]) { for(int n = m; n < bars_check - 1; n++) { t_1_3_values_2 = ObjectGetValueByTime(chart_id, tline_1_3, time[n], 0); t_2_4_values = ObjectGetValueByTime(chart_id, tline_2_4, time[n], 0); if(close[n] < open[n] && open[n] > t_1_3_values_2 && close[n] < t_1_3_values_2) { tline_1_3_visible = StringFormat("TREND LINE WAVE 1 AND 3 V %d", i); ObjectCreate(chart_id,tline_1_3_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[n],t_1_3_values_2); ObjectSetInteger(chart_id, tline_1_3_visible, OBJPROP_COLOR, clrBlue); tline_2_4_visible = StringFormat("TREND LINE WAVE 2 AND 4 V %d", i); ObjectCreate(chart_id,tline_2_4_visible,OBJ_TREND,0,wv2_ll_t,wv2_ll,time[n],t_2_4_values); ObjectSetInteger(chart_id, tline_2_4_visible, OBJPROP_COLOR, clrBlue); break; } } break; } }
Saída:

Explicação:
Mas esse ainda não é o resultado que buscamos. Embora ajudem a identificar o rompimento, as linhas de tendência visíveis criadas quando o preço cruza a linha 1-3 e fecha acima dela ainda não representam a conclusão da estrutura das ondas de Wolfe. O objetivo é manter essas linhas prolongadas até que o preço volte a cruzar a linha de tendência 1-3 e feche abaixo dela. Mais especificamente, um laço for interno utiliza a variável t_1_3_values_2 para armazenar o nível de preço da linha de tendência 1-3 em um momento posterior. Esse laço inicia a varredura na barra de índice m, onde foi registrado o rompimento para cima. Para cada barra n, a função ObjectGetValueByTime obtém o valor da linha de tendência no horário correspondente e o armazena na variável t_1_3_values_2.
A condição if(close[n] < open[n] && open[n] > t_1_3_values_2 && close[n] < t_1_3_values_2 verifica se há um candle de baixa que abriu acima da linha de tendência e fechou abaixo dela, indicando que o preço voltou a cruzá-la para baixo. Essa ocorrência é especialmente importante porque muitas vezes marca o fim da onda 5 e o início da reversão esperada. Assim que esse segundo cruzamento é identificado, são criadas duas novas linhas de tendência distintas: uma conecta a onda 1 ao novo ponto identificado no gráfico, enquanto a outra conecta a onda 2 a esse mesmo ponto. Isso oferece uma representação mais completa e precisa das ondas de Wolfe, desde o início da estrutura até o rompimento e a reversão, substituindo as linhas de tendência anteriores. Agora, as linhas se estendem desde seus pontos de origem até o momento exato em que a ação do preço confirma a formação completa do padrão.
O próximo passo é determinar o nível de preço da onda 5. Para isso, precisamos localizar a maior máxima entre dois momentos importantes: o primeiro, quando o preço cruza a linha de tendência 1-3 e fecha acima dela; e o segundo, quando ocorre a reversão e o preço volta a cruzar essa mesma linha para baixo. Esse intervalo geralmente corresponde à fase final do padrão de ondas de Wolfe. Antes de iniciar a reversão esperada, o preço costuma apresentar mais um impulso de alta nessa região. Ao identificar a maior máxima desse intervalo, podemos determinar com precisão o topo da onda 5.
Exemplo:int cross_bars; int cross_bars_highest; string wv5_txt;
if(close[m] > open[m] && open[m] < t_1_3_values && close[m] > t_1_3_values && time[m] > time[l+4]) { for(int n = m; n < bars_check - 1; n++) { t_1_3_values_2 = ObjectGetValueByTime(chart_id, tline_1_3, time[n], 0); t_2_4_values = ObjectGetValueByTime(chart_id, tline_2_4, time[n], 0); if(close[n] < open[n] && open[n] > t_1_3_values_2 && close[n] < t_1_3_values_2) { tline_1_3_visible = StringFormat("TREND LINE WAVE 1 AND 3 V %d", i); ObjectCreate(chart_id,tline_1_3_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[n],t_1_3_values_2); ObjectSetInteger(chart_id, tline_1_3_visible, OBJPROP_COLOR, clrBlue); tline_2_4_visible = StringFormat("TREND LINE WAVE 2 AND 4 V %d", i); ObjectCreate(chart_id,tline_2_4_visible,OBJ_TREND,0,wv2_ll_t,wv2_ll,time[n],t_2_4_values); ObjectSetInteger(chart_id, tline_2_4_visible, OBJPROP_COLOR, clrBlue); cross_bars = Bars(_Symbol,timeframe,time[n], time[m]); cross_bars_highest = ArrayMaximum(high,m,cross_bars); wv5_txt = StringFormat("WAVE 5 %d", i); ObjectCreate(chart_id, wv5_txt, OBJ_TEXT, 0, time[cross_bars_highest], high[cross_bars_highest]); ObjectSetString(chart_id, wv5_txt, OBJPROP_TEXT, "WV5"); ObjectSetInteger(chart_id, wv5_txt, OBJPROP_COLOR, clrBlue); break; } }
Explicação:
Esse trecho de código identifica e marca a quinta onda do padrão de Wolfe. Depois que o preço rompe a linha de tendência 1-3 e retorna para baixo dela, o algoritmo calcula a quantidade de barras entre os pontos de rompimento e reversão para determinar o momento esperado de formação da onda 5. Em seguida, utiliza a função ArrayMaximum() para procurar a maior máxima no array de preços high[], analisando a quantidade de barras definida pela variável cross_bars a partir do índice m. A função identifica a maior máxima desse intervalo, que corresponde ao topo da onda 5. O índice dessa máxima é armazenado na variável cross_bars_highest.
Para marcar essa máxima com o rótulo "WV5", o código cria um objeto de texto no gráfico. O rótulo é posicionado com base na data e no preço correspondentes ao índice cross_bars_highest e recebe a cor azul (blue), mantendo o mesmo padrão visual dos rótulos das ondas anteriores. Isso completa a representação gráfica da estrutura de Wolfe, garantindo que a onda 5 seja marcada corretamente na maior máxima registrada entre o rompimento e a reversão.
Extensão de Fibonacci
Como você deve se lembrar, já estabelecemos que a onda 5 precisa estar dentro de uma faixa específica de extensão de Fibonacci, calculada a partir das ondas 3 e 4. Essa faixa normalmente corresponde aos níveis de 127,2% a 161,8% do movimento de preço entre essas duas ondas.
Exemplo:input ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT; // TIMEFRAME input double max_fib_ext_wv12 = 161.8; // WAVE 1 AND 2 FIBO EXTENSION MAX LEVEL input double min_fib_ext_wv12 = 127.2; // WAVE 1 AND 2 FIBO EXTENSION MIN LEVEL input double max_fib_ext_wv34 = 120.0; // WAVE 3 AND 4 FIBO EXTENSION MAX LEVEL input double min_fib_ext_wv34 = 200.0; // WAVE 3 AND 4 FIBO EXTENSION MIN LEVEL string fib_ext_3_4; double fib_ext_3_4_161_8; double fib_ext_3_4_127_2; string fib_ext_3_4_168_127; string fib_ext_range_3_4; int no_bars;
for(int l = k; l < bars_check - 7; l++) { if(IsSwingLow(low, l, 7) && time[l] > wv3_time) { wv4 = low[l]; wv4_time = time[l]; wv4_txt = StringFormat("WAVE 4 %d", l); wv3_wv4_bars = Bars(_Symbol, timeframe, wv3_time, wv4_time); wv3_highest_index = ArrayMaximum(high, k, wv3_wv4_bars); wv3_hh = high[wv3_highest_index]; wv3_hh_t = time[wv3_highest_index]; wv2_wv3_bars = Bars(_Symbol, timeframe, wv2_time, wv3_time); wv2_lowest_index = ArrayMinimum(low, j, wv2_wv3_bars); wv2_ll = low[wv2_lowest_index]; wv2_ll_t = time[wv2_lowest_index]; wv1_wv2_bars = Bars(_Symbol, timeframe, wv1_time, wv2_time); wv1_highest_index = ArrayMaximum(high, i, wv1_wv2_bars); wv1_hh = high[wv1_highest_index]; wv1_hh_t = time[wv1_highest_index]; wv1_wv2_size = MathAbs(wv1_hh - wv2_ll); wv1_wv2_70p = (wv1_wv2_size / 100) * 70; fib_ext_1_2_127_2 = MathAbs((((wv1_hh - wv2_ll) / 100) * (min_fib_ext_wv12 - 100)) + wv1_hh); fib_ext_1_2_161_8 = MathAbs((((wv1_hh - wv2_ll) / 100) * (max_fib_ext_wv12 - 100)) + wv1_hh); wv3_wv4_size = MathAbs(wv3_hh - wv4); if(wv3_wv4_size >= wv1_wv2_size && wv4 > wv2_ll && wv4 < wv3_hh && wv3_hh >= fib_ext_1_2_127_2 && wv3_hh <= fib_ext_1_2_161_8) { tline_1_3 = StringFormat("TREND LINE WAVE 1 AND 3 %d", i); if(ObjectCreate(chart_id,tline_1_3,OBJ_TREND,0,wv1_hh_t,wv1_hh,wv3_hh_t,wv3_hh)) { ObjectSetInteger(chart_id, tline_1_3, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_RAY_RIGHT, true); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } tline_2_4 = StringFormat("TREND LINE WAVE 2 AND 4 %d", i); if(ObjectCreate(chart_id,tline_2_4,OBJ_TREND,0,wv2_ll_t,wv2_ll,wv4_time,wv4)) { ObjectSetInteger(chart_id, tline_2_4, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_2_4, OBJPROP_RAY_RIGHT, true); ObjectSetInteger(chart_id, tline_2_4, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } tline_1_4 = StringFormat("TREND LINE WAVE 1 AND 4 %d", i); if(ObjectCreate(chart_id,tline_1_4,OBJ_TREND,0,wv1_hh_t,wv1_hh,wv4_time,wv4)) { ObjectSetInteger(chart_id, tline_1_4, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_4, OBJPROP_RAY_RIGHT, true); ObjectSetInteger(chart_id, tline_1_4, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } fib_ext_3_4 = StringFormat("FIB EXTENSION WAVE 3 AND 4 %d", i); fib_ext_3_4_127_2 = MathAbs((((wv3_hh - wv4) / 100) * (min_fib_ext_wv34 - 100)) + wv3_hh); fib_ext_3_4_161_8 = MathAbs((((wv3_hh - wv4) / 100) * (max_fib_ext_wv34 - 100)) + wv3_hh); fib_ext_3_4_168_127 = StringFormat("FIB EXTENSION wv3 wv4 %d", i); for(int m = l; m < bars_check - 2; m++) { t_1_3_values = ObjectGetValueByTime(chart_id, tline_1_3, time[m], 0); if(close[m] > open[m] && open[m] < t_1_3_values && close[m] > t_1_3_values && time[m] > time[l+4]) { for(int n = m; n < bars_check - 1; n++) { t_1_3_values_2 = ObjectGetValueByTime(chart_id, tline_1_3, time[n], 0); t_2_4_values = ObjectGetValueByTime(chart_id, tline_2_4, time[n], 0); no_bars = Bars(_Symbol, timeframe, wv3_hh_t, time[n]); cross_bars = Bars(_Symbol,timeframe,time[n], time[m]); cross_bars_highest = ArrayMaximum(high,m,cross_bars); if(close[n] < open[n] && open[n] > t_1_3_values_2 && close[n] < t_1_3_values_2 && no_bars < 100 && time[n] > time[m] && high[cross_bars_highest] >= fib_ext_3_4_127_2 && high[cross_bars_highest] <= fib_ext_3_4_161_8) { ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_hh_t, wv1_hh); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_ll_t, wv2_ll); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_ll_t, wv2_ll, wv1_hh_t, wv1_hh, wv2_ll_t, wv2_ll); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_hh_t, wv1_hh - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_hh_t, fib_ext_1_2_161_8, wv2_ll_t, fib_ext_1_2_127_2); ObjectCreate(chart_id, wv3_txt, OBJ_TEXT, 0, wv3_hh_t, wv3_hh); ObjectSetString(chart_id, wv3_txt, OBJPROP_TEXT, "WV3"); ObjectSetInteger(chart_id, wv3_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv4_txt, OBJ_TEXT, 0, wv4_time, wv4); ObjectSetString(chart_id, wv4_txt, OBJPROP_TEXT, "WV4"); ObjectSetInteger(chart_id, wv4_txt, OBJPROP_COLOR, clrBlue); tline_1_3_visible = StringFormat("TREND LINE WAVE 1 AND 3 V %d", i); ObjectCreate(chart_id,tline_1_3_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[n],t_1_3_values_2); ObjectSetInteger(chart_id, tline_1_3_visible, OBJPROP_COLOR, clrBlue); tline_2_4_visible = StringFormat("TREND LINE WAVE 2 AND 4 V %d", i); ObjectCreate(chart_id,tline_2_4_visible,OBJ_TREND,0,wv2_ll_t,wv2_ll,time[n],t_2_4_values); ObjectSetInteger(chart_id, tline_2_4_visible, OBJPROP_COLOR, clrBlue); wv5_txt = StringFormat("WAVE 5 %d", i); ObjectCreate(chart_id, wv5_txt, OBJ_TEXT, 0, time[cross_bars_highest], high[cross_bars_highest]); ObjectSetString(chart_id, wv5_txt, OBJPROP_TEXT, "WV5"); ObjectSetInteger(chart_id, wv5_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, fib_ext_3_4,OBJ_EXPANSION, 0,wv4_time, wv4,wv3_hh_t,wv3_hh,wv4_time,wv4); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id,fib_ext_3_4,OBJPROP_LEVELCOLOR,i,clrBlue); ObjectSetInteger(chart_id,fib_ext_3_4,OBJPROP_COLOR,clrBlue); } fib_ext_range_3_4 = StringFormat("Fibo EXPENSION RANGE WV3 WV4 %d", i); ObjectCreate(chart_id,fib_ext_range_3_4,OBJ_RECTANGLE,0,wv3_hh_t,fib_ext_3_4_127_2,time[cross_bars_highest],fib_ext_3_4_161_8); break; } } break; } } } break; } }
Saída:

Explicação:
Aqui, utilizamos a extensão de Fibonacci das ondas 3 e 4. Ao calcular os níveis de Fibonacci e contar as barras entre a onda 3 e o fechamento do preço abaixo da linha de tendência 1-3, o algoritmo garante a correção estrutural e a compactação do padrão. Por meio de um bloco condicional, o EA procura um candle de baixa que cruze a linha de tendência 1-3 e feche abaixo dela. A reversão deve ocorrer em menos de 100 barras, e a maior máxima registrada entre o rompimento e a reversão precisa estar dentro da faixa permitida de extensão de Fibonacci, conforme os parâmetros definidos adiante. Se todos esses requisitos forem atendidos, a onda 5 poderá ser considerada válida.
Em seguida, utilizamos o movimento entre as ondas 3 e 4 como referência para criar o objeto de extensão de Fibonacci. Para facilitar a visualização, os três níveis de extensão (0%, 127,2% e 161,8%) são marcados em azul. Também desenhamos um retângulo para destacar visualmente a zona-alvo de Fibonacci. É fundamental que todos os objetos gráficos correspondentes, como zonas de extensão, rótulos e linhas de tendência, sejam criados exclusivamente dentro desse bloco condicional. Isso reduz a ocorrência de sinais falsos e aumenta a confiabilidade da detecção do padrão, garantindo que a estrutura completa só seja desenhada após o cumprimento de todas as regras.
Traçado da linha de tendência entre as ondas 1 e 4
Antes de permitir que o EA execute operações, precisamos traçar a linha de tendência que conecta as ondas 1 e 4. Essa linha desempenha um papel fundamental no padrão de ondas de Wolfe, principalmente no planejamento da saída da operação.int no_wv1_n_bars; int no_n_c_bars; string tline_1_4_visible; double t_1_4_values; string tline_1_4_visible_2; if(close[n] < open[n] && open[n] > t_1_3_values_2 && close[n] < t_1_3_values_2 && no_bars < 100 && time[n] > time[m] && high[cross_bars_highest] >= fib_ext_3_4_127_2 && high[cross_bars_highest] <= fib_ext_3_4_161_8) { ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_hh_t, wv1_hh); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_ll_t, wv2_ll); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_ll_t, wv2_ll, wv1_hh_t, wv1_hh, wv2_ll_t, wv2_ll); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_hh_t, wv1_hh - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_hh_t, fib_ext_1_2_161_8, wv2_ll_t, fib_ext_1_2_127_2); ObjectCreate(chart_id, wv3_txt, OBJ_TEXT, 0, wv3_hh_t, wv3_hh); ObjectSetString(chart_id, wv3_txt, OBJPROP_TEXT, "WV3"); ObjectSetInteger(chart_id, wv3_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv4_txt, OBJ_TEXT, 0, wv4_time, wv4); ObjectSetString(chart_id, wv4_txt, OBJPROP_TEXT, "WV4"); ObjectSetInteger(chart_id, wv4_txt, OBJPROP_COLOR, clrBlue); tline_1_3_visible = StringFormat("TREND LINE WAVE 1 AND 3 V %d", i); ObjectCreate(chart_id,tline_1_3_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[n],t_1_3_values_2); ObjectSetInteger(chart_id, tline_1_3_visible, OBJPROP_COLOR, clrBlue); tline_2_4_visible = StringFormat("TREND LINE WAVE 2 AND 4 V %d", i); ObjectCreate(chart_id,tline_2_4_visible,OBJ_TREND,0,wv2_ll_t,wv2_ll,time[n],t_2_4_values); ObjectSetInteger(chart_id, tline_2_4_visible, OBJPROP_COLOR, clrBlue); wv5_txt = StringFormat("WAVE 5 %d", i); ObjectCreate(chart_id, wv5_txt, OBJ_TEXT, 0, time[cross_bars_highest], high[cross_bars_highest]); ObjectSetString(chart_id, wv5_txt, OBJPROP_TEXT, "WV5"); ObjectSetInteger(chart_id, wv5_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, fib_ext_3_4,OBJ_EXPANSION, 0,wv4_time, wv4,wv3_hh_t,wv3_hh,wv4_time,wv4); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id,fib_ext_3_4,OBJPROP_LEVELCOLOR,i,clrBlue); ObjectSetInteger(chart_id,fib_ext_3_4,OBJPROP_COLOR,clrBlue); } fib_ext_range_3_4 = StringFormat("Fibo EXPENSION RANGE WV3 WV4 %d", i); ObjectCreate(chart_id,fib_ext_range_3_4,OBJ_RECTANGLE,0,wv3_hh_t,fib_ext_3_4_127_2,time[cross_bars_highest],fib_ext_3_4_161_8); no_wv1_n_bars = Bars(_Symbol, timeframe, wv1_hh_t, time[n]); no_n_c_bars = Bars(_Symbol, timeframe, time[n], TimeCurrent()); if(no_n_c_bars <= no_wv1_n_bars) { t_1_4_values = ObjectGetValueByTime(chart_id, tline_1_4, TimeCurrent(), 0); tline_1_4_visible = "TL WAVE 1 AND 4 Visible"; ObjectCreate(chart_id,tline_1_4_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,TimeCurrent(),t_1_4_values); ObjectSetInteger(chart_id,tline_1_4_visible,OBJPROP_STYLE,STYLE_DASH); ObjectSetInteger(chart_id,tline_1_4_visible,OBJPROP_COLOR,clrBlue); } if(no_n_c_bars > no_wv1_n_bars) { ObjectDelete(chart_id,tline_1_4_visible); t_1_4_values = ObjectGetValueByTime(chart_id, tline_1_4, time[n + no_wv1_n_bars], 0); tline_1_4_visible_2 = StringFormat("TL WAVE 1 AND 4 DISPLAY %d", i); ObjectCreate(chart_id,tline_1_4_visible_2,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[n+no_wv1_n_bars],t_1_4_values); ObjectSetInteger(chart_id,tline_1_4_visible_2,OBJPROP_STYLE,STYLE_DASH); ObjectSetInteger(chart_id,tline_1_4_visible_2,OBJPROP_COLOR,clrBlue); } break; }
Explicação:
As variáveis no_wv1_n_bars e no_n_c_bars são utilizadas para calcular a quantidade de barras entre pontos importantes do gráfico. Especificamente, no_wv1_n_bars determina o número de barras entre a marca de tempo da onda 1 e o momento em que o mercado reverteu, cruzando novamente a linha de tendência para baixo. Já no_n_c_bars armazena a quantidade de barras entre a barra atual do gráfico e o ponto de reversão (onda 5). A comparação desses valores permite determinar se a linha de tendência 1-4 deve se estender até uma barra futura predefinida ou até a barra atual do mercado.
A linha de tendência identificada como "TL WAVE 1 AND 4 Visible" é traçada entre a onda 1 e o horário atual do mercado, desde que a quantidade de barras após o ponto de reversão não ultrapasse o intervalo entre a onda 1 e esse ponto (no_n_c_bars <= no_wv1_n_bars). A função ObjectGetValueByTime é utilizada para obter o valor atual da linha de tendência, que é desenhada em azul e com estilo tracejado para facilitar a visualização.
Por outro lado, se a quantidade de barras após o ponto de reversão ultrapassar o intervalo entre a onda 1 e a reversão, a linha traçada anteriormente será excluída pela função ObjectDelete. Nesse caso, uma nova linha de tendência será criada, partindo da onda 1 até um ponto específico no futuro (time[n + no_wv1_n_bars]), de modo a manter a mesma extensão da projeção original. Essa nova linha recebe um nome gerado dinamicamente e também é desenhada em azul, com estilo tracejado. Dessa forma, o algoritmo se adapta às atualizações do gráfico em tempo real, mantendo a linha de tendência entre as ondas 1 e 4 estável e com a orientação definida.
Execução de operações
Até aqui, conseguimos identificar as cinco ondas do padrão de Wolfe, da onda 1 à onda 5, além das três linhas de tendência principais, que conectam as ondas 1 e 3, 2 e 4, e 1 e 4. Essas linhas não apenas oferecem uma confirmação visual do padrão, mas também servem de referência para decidir quando executar as operações.
O próximo passo é executar uma operação com base na estrutura já identificada. A condição de entrada para o padrão de ondas de Wolfe de baixa está diretamente relacionada ao comportamento do preço nas proximidades da linha de tendência 1-3. Primeiro, um candle deve cruzar essa linha para cima, o que pode indicar que a tendência de alta está chegando ao fim. Depois, o preço precisa voltar a cruzá-la para baixo. Esse segundo cruzamento representa uma boa oportunidade para abrir uma posição vendida, pois reforça a possibilidade de uma reversão de baixa. O EA só deve abrir a operação depois que essas duas etapas de confirmação forem concluídas.
Exemplo:
#include <Trade/Trade.mqh> CTrade trade; input int MagicNumber = 6160; input double lot_size = 0.01; input ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT; // TIMEFRAME input double max_fib_ext_wv12 = 161.8; // WAVE 1 AND 2 FIBO EXTENSION MAX LEVEL input double min_fib_ext_wv12 = 127.2; // WAVE 1 AND 2 FIBO EXTENSION MIN LEVEL input double max_fib_ext_wv34 = 200.0; // WAVE 3 AND 4 FIBO EXTENSION MAX LEVEL input double min_fib_ext_wv34 = 120.0; // WAVE 3 AND 4 FIBO EXTENSION MIN LEVEL
datetime time_exe[]; datetime lastTradeBarTime = 0; double ask_price; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- trade.SetExpertMagicNumber(MagicNumber); ArraySetAsSeries(time_exe,true); //--- return(INIT_SUCCEEDED); }
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- total_symbol_bars = Bars(_Symbol, timeframe); time_bar = iTime(_Symbol,timeframe,0); CopyOpen(_Symbol, timeframe, time_bar, bars_check, open); CopyClose(_Symbol, timeframe, time_bar, bars_check, close); CopyLow(_Symbol, timeframe, time_bar, bars_check, low); CopyHigh(_Symbol, timeframe, time_bar, bars_check, high); CopyTime(_Symbol, timeframe, time_bar, bars_check, time); CopyTime(_Symbol, timeframe, 0, 2, time_exe); datetime currentBarTime = iTime(_Symbol, timeframe, 0); ask_price = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
if(time[n] == time_exe[1] && currentBarTime != lastTradeBarTime) { trade.Sell(lot_size,_Symbol,ask_price, high[cross_bars_highest],wv2_ll); lastTradeBarTime = currentBarTime; }
Saída:

Explicação:
A diretiva #include permite incorporar a biblioteca de negociação padrão do MQL5, disponibilizando as funcionalidades de gerenciamento de operações da classe CTrade. Após incluir essa biblioteca, criamos uma instância da classe CTrade chamada trade. Esse objeto é responsável por executar os comandos de negociação, como compra, venda, definição de take-profit e stop-loss, além do gerenciamento de ordens. Em seguida, declaramos duas variáveis de entrada: MagicNumber e lot_size. As operações realizadas pelo EA são identificadas por um número mágico exclusivo (MagicNumber), permitindo diferenciá-las de outras operações executadas na mesma conta. Já a variável lot_size define o volume da operação, estabelecido neste exemplo em 0,01 lote.
Em seguida, declaramos algumas variáveis: time_exe[], lastTradeBarTime e ask_price. O array time_exe armazenará os horários das barras mais recentes. A variável lastTradeBarTime é inicializada com zero e utilizada para impedir que o EA execute várias operações no mesmo candle. A variável ask_price armazena o preço Ask atual do ativo, utilizado para executar a operação de venda. A instrução trade.SetExpertMagicNumber(MagicNumber); atribui um número mágico ao objeto de negociação, permitindo identificar posteriormente cada operação executada por ele. A função ArraySetAsSeries(time_exe, true); configura o array time_exe como uma série temporal, de modo que o índice 0 corresponda ao candle mais recente.
Em seguida, a função CopyTime(_Symbol, timeframe, 0, 2, time_exe); copia os horários das duas últimas barras para o array time_exe. A instrução datetime currentBarTime = iTime(_Symbol, timeframe, 0); obtém o horário de abertura do candle atual, que ainda está em formação. Já a instrução ask_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); obtém o preço Ask atual do ativo, necessário para enviar a ordem de venda.
A condição if (time[n] == time_exe[1] && currentBarTime != lastTradeBarTime) verifica se o horário armazenado em time[n] corresponde ao horário de abertura da barra anterior (time_exe[1]). Ao mesmo tempo, a comparação com lastTradeBarTime permite confirmar que nenhuma operação foi executada na barra atual. Se essa condição for verdadeira, o EA enviará uma ordem de venda por meio de trade.Sell(). A operação será aberta ao preço atual armazenado em ask_price, com o stop-loss definido no nível high[cross_bars_highest], que provavelmente corresponde ao topo da onda 5, e o take-profit estabelecido em wv2_ll, a mínima da onda 2, que representa um possível alvo de preço. Por fim, lastTradeBarTime recebe o horário da barra atual, impedindo novas entradas durante o mesmo candle.
Agora, precisamos considerar o último ponto importante da nossa lista: garantir o encerramento correto das operações. Depois de executar uma operação com base no padrão de ondas de Wolfe, precisamos implementar uma lógica que feche automaticamente a posição quando o preço tocar a linha de tendência que conecta as ondas 1 e 4. Essa linha representa nosso alvo de saída, pois, teoricamente, espera-se que o preço reverta nessa região. Além disso, precisamos evitar que as operações permaneçam abertas por tempo excessivo. Se o preço não atingir a linha de tendência dentro de uma quantidade razoável de barras (candles), o EA deverá encerrar a operação mesmo assim. Isso ajuda a limitar a exposição desnecessária ao risco quando o padrão não funciona como esperado ou as condições de mercado mudam.
Exemplo:double low_m[]; double high_m[]; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- trade.SetExpertMagicNumber(MagicNumber); ArraySetAsSeries(time_exe,true); ArraySetAsSeries(low_m,true); ArraySetAsSeries(high_m,true); //--- return(INIT_SUCCEEDED); }
CopyLow(_Symbol, timeframe, 0, 3, low_m); CopyHigh(_Symbol, timeframe, 0, 3, high_m);
if(no_n_c_bars <= no_wv1_n_bars) { t_1_4_values = ObjectGetValueByTime(chart_id, tline_1_4, TimeCurrent(), 0); tline_1_4_visible = "TL WAVE 1 AND 4 Visible"; ObjectCreate(chart_id,tline_1_4_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,TimeCurrent(),t_1_4_values); ObjectSetInteger(chart_id,tline_1_4_visible,OBJPROP_STYLE,STYLE_DASH); ObjectSetInteger(chart_id,tline_1_4_visible,OBJPROP_COLOR,clrBlue); if(time[n] == time_exe[1] && currentBarTime != lastTradeBarTime) { trade.Sell(lot_size,_Symbol,ask_price, high[cross_bars_highest],wv2_ll); lastTradeBarTime = currentBarTime; } for(int i = 0; i < PositionsTotal(); i++) { ulong ticket = PositionGetTicket(i); datetime positionTime = 0; if(PositionSelectByTicket(ticket)) { if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetString(POSITION_SYMBOL) == ChartSymbol(chart_id)) { positionTime = (datetime)PositionGetInteger(POSITION_TIME); if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { double pos_bars = Bars(_Symbol, timeframe, positionTime, TimeCurrent()); if((ask_price < t_1_4_values || low_m[1] < t_1_4_values || no_n_c_bars == no_wv1_n_bars) && no_n_c_bars == pos_bars+1) { trade.PositionClose(ticket); } } } } } } if(no_n_c_bars > no_wv1_n_bars) { ObjectDelete(chart_id,tline_1_4_visible); t_1_4_values = ObjectGetValueByTime(chart_id, tline_1_4, time[n + no_wv1_n_bars], 0); tline_1_4_visible_2 = StringFormat("TL WAVE 1 AND 4 DISPLAY %d", i); ObjectCreate(chart_id,tline_1_4_visible_2,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[n+no_wv1_n_bars],t_1_4_values); ObjectSetInteger(chart_id,tline_1_4_visible_2,OBJPROP_STYLE,STYLE_DASH); ObjectSetInteger(chart_id,tline_1_4_visible_2,OBJPROP_COLOR,clrBlue); }
Saída:

Explicação:
Na primeira parte do código, declaramos dois arrays: double low_m[]; e double high_m[];. Eles armazenam as mínimas e máximas mais recentes das barras do gráfico. Seguindo a convenção de indexação das séries temporais do MetaTrader 5, as chamadas ArraySetAsSeries(low_m, true); e ArraySetAsSeries(high_m, true); configuram os arrays para que o índice 0 corresponda sempre ao candle mais recente. Essa configuração é necessária para comparar os níveis de preço atuais ou recentes com os valores relevantes da linha de tendência.
Em seguida, as mínimas e máximas das três barras mais recentes são copiadas para os arrays low_m e high_m, respectivamente, por meio das funções CopyLow(_Symbol, timeframe, 0, 3, low_m); e CopyHigh(_Symbol, timeframe, 0, 3, high_m);. O código então analisa esses valores para verificar se o preço tocou uma linha de tendência específica, como a linha 1-4, ou a cruzou para baixo.
Se a posição for de venda, conforme o padrão de ondas de Wolfe de baixa, o código calcula a quantidade de barras transcorridas desde a abertura da operação usando Bars(_Symbol, timeframe, positionTime, TimeCurrent()). Em seguida, uma condição verifica se o mercado atingiu o ponto de saída, avaliando os seguintes critérios:
- O preço Ask atual está abaixo da linha de tendência 1-4 (t_1_4_values);
- A mínima do candle anterior (low_m[1]) rompeu essa linha de tendência;
- A quantidade de barras desde a entrada corresponde à quantidade necessária para alcançar a linha de tendência 1-4 (no_n_c_bars == no_wv1_n_bars);
- Para associar a posição ao padrão mais recente, deve-se cumprir a condição (no_n_c_bars == pos_bars + 1).
O EA utiliza essa condição para encerrar a posição quando todos os critérios são atendidos, indicando que a operação atingiu o ponto de saída esperado ou permaneceu aberta por tempo excessivo. Para isso, utiliza Ticket e PositionClose. A condição no_n_c_bars == pos_bars + 1 permite verificar se a operação aberta está corretamente associada ao padrão de ondas de Wolfe mais recente. A lógica do EA procura vários padrões de Wolfe dentro de uma quantidade predefinida de barras. No entanto, ele só executa uma operação quando time[n] == time_exe[1]. Isso garante que a entrada ocorra no momento em que o padrão mais recente é confirmado.
A variável pos_bars representa a quantidade de barras transcorridas desde a abertura da operação e é calculada para manter a correspondência entre o sinal e sua execução. Já no_n_c_bars indica quantas barras se passaram entre o momento atual e o ponto de confirmação do padrão de ondas de Wolfe (time[n]). Ao verificar a relação no_n_c_bars == pos_bars + 1, o EA identifica que a operação foi iniciada com base nesse padrão específico, e não em um padrão anterior.
Essa verificação é fundamental porque, mesmo que o EA identifique vários padrões de ondas de Wolfe no gráfico, ele deve gerenciar e encerrar apenas a operação associada à formação mais recente. Sem esse critério, o EA poderia interromper ou prejudicar inadvertidamente operações abertas com base em sinais anteriores. Ao validar essa correspondência, o EA garante o processamento correto das transações, evita conflitos entre sinais e mantém um comportamento consistente na execução das ordens e na gestão de riscos.
Identificação de padrões de ondas de Wolfe de alta
O padrão de ondas de Wolfe de alta é simplesmente o inverso do padrão de baixa que analisamos anteriormente. Como a estrutura e a lógica são muito semelhantes, não precisamos explicar novamente todos os detalhes. Em vez disso, vamos destacar apenas os aspectos que se invertem ou apresentam diferenças. Neste caso, procuramos uma estrutura de cinco ondas que indique uma possível oportunidade de compra, em vez de venda.
A onda 1, que estabelece a base inicial do padrão de Wolfe de alta, deve corresponder a um fundo de swing. Após a onda 2, que deve ser um topo de swing, a onda 3 precisa formar outro fundo de swing, sem romper o nível da onda 1. O setup de alta se completa com a formação da onda 4, um topo de swing normalmente abaixo do topo da onda 2, e da onda 5, um fundo de swing.
Os extremos das ondas 1 a 3 devem corresponder às máximas ou mínimas registradas nos respectivos trechos entre ondas consecutivas, enquanto a onda 5 precisa estar dentro da faixa de extensão de Fibonacci de 127,2% a 161,8%, calculada a partir das ondas 3 e 4. O usuário pode ajustar essas faixas para controlar a sensibilidade da detecção de padrões. Para aumentar a confiabilidade da entrada, o preço deve primeiro cair abaixo da linha de tendência que conecta as ondas 1 e 3 e, depois, voltar a ultrapassá-la. A linha entre as ondas 1 e 4 costuma ser utilizada como alvo de realização de lucro. As principais linhas de tendência, que conectam as ondas 1-3, 2-4 e 1-4, são traçadas automaticamente para facilitar a identificação do padrão e o planejamento da saída das operações.

Conclusão
Neste artigo, mostramos como desenvolver um EA em MQL5 capaz de identificar padrões de ondas de Wolfe tanto de alta quanto de baixa. Vimos como utilizar topos e fundos de swing para detectar a estrutura de cinco ondas, aplicar níveis de extensão de Fibonacci, traçar as principais linhas de tendência e abrir operações somente depois que todos os critérios forem atendidos. Embora a faixa de extensão de Fibonacci entre 127,2% e 161,8% seja considerada padrão, os usuários podem ajustar esses níveis conforme suas preferências. Além de automatizar a identificação de um padrão gráfico complexo, este projeto oferece uma base sólida para desenvolver sistemas de negociação mais avançados, fundamentados na análise de padrões.
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/18884
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.
Ferramentas de trading em MQL5 (Parte 6): Painel holográfico dinâmico com animação pulsante e controles
Automatização de estratégias de negociação em MQL5 (Parte 24): Sistema de negociação por rompimento da sessão de Londres com gerenciamento de risco e trailing stops
Desenvolvimento de ferramentas para análise de Price Action (Parte 33): Ferramenta baseada na Teoria da Amplitude das Velas
Recursos do Assistente MQL5 que você precisa conhecer (Parte 76): Uso de padrões do Awesome Oscillator e canais de envelopes com aprendizado supervisionado
- 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