English Русский 中文 Español Deutsch 日本語
preview
Introdução ao MQL5 (Parte 13): Um Guia para Iniciantes na Criação de Indicadores Personalizados (II)

Introdução ao MQL5 (Parte 13): Um Guia para Iniciantes na Criação de Indicadores Personalizados (II)

MetaTrader 5Experts |
276 2
ALGOYIN LTD
Israel Pelumi Abioye

Introdução

Bem-vindo de volta à nossa série sobre MQL5! Parte 12 desta série explorou os fundamentos da criação de indicadores personalizados em MQL5. Criamos um indicador de Média Móvel do zero, implementando sua lógica manualmente em vez de depender de funções embutidas. Em seguida, expandimos esse conhecimento transformando-o em uma Média Móvel no formato de candles, demonstrando como manipular elementos gráficos dentro de um indicador.

Com base nessa fundação, este artigo apresentará conceitos mais interessantes no desenvolvimento de indicadores. Utilizaremos uma abordagem baseada em projetos, como de costume, para garantir que você compreenda os tópicos colocando-os em prática. A criação de um indicador Heikin Ashi e o cálculo de uma Média Móvel utilizando seus dados serão os principais objetivos. Após a criação desses indicadores, desenvolveremos um Expert Advisor que incorpora os indicadores Heikin Ashi e Média Móvel. Mesmo aqueles que são novos no MQL5 poderão acompanhar, pois este é um artigo amigável para iniciantes. Para ajudá-lo a entender não apenas como a implementação funciona, mas também por que cada etapa é necessária, cada linha de código será explicada detalhadamente.

Este artigo abordará uma estratégia destinada exclusivamente a fins educacionais. Não se trata de uma estratégia de negociação que garanta sucesso nem de aconselhamento financeiro. Antes de utilizar qualquer estratégia em negociações reais, sempre teste em um ambiente sem risco.

Heikin Ashi (HA) e Média Móvel HA

Figura 1. Indicador Heikin Ashi e MA

Neste artigo, você aprenderá:

  • Como criar um indicador Heikin Ashi personalizado do zero em MQL5.
  • Utilizar dados de candles Heikin Ashi para calcular uma Média Móvel Heikin Ashi.
  • Usar a função iCustom() para acessar indicadores que não são nativos e integrar seus dados em estratégias de negociação.
  • Definir condições de entrada utilizando cruzamentos entre Heikin Ashi e Média Móvel.
  • Gerenciar risco de forma eficaz definindo níveis de stop-loss e take-profit dinamicamente com base em cálculos do Heikin Ashi.
  • Aplicar um mecanismo de trailing stop utilizando padrões de candles Heikin Ashi para proteger lucros conforme as tendências se desenvolvem.

1. Indicador Heikin Ashi

1.1. Compreendendo o Indicador Heikin Ashi

O indicador Heikin Ashi (HA) facilita a visualização de tendências. O HA utiliza uma técnica única para determinar novos valores com base em dados históricos de preço suavizados, em contraste com os gráficos de velas tradicionais, que exibem os preços exatos de abertura, máxima, mínima e fechamento para cada período. Isso ajuda os traders a filtrar o ruído e focar no que realmente importa, produzindo uma visão mais clara e compreensível dos movimentos do mercado.

Cada candle em um gráfico de velas tradicional mostra o movimento do preço durante um determinado período. Enquanto um candle verde (alta) indica que o preço fechou acima da abertura, um candle vermelho (baixa) indica o contrário. As sombras finas acima e abaixo do corpo do candle fornecem uma visão da volatilidade do mercado, mostrando os preços mais altos e mais baixos atingidos naquele período.

Mas os candles Heikin Ashi funcionam de maneira diferente. Eles utilizam um cálculo especial para suavizar as tendências em vez de representar com precisão os movimentos de preço. Candles verdes mais longos com poucas sombras indicam uma tendência de alta, facilitando a identificação e o acompanhamento do momentum positivo. De forma semelhante, candles vermelhos tornam-se mais evidentes durante uma tendência de baixa, indicando claramente movimentos negativos. Candles menores com sombras em ambas as extremidades frequentemente aparecem quando o mercado está lateralizado ou sem forte momentum, indicando hesitação ou indecisão dos traders.

O indicador HA é único porque modifica os cálculos tradicionais de candles utilizando uma técnica de média. Ele gera novos valores que produzem uma representação mais suave e consistente do movimento de preços, em vez de plotar diretamente os preços de abertura, máxima, mínima e fechamento do mercado. Ao remover o “ruído” de pequenas flutuações de preço, os traders conseguem identificar tendências com mais facilidade e tomar decisões mais assertivas.

Fechamento Heikin Ashi 

A média dos valores de abertura, máxima, mínima e fechamento do período atual é usada para determinar o preço de fechamento Heikin Ashi. Diferentemente dos candles tradicionais, que utilizam apenas o preço de fechamento, esse método fornece uma visão mais equilibrada da variação de preço.

A fórmula é:

Figura 2. Fórmula HA_Close

O fechamento Heikin Ashi suaviza as oscilações de preço ao calcular a média desses quatro valores, tornando os padrões mais visíveis.

Abertura Heikin Ashi

O preço de abertura Heikin Ashi é determinado com base no candle Heikin Ashi anterior, e não na abertura real do mercado. Ele é calculado pela média entre a abertura e o fechamento do Heikin Ashi anteriores:

Figura 3. Fórmula HA_Open

O Heikin Ashi reduz os saltos imprevisíveis comuns nos gráficos tradicionais ao criar um fluxo contínuo de movimento de preços, conectando o valor de abertura de cada novo candle ao anterior.

Máxima Heikin Ashi

O preço máximo Heikin Ashi corresponde ao maior valor atingido no período, porém considera três valores: a máxima do período atual, a abertura Heikin Ashi e o fechamento Heikin Ashi, em vez de apenas a máxima real do mercado. Desses três valores, seleciona-se o maior:Figura 4.

Figura 4. Fórmula HA_High

Mínima Heikin Ashi

De forma semelhante, o preço mínimo Heikin Ashi é calculado selecionando o menor valor entre o fechamento Heikin Ashi, a abertura Heikin Ashi e a mínima real do período:

Figura 5. Fórmula HA_Low

Essa abordagem mantém a consistência com os métodos de suavização, ao mesmo tempo em que garante que a mínima Heikin Ashi capture o ponto mais baixo da variação de preço. O Heikin Ashi elimina pequenas oscilações e fornece uma visão mais precisa da direção do mercado ao empregar esses cálculos. Utilizaremos esse raciocínio para construir nosso próprio indicador Heikin Ashi em MQL5 na próxima parte.

1.2. Benefícios de usar Heikin Ashi

Como é capaz de eliminar pequenas variações de preço, o indicador Heikin Ashi é muito utilizado por traders, pois facilita significativamente a identificação de tendências. Gráficos de candles tradicionais podem ser difíceis de interpretar devido às rápidas mudanças de cor, frequentemente deixando os traders em dúvida sobre se o mercado está em alta ou em baixa. Ao utilizar dados de preço suavizados por médias, o Heikin Ashi resolve esse problema e ajuda a evitar a análise excessiva de detalhes irrelevantes.

Uma sequência de candles vermelhos indica uma tendência de baixa, enquanto uma sequência de candles verdes normalmente indica uma forte tendência de alta. Essa clareza facilita a distinção entre mudanças reais e duradouras no mercado e quedas momentâneas. O Heikin Ashi ajuda a reduzir sinais falsos, evitando operações desnecessárias causadas por oscilações de curto prazo. Ao utilizar dados históricos, ele filtra o ruído do mercado, oferecendo uma confirmação de tendência mais confiável. Muitos traders o combinam com ferramentas como RSI ou Médias Móveis para aprimorar suas estratégias. Com uma visualização mais clara da ação do preço, o Heikin Ashi facilita a decisão de quando entrar ou sair de operações.

1.3. Implementando Heikin Ashi em MQL5

Implementar o indicador Heikin Ashi em MQL5 é o próximo passo após compreender seu funcionamento. Construiremos nosso próprio indicador Heikin Ashi do zero, pois o MetaTrader 5 não possui um nativo. Para isso, as fórmulas do Heikin Ashi devem ser codificadas, aplicadas aos dados de preço e o indicador deve ser exibido no gráfico.

Como de costume, o desenvolvimento de um programa começa com a elaboração de um pseudocódigo que descreve a lógica antes de iniciarmos a escrita do código. Isso garante que compreendamos cada etapa antes de implementar o programa e nos ajuda a estruturá-lo adequadamente.

Pseudocódigo:

CONFIGURAR INDICADOR

  • Definir o indicador para ser plotado em uma janela separada do gráfico.
  • Configurações de plotagem para os candles Heikin Ashi
  • Definir 4 buffers para armazenar os valores do Heikin Ashi (Open, High, Low, Close).
DEFINIR BUFFERS

Criar buffers para armazenar os valores calculados para:

  • Abertura Heikin Ashi
  • Máxima Heikin Ashi
  • Mínima Heikin Ashi
  • Fechamento Heikin Ashi

CALCULAR VALORES HEIKIN ASHI 

Percorrer os dados históricos de preço para calcular os valores do Heikin Ashi utilizando as fórmulas:

  • HA Close = (Open + High + Low + Close) / 4
  • HA Open = (HA Open anterior + HA Close anterior) / 2
  • HA High = Máximo entre (High, HA Open, HA Close)
  • HA Low = Mínimo entre (Low, HA Open, HA Close)

1.3.1. Criação e Personalização do Heikin Ashi

Agora devemos avançar para a programação após a criação do pseudocódigo. Como foi abordado no artigo anterior, o primeiro passo ao projetar e modificar um indicador é visualizar como ele deve aparecer no gráfico. A plotagem do indicador, a exibição dos candles Heikin Ashi e a inclusão de quaisquer outros componentes, como cores para tendências de alta e baixa, devem ser definidos antes da criação de qualquer código.

Devemos garantir que nosso indicador personalizado substitua corretamente os valores dos candles tradicionais pelos seus próprios valores calculados, já que o Heikin Ashi altera a aparência dos candles. Isso envolve configurar buffers para os preços de abertura, máxima, mínima e fechamento, além de garantir que as cores mudem dinamicamente para representar tanto tendências de alta quanto de baixa. Podemos definir a estrutura do indicador e começar a escrever o código assim que tivermos essa visualização clara. Precisamos definir as propriedades do indicador Heikin Ashi antes de aplicar sua lógica. Esses parâmetros determinam o estilo dos elementos plotados (como os candles Heikin Ashi), o número de buffers que o indicador utilizará e como ele será exibido no gráfico.

Exemplo:

// PROPERTY SETTINGS
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1

// PLOT SETTINGS FOR HEIKIN ASHI CANDLES
#property indicator_label1  "Heikin Ashi"
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrGreen, clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

Explicação:

Configurações de Propriedade
#property indicator_separate_window

Isso instrui o MetaTrader 5 a exibir o indicador em uma janela diferente, em vez de sobrepô-lo ao gráfico principal. Essa linha seria removida caso quiséssemos que ele aparecesse diretamente no gráfico de preços.

Analogia

Considere seu gráfico de trading como uma estação de trabalho onde você analisa as mudanças do mercado. Ferramentas essenciais, como candles de preço e indicadores tradicionais, ficam no gráfico principal, que funciona como uma mesa de trabalho. Agora, imagine que você está trabalhando em um projeto paralelo detalhado que precisa de um espaço específico, como um pequeno quadro branco ao lado da sua mesa. Ao mover essa atividade específica para o quadro branco, você pode se concentrar nela de forma independente, sem sobrecarregar o espaço principal.

Da mesma forma, #property indicator_separate_window move o indicador Heikin Ashi para sua própria janela em vez de sobrepô-lo ao gráfico principal, facilitando a análise de tendências sem interferir nos dados padrão de candles.

#property indicator_buffers 5

Isso especifica quantos buffers o indicador utilizará. Neste caso, estão sendo utilizados cinco buffers: um para representação de cores e os outros para armazenar os valores calculados do Heikin Ashi (Open, High, Low e Close).

Analogia

Agora que você tem um quadro branco separado ao lado da sua mesa de trabalho para seu projeto paralelo, imagine que precisa de cinco bandejas diferentes para organizar seu trabalho. Esboços, medições, anotações e outros elementos são armazenados em bandejas separadas. Isso mantém tudo organizado para que você possa acessar rapidamente as informações relevantes quando necessário.

Assim como essas bandejas, #property indicator_buffers 5 garante que diferentes pontos de dados do Heikin Ashi sejam mantidos separados. Aqui, temos cinco buffers: um para representação de cores e quatro para os valores Heikin Ashi (Open, High, Low e Close). Esses buffers mantêm os cálculos do indicador organizados, facilitando a exibição dos dados corretos no gráfico, da mesma forma que as bandejas mantêm seu espaço de trabalho organizado.

#property indicator_plots 1

Isso indica quantos gráficos (plots) o indicador exibirá. Precisamos de apenas um plot, pois estamos desenhando os candles Heikin Ashi como uma única unidade.

Analogia

Após organizar seus materiais em bandejas distintas e configurar seu espaço de trabalho no quadro branco, o próximo passo é decidir como exibir seu trabalho. Em vez de criar vários gráficos separados, imagine que você está criando um único diagrama abrangente que unifica todos os dados em uma representação visual clara e compreensível.

Da mesma forma, #property indicator_plots 1 informa ao MetaTrader 5 que o indicador Heikin Ashi será exibido como um único elemento plotado. Assim como no seu diagrama único no quadro branco, vários buffers armazenam dados distintos (Open, High, Low, Close e cor), mas todos se combinam para formar um único conjunto de candles. Precisamos de apenas um plot para exibir os candles Heikin Ashi no gráfico, pois estamos apenas plotando esse conjunto.

Configurações de Plot

#property indicator_label1  "Heikin Ashi"
#property indicator_type1   DRAW_COLOR_CANDLES  
#property indicator_color1  clrGreen, clrRed    
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

Analogia

Depois de organizar seus materiais e preparar seu espaço de trabalho, é importante apresentar suas conclusões de forma clara e compreensível. Para tornar as tendências mais evidentes, você opta por usar símbolos codificados por cores em vez de texto simples ou representações abstratas. Você identifica claramente seu diagrama rotulando-o como "Heikin Ashi", facilitando o entendimento de qualquer pessoa que observe o quadro. Da mesma forma, #property indicator_label1 "Heikin Ashi" atribui um nome ao indicador e garante que ele apareça na lista de indicadores do MetaTrader 5. Dessa forma, os traders podem identificá-lo rapidamente em seus gráficos entre outros indicadores.

#property indicator_type1 DRAW_COLOR_CANDLES instrui o MetaTrader 5 a usar candles coloridos em vez de linhas ou histogramas. As cores são definidas por #property indicator_color1 clrGreen, clrRed, onde verde representa candles de alta e vermelho representa candles de baixa. Essa clareza visual facilita a identificação de tendências rapidamente. Para manter seu quadro organizado e legível, você decide usar traços sólidos em vez de linhas tracejadas ou pontilhadas.

Da mesma forma, #property indicator_style1 STYLE_SOLID garante que os candles Heikin Ashi sejam preenchidos com uma cor sólida, tornando-os visualmente distintos. Por fim, assim como você evita deixar suas linhas muito grossas para não poluir o diagrama, #property indicator_width1 1 mantém a largura dos contornos dos candles adequada para clareza, sem sobrecarregar o gráfico.Ao configurar o indicador Heikin Ashi dessa forma, criamos uma representação clara, estruturada e visualmente intuitiva das tendências de mercado, assim como um quadro bem organizado facilita a compreensão de um projeto

Agora que definimos as propriedades do indicador e as configurações de plotagem, o próximo passo é definir os buffers que armazenarão os preços dos candles Heikin Ashi. Os buffers funcionam como contêineres de armazenamento para os valores calculados do indicador, permitindo que o MetaTrader 5 os exiba no gráfico. Neste caso, precisamos de buffers para armazenar os preços de abertura, máxima, mínima e fechamento do Heikin Ashi, além de um buffer adicional para representar as cores. Também definiremos seus respectivos índices para garantir que cada buffer corresponda corretamente aos dados desejados.

Exemplo:

// PROPERTY SETTINGS
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1

// PLOT SETTINGS FOR HEIKIN ASHI CANDLES
#property indicator_label1  "Heikin Ashi"
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrGreen, clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

// INDICATOR BUFFERS
double HA_Open[];
double HA_High[];
double HA_Low[];
double HA_Close[];
double ColorBuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
// SET BUFFERS
   SetIndexBuffer(0, HA_Open, INDICATOR_DATA);
   SetIndexBuffer(1, HA_High, INDICATOR_DATA);
   SetIndexBuffer(2, HA_Low, INDICATOR_DATA);
   SetIndexBuffer(3, HA_Close, INDICATOR_DATA);
   SetIndexBuffer(4, ColorBuffer, INDICATOR_COLOR_INDEX);

   return INIT_SUCCEEDED;
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {

   return(rates_total);

  }

Explicação:

Construímos arrays (buffers) que armazenam os preços de abertura, máxima, mínima e fechamento dos candles modificados para guardar os valores calculados do indicador Heikin Ashi. Também controlamos a cor de cada candle utilizando um buffer separado.

double HA_Open[];
double HA_High[];
double HA_Low[];
double HA_Close[];
double ColorBuffer[];

O buffer HA_Open[] contém o preço de abertura Heikin Ashi de cada candle, enquanto HA_High[] armazena o maior preço do candle Heikin Ashi. Da mesma forma, HA_Close[] contém o preço de fechamento e HA_Low[] registra o menor preço. Além disso, o ColorBuffer[] é utilizado para definir a cor de cada candle, distinguindo entre candles de alta (verde) e de baixa (vermelho). Esses buffers trabalham em conjunto para permitir que o gráfico armazene e exiba os candles Heikin Ashi atualizados.

SetIndexBuffer(0, HA_Open, INDICATOR_DATA);
SetIndexBuffer(1, HA_High, INDICATOR_DATA);
SetIndexBuffer(2, HA_Low, INDICATOR_DATA);
SetIndexBuffer(3, HA_Close, INDICATOR_DATA);
SetIndexBuffer(4, ColorBuffer, INDICATOR_COLOR_INDEX);     

A função SetIndexBuffer no MetaTrader 5 conecta buffers específicos aos seus respectivos índices, garantindo que os dados do Heikin Ashi sejam processados e exibidos corretamente. De acordo com a estrutura de candles da plataforma, o preço de abertura é sempre atribuído ao índice 0, enquanto os valores de máxima, mínima e fechamento são mapeados para os índices 1, 2 e 3. Na ausência de uma indexação adequada, o MetaTrader 5 pode não reconhecer os dados como candles válidos, o que pode resultar em elementos ausentes no gráfico ou problemas de exibição.

SetIndexBuffer(4, ColorBuffer, INDICATOR_COLOR_INDEX) define a cor de cada candle, indicando movimentos de alta (verde) ou de baixa (vermelho), permitindo diferenciar visualmente as tendências. Ao indexar corretamente esses buffers, o indicador Heikin Ashi garante uma representação precisa dos preços e do estilo visual, permitindo que os traders analisem tendências rapidamente e tomem decisões bem fundamentadas.

Agora devemos realizar os cálculos que geram os valores do Heikin Ashi após configurar as propriedades do indicador, definir os buffers e conectá-los aos índices apropriados.

Exemplo:

// PROPERTY SETTINGS
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1

// PLOT SETTINGS FOR HEIKIN ASHI CANDLES
#property indicator_label1  "Heikin Ashi"
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrGreen, clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

// INDICATOR BUFFERS
double HA_Open[];
double HA_High[];
double HA_Low[];
double HA_Close[];
double ColorBuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
// SET BUFFERS
   SetIndexBuffer(0, HA_Open, INDICATOR_DATA);
   SetIndexBuffer(1, HA_High, INDICATOR_DATA);
   SetIndexBuffer(2, HA_Low, INDICATOR_DATA);
   SetIndexBuffer(3, HA_Close, INDICATOR_DATA);
   SetIndexBuffer(4, ColorBuffer, INDICATOR_COLOR_INDEX);

   return INIT_SUCCEEDED;
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {

   if(rates_total < 2)
      return 0; // ENSURE ENOUGH DATA

   for(int i = 1; i < rates_total; i++)  // START FROM SECOND BAR
     {
      // HEIKIN ASHI CLOSE FORMULA
      HA_Close[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0;

      // HEIKIN ASHI OPEN FORMULA
      HA_Open[i] = (HA_Open[i - 1] + HA_Close[i - 1]) / 2.0;

      // HEIKIN ASHI HIGH FORMULA
      HA_High[i] = MathMax(high[i], MathMax(HA_Open[i], HA_Close[i]));

      // HEIKIN ASHI LOW FORMULA
      HA_Low[i] = MathMin(low[i], MathMin(HA_Open[i], HA_Close[i]));

      // SET COLOR: GREEN FOR BULLISH, RED FOR BEARISH
      ColorBuffer[i] = (HA_Close[i] >= HA_Open[i]) ? 0 : 1;
     }

   return(rates_total);

  }

Como a primeira barra não possui dados anteriores, esse processo calcula os valores Heikin Ashi a partir da segunda barra. Para suavizar as oscilações de preço, o preço de fechamento é calculado como a média dos valores de abertura, máxima, mínima e fechamento da barra atual. O preço de abertura garante transições suaves ao calcular a média entre a abertura e o fechamento Heikin Ashi da barra anterior. Os preços máximo e mínimo são determinados como os maiores e menores valores entre a máxima/mínima da barra atual e os valores de abertura/fechamento Heikin Ashi. Por fim, os candles são coloridos de vermelho (baixa) ou verde (alta) caso o fechamento seja menor ou igual à abertura. Isso ajuda os traders a visualizar tendências ao reduzir o ruído do mercado.

Figura 6. Indicador HA


2. Criando uma Média Móvel a partir dos Dados Heikin Ashi

Agora que geramos com sucesso os candles Heikin Ashi, o próximo passo é criar uma Média Móvel (MA) com base nos valores do Heikin Ashi, em vez de utilizar dados de preço padrão.

Pseudocódigo:

MODIFICAR PROPRIEDADES DO INDICADOR

  • Ajustar a quantidade de buffers de cinco para seis para acomodar a Média Móvel Heikin Ashi. 

  • Alterar o número de plots de 1 para 2 para que os candles e a Média Móvel Heikin Ashi possam ser exibidos juntos.

DEFINIR BUFFER PARA A MÉDIA MÓVEL HEIKIN ASHI

  • Criar um buffer para armazenar os valores da Média Móvel Heikin Ashi.
  • Definir uma variável de entrada para o período da Média Móvel (por exemplo, 20).

CONFIGURAR BUFFER PARA A MÉDIA MÓVEL HEIKIN ASHI

  • Associar o buffer a um índice para armazenar os valores calculados da MA.
  • Definir o índice do plot para iniciar no período da Média Móvel, garantindo uma exibição correta.

CALCULAR MÉDIA MÓVEL HEIKIN ASHI

  • Iniciar o loop a partir de (período - 1) para garantir dados suficientes.
  • Calcular a soma dos últimos 'n' valores de fechamento Heikin Ashi.
  • Dividir a soma pelo período e armazenar o resultado no buffer.

Exemplo:

// PROPERTY SETTINGS
#property indicator_separate_window
#property indicator_buffers 6
#property indicator_plots   2

// PLOT SETTINGS FOR HEIKIN ASHI CANDLES
#property indicator_label1  "Heikin Ashi"
#property indicator_type1   DRAW_COLOR_CANDLES  
#property indicator_color1  clrGreen, clrRed    
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//PROPERTIES OF THE Heikin MA
#property indicator_label2  "Heikin MA"   
#property indicator_type2   DRAW_LINE  
#property indicator_style2  STYLE_DASH 
#property indicator_width2  1          
#property indicator_color2  clrBrown   

// INDICATOR BUFFERS
double HA_Open[];
double HA_High[];
double HA_Low[];
double HA_Close[];
double ColorBuffer[]; 

double Heikin_MA_Buffer[];
int input  heikin_ma_period = 20;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
    // SET BUFFERS
    SetIndexBuffer(0, HA_Open, INDICATOR_DATA);
    SetIndexBuffer(1, HA_High, INDICATOR_DATA);
    SetIndexBuffer(2, HA_Low, INDICATOR_DATA);
    SetIndexBuffer(3, HA_Close, INDICATOR_DATA);
    SetIndexBuffer(4, ColorBuffer, INDICATOR_COLOR_INDEX);
    
    SetIndexBuffer(5, Heikin_MA_Buffer, INDICATOR_DATA);  
    PlotIndexSetInteger(5, PLOT_DRAW_BEGIN, heikin_ma_period);
     
    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
    if (rates_total < 2) return 0; // ENSURE ENOUGH DATA
      
    for (int i = 1; i < rates_total; i++) // START FROM SECOND BAR
    {
        // HEIKIN ASHI CLOSE FORMULA
        HA_Close[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0;

        // HEIKIN ASHI OPEN FORMULA
        HA_Open[i] = (HA_Open[i - 1] + HA_Close[i - 1]) / 2.0;

        // HEIKIN ASHI HIGH FORMULA
        HA_High[i] = MathMax(high[i], MathMax(HA_Open[i], HA_Close[i]));

        // HEIKIN ASHI LOW FORMULA
        HA_Low[i] = MathMin(low[i], MathMin(HA_Open[i], HA_Close[i]));

        // SET COLOR: GREEN FOR BULLISH, RED FOR BEARISH
        ColorBuffer[i] = (HA_Close[i] >= HA_Open[i]) ? 0 : 1;
    }    
    
     for(int i = heikin_ma_period - 1; i < rates_total; i++)
     {

      double sum = 0.0;
      for(int j = 0; j < heikin_ma_period; j++)
        {
         sum += HA_Close[i - j];
        }

      Heikin_MA_Buffer[i] = sum / heikin_ma_period;

     }

    return rates_total;
}

Explicação:

Primeiramente, devemos modificar as configurações de buffers e plots para incorporar a Média Móvel Heikin Ashi (HA MA) ao indicador. Utilizando #property indicator_buffers 6, o número de buffers é aumentado de 5 para 6, garantindo espaço adicional para armazenar os dados da Heikin MA. Os candles Heikin Ashi e a Heikin MA podem ser exibidos simultaneamente no gráfico ao usar #property indicator_plots 2 para alterar o número de plots de 1 para 2. Isso garante que o indicador possa gerenciar eficientemente ambos os conjuntos de dados.

Em seguida, as propriedades do plot da Heikin MA são configuradas. #property indicator_label2 é o rótulo. Ao atribuir um nome à Média Móvel, "Heikin MA" torna-a visível na lista de indicadores. Para definir que a Média Móvel será exibida como uma linha em vez de candles, o tipo é configurado com #property indicator_type2 DRAW_LINE. Definimos #property indicator_style2 STYLE_DASH para tornar a linha tracejada e utilizamos #property indicator_width2 1 para determinar sua largura, aumentando a visibilidade. Usando #property indicator_color2 clrBrown, a cor é definida como marrom, garantindo um contraste forte com os candles Heikin Ashi.

Após configurar as propriedades, definimos um parâmetro de entrada int input heikin_ma_period = 20; que permite aos usuários alterar o período e declaramos um array double Heikin_MA_Buffer[]; para armazenar os dados da Média Móvel. SetIndexBuffer(5, Heikin_MA_Buffer, INDICATOR_DATA); é utilizado para vincular o buffer ao indicador, permitindo que o MetaTrader 5 gerencie e exiba os valores corretamente. PlotIndexSetInteger(5, PLOT_DRAW_BEGIN, heikin_ma_period); também garante que a Média Móvel seja plotada apenas após haver barras suficientes disponíveis.

Calcular a Média Móvel Heikin Ashi é a etapa final. Para garantir que haja dados suficientes para o cálculo, o loop começa em heikin_ma_period - 1. A Média Móvel é calculada dentro do loop somando os últimos n valores de fechamento Heikin Ashi e dividindo o total pelo período. O indicador então plota a Média Móvel junto com os candles Heikin Ashi após armazenar o resultado em Heikin_MA_Buffer[i], fornecendo aos traders uma ferramenta suavizada de acompanhamento de tendência.

Figura 7. Indicador HA e HA MA


3. Integrando um Indicador Personalizado em um Expert Advisor

Você pode estar se perguntando: agora que criamos um indicador personalizado, como podemos utilizá-lo para criar um Expert Advisor? Usando o indicador Heikin Ashi criado no capítulo anterior, continuaremos nossa abordagem baseada em projetos e desenvolveremos um EA nesta etapa. Nossa técnica será transformada em um robô de trading funcional, já que este EA utilizará sinais do Heikin Ashi para automatizar decisões de negociação.

Uma estratégia simples de cruzamento baseada na Média Móvel Heikin Ashi (HA MA) e nos candles Heikin Ashi (HA) será utilizada como estratégia de trading. Essa abordagem ajuda a identificar possíveis reversões de tendência e sinais de continuação ao analisar a relação entre o preço de fechamento do candle Heikin Ashi e a Média Móvel Heikin Ashi. Uma tendência de alta e uma possível oportunidade de compra são indicadas quando um candle Heikin Ashi fecha acima da Média Móvel Heikin Ashi. Por outro lado, quando um candle Heikin Ashi fecha abaixo da Média Móvel Heikin Ashi, é gerado um sinal de venda, indicando uma possível reversão de baixa e uma oportunidade de venda.

Figura 8. Lógica de Compra e Venda

3.1. Recuperando Dados do Indicador

A primeira coisa a considerar ao integrar um indicador personalizado em um EA é como obter os dados desse indicador dentro do EA. O EA não consegue basear suas decisões de trading no indicador se seus valores não estiverem acessíveis. Por exemplo, os quatro valores que compõem um candle Heikin Ashi devem ser importados para nossa estratégia de cruzamento com Média Móvel:

  • Preço de abertura HA
  • Preço máximo HA
  • Preço mínimo HA
  • Preço de fechamento HA

Esses parâmetros são a base dos nossos sinais de trading e serão utilizados para determinar se um candle Heikin Ashi cruzou acima ou abaixo da HA MA.

Exemplo:

// Declare arrays to store Heikin Ashi data from the custom indicator
double heikin_open[];   // Stores Heikin Ashi Open prices
double heikin_close[];  // Stores Heikin Ashi Close prices
double heikin_low[];    // Stores Heikin Ashi Low prices
double heikin_high[];   // Stores Heikin Ashi High prices
double heikin_ma[];     // Stores Heikin Ashi Moving Average values

int heikin_handle;      // Handle for the custom Heikin Ashi indicator

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
// Ensure arrays store data in a time series format (most recent data first)
   ArraySetAsSeries(heikin_open, true);
   ArraySetAsSeries(heikin_close, true);
   ArraySetAsSeries(heikin_low, true);
   ArraySetAsSeries(heikin_high, true);
   ArraySetAsSeries(heikin_ma, true);

// Load the custom Heikin Ashi indicator and get its handle
   heikin_handle = iCustom(_Symbol, PERIOD_CURRENT, "Project7 Heikin Ashi Indicator.ex5");

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
// Nothing to clean up in this case, but can be used for resource management if needed
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
// Copy the latest 3 values of each buffer from the Heikin Ashi indicator
   CopyBuffer(heikin_handle, 0, 0, 3, heikin_open);  // Get HA Open values
   CopyBuffer(heikin_handle, 1, 0, 3, heikin_high);  // Get HA High values
   CopyBuffer(heikin_handle, 2, 0, 3, heikin_low);   // Get HA Low values
   CopyBuffer(heikin_handle, 3, 0, 3, heikin_close); // Get HA Close values
   CopyBuffer(heikin_handle, 5, 0, 3, heikin_ma);    // Get HA Moving Average values

// Print index 0 values to the terminal
   Print("HA Open: ", heikin_open[0],
         "\nHA High: ", heikin_high[0],
         "\nHA Low: ", heikin_low[0],
         "\nHA Close: ", heikin_close[0],
         "\nHA MA: ", heikin_ma[0]);
  }

Explicação:

Declarando Arrays para Armazenar Dados Heikin Ashi

Declarar arrays para armazenar os dados coletados do indicador é o primeiro passo na integração de um indicador personalizado em um Expert Advisor (EA). Neste caso, cinco arrays são declarados para armazenar os diferentes componentes do indicador Heikin Ashi:

  • heikin_open[]: Armazena os preços de abertura Heikin Ashi.
  • heikin_close[]: Armazena os preços de fechamento Heikin Ashi.
  • heikin_low[]: Armazena os preços mínimos Heikin Ashi.
  • heikin_high[]: Armazena os preços máximos Heikin Ashi.
  • heikin_ma[]: Armazena os valores da Média Móvel Heikin Ashi.

Esses arrays são essenciais porque fornecem ao EA acesso tanto aos valores atuais quanto aos históricos do Heikin Ashi. Ao armazenar esses dados, o EA pode avaliar movimentos históricos de preço e ajustar suas decisões de trading. Esses arrays não precisam ser inicializados com valores fixos, pois serão preenchidos com dados do indicador personalizado e atualizados dinamicamente conforme novos dados se tornam disponíveis.

Declarando o Handle do Indicador

O handle do indicador Heikin Ashi personalizado é armazenado na variável heikin_handle. Um handle em MQL5 é uma referência única para uma instância de indicador em execução em segundo plano. Esse handle é essencial porque permite que o EA interaja com o indicador e solicite dados quando necessário. Sem um handle, o EA não teria acesso aos valores do Heikin Ashi. Posteriormente, quando a função iCustom() for executada, um valor será atribuído ao handle. Se o handle for inválido (retornar -1), isso significa que o indicador não foi carregado corretamente, impedindo o EA de recuperar os dados necessários.

Inicialização de Arrays no Formato de Série Temporal

Os arrays devem ser configurados para que os dados mais recentes estejam sempre no índice 0 quando forem declarados. Para isso, utiliza-se a função ArraySetAsSeries(), que organiza os elementos do array em ordem decrescente, mantendo os dados mais recentes primeiro.

A função é aplicada a cada um dos cinco arrays da seguinte forma:

 ArraySetAsSeries(heikin_open, true);
 ArraySetAsSeries(heikin_close, true);
 ArraySetAsSeries(heikin_low, true);
 ArraySetAsSeries(heikin_high, true);
 ArraySetAsSeries(heikin_ma, true);

Ao converter esses arrays para o formato de série temporal, o índice 0 sempre conterá os dados mais recentes do Heikin Ashi. Isso é especialmente útil na implementação de estratégias de trading, pois garante que o EA reaja aos movimentos atuais do mercado em vez de dados antigos.

Carregando o Indicador Heikin Ashi Personalizado com iCustom()

Para integrar um indicador personalizado em um Expert Advisor (EA), precisamos de uma forma de acessar seus dados. A função iCustom() permite carregar um indicador personalizado e obter um handle que o EA pode usar para solicitar valores do indicador. Sem esse handle, o EA não conseguiria acessar os dados do indicador.

heikin_handle = iCustom(_Symbol, PERIOD_CURRENT, "Project7 Heikin Ashi Indicator.ex5");

  • _Symbol: Indica que o indicador será aplicado ao símbolo de negociação atual (por exemplo, EUR/USD, GBP/JPY, etc.). Isso garante que o indicador processe dados do mesmo ativo em que o EA está sendo executado.
  • PERIOD_CURRENT: Aplica o indicador ao mesmo timeframe do EA. Se o EA estiver rodando em um gráfico H1, o indicador também será aplicado ao H1.
  • "Project7 Heikin Ashi Indicator.ex5": Especifica o nome do arquivo do indicador personalizado que o EA deve utilizar. A extensão .ex5 indica que se trata de um arquivo compilado de indicador MQL5.

É essencial garantir que o arquivo do indicador esteja no diretório correto do MetaTrader 5. O indicador deve estar na pasta Indicators dentro do diretório MQL5. O caminho completo desse diretório é:

A função iCustom() é, em resumo, o principal mecanismo que conecta um indicador personalizado a um EA. Ela fornece ao EA um handle que permite a extração dinâmica dos valores do indicador. A função não funcionará corretamente se o indicador não estiver localizado adequadamente no diretório Indicators (ou em uma subpasta dentro dele).

Copiando Dados do Indicador para os Arrays

Após obter o handle, o EA pode recuperar os valores mais recentes do Heikin Ashi utilizando a função CopyBuffer(). A função CopyBuffer() copia dados dos buffers internos do indicador para os arrays do EA. Neste EA, a função é chamada cinco vezes, uma para cada tipo de dado:

CopyBuffer(heikin_handle, 0, 0, 3, heikin_open);  // Get HA Open values
CopyBuffer(heikin_handle, 1, 0, 3, heikin_high);  // Get HA High values
CopyBuffer(heikin_handle, 2, 0, 3, heikin_low);   // Get HA Low values
CopyBuffer(heikin_handle, 3, 0, 3, heikin_close); // Get HA Close values
CopyBuffer(heikin_handle, 5, 0, 3, heikin_ma);    // Get HA Moving Average values

Os dados são recuperados do indicador personalizado usando a mesma estrutura em cada chamada de CopyBuffer(). O primeiro parâmetro é o handle obtido com iCustom(), chamado heikin_handle. Esse handle permite que o EA acesse os dados do indicador Heikin Ashi personalizado. Sem ele, o EA não conseguiria solicitar os valores do indicador.Os parâmetros seguintes (0, 1, 2, 3, 5) representam os índices dos buffers dos diferentes componentes do indicador Heikin Ashi. Em MQL5, os indicadores utilizam buffers para armazenar seus dados, e cada buffer possui um índice único. Neste caso, o índice 0 representa o preço de abertura Heikin Ashi, o índice 1 a máxima, o índice 2 a mínima, o índice 3 o fechamento e o índice 5 a Média Móvel Heikin Ashi. Ao especificar esses índices, garantimos que os dados corretos sejam recuperados do indicador.

O terceiro parâmetro, 0, indica que a cópia dos dados deve começar a partir da barra mais recente (candle atual). Isso garante que o EA utilize sempre os dados mais atualizados do mercado, essenciais para decisões em tempo real. O quarto parâmetro, 3, indica que três pontos de dados devem ser copiados. A obtenção de múltiplos valores permite que o EA analise tanto dados atuais quanto históricos do Heikin Ashi, o que é útil para identificar padrões ou confirmar tendências. 

Por fim, os dados recuperados são armazenados nos arrays correspondentes — heikin_open, heikin_high, heikin_low, heikin_close e heikin_ma. Os valores obtidos são armazenados nessas matrizes para que o EA possa processá-los e utilizá-los em sua lógica de negociação. Para que o EA tome decisões bem fundamentadas com base nas tendências de preço, é essencial que ele tenha acesso a dados atualizados do indicador Heikin Ashi.

3.2. Utilizando os Dados do Indicador na Estratégia de Trading

Após aprender como extrair dados do indicador personalizado, agora precisamos entender como aplicar esses dados à nossa estratégia de trading. Isso nos permitirá utilizar o indicador Heikin Ashi de forma eficaz dentro de um EA e demonstrar como tomar decisões com base nos valores obtidos. Além disso, esse processo oferece uma oportunidade de explorar conceitos importantes do MQL5, aprofundando nossa compreensão ao longo do estudo. 

No entanto, não podemos simplesmente aplicar a lógica sem considerar elementos essenciais do EA. A gestão adequada de operações exige a incorporação de funcionalidades específicas. Isso inclui monitorar a quantidade de posições abertas, implementar trailing stops, controlar parâmetros de risco e garantir que o EA execute as operações de forma estruturada. Ao incluir esses elementos essenciais, construímos um sistema de trading mais confiável e eficaz, capaz de operar em um ambiente real.

3.2.1. Rastreamento de Posições de Compra e Venda Abertas no Expert Advisor

Para que a estratégia funcione corretamente, devemos garantir que apenas uma posição de compra e uma de venda estejam abertas ao mesmo tempo. Isso reduz riscos desnecessários provenientes de múltiplas posições na mesma direção e ajuda a manter o controle da execução das operações. Ao monitorar o número de posições abertas, o EA pode decidir se deve abrir uma nova posição ou aguardar o fechamento de uma existente antes de executar outra. Esse método garante que a estratégia opere conforme planejado e melhora a gestão de posições.

Exemplo:

int totalPositions = 0;
int position_type_buy = 0;
int position_type_sell = 0;

for(int i = 0; i < PositionsTotal(); i++)
  {
   ulong ticket = PositionGetTicket(i);

   if(PositionSelectByTicket(ticket))
     {
      if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetString(POSITION_SYMBOL) == ChartSymbol(ChartID())
     {
      totalPositions++;
      if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
           {
            position_type_buy++;
           }
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
           {
            position_type_sell++;
           }
        }
     }
  }

O EA conta o número de operações de compra, venda e o total de trades para acompanhar as posições abertas. Ele percorre as posições abertas, classifica-as como compra ou venda e utiliza o número mágico (Magic Number) e o símbolo do gráfico para confirmar que pertencem à estratégia. Ao permitir apenas uma operação de compra e uma de venda por vez, garante-se um gerenciamento de posições controlado.

3.2.2. Rastreamento do Limite Diário de Operações no Expert Advisor

O foco desta seção é o total de operações realizadas durante uma sessão de trading. O Expert Advisor garante que a estratégia não ultrapasse o limite diário de operações ao definir um intervalo de tempo específico e contabilizar operações de compra e venda. Essa abordagem ajuda a manter um comportamento disciplinado, evitando excesso de operações no período definido.

Exemplo:

input int daily_trades = 6; // Total Daily Trades

// Start and end time for
string start = "00:00";
string end = "23:50";

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

   datetime start_time = StringToTime(start);
   datetime end_time = StringToTime(end);
   bool success = HistorySelect(start_time, end_time);

// Getting total trades
   int totalDeal = 0;
   int deal_type_buy = 0;
   int deal_type_sell = 0;
   if(success)
     {
      for(int i = 0; i < HistoryDealsTotal(); i++)
        {
         ulong ticket = HistoryDealGetTicket(i);

         if(HistoryDealGetInteger(ticket, DEAL_MAGIC) == MagicNumber && HistoryDealGetString(ticket,DEAL_SYMBOL) == ChartSymbol(chart_id))
           {
            if(HistoryDealGetInteger(ticket, DEAL_ENTRY) == DEAL_ENTRY_IN)
              {
               totalDeal++;
               if(HistoryDealGetInteger(ticket, DEAL_TYPE) == DEAL_TYPE_BUY)
                 {

                  deal_type_buy++;

                 }
               if(HistoryDealGetInteger(ticket, DEAL_TYPE) == DEAL_TYPE_SELL)
                 {

                  deal_type_sell++;

                 }
              }
           }
        }
     }
  }

Explicação:

Inicialmente, o EA converte os horários de início e fim especificados para o formato datetime, a fim de monitorar o total de operações realizadas durante a sessão. Em seguida, utiliza a função HistorySelect() para selecionar o histórico de trades dentro desse intervalo. Se a seleção for bem-sucedida, o EA inicializa contadores para registrar o número total de operações executadas, bem como a quantidade de compras e vendas separadamente.

O EA então percorre o histórico de trades, extraindo o número de ticket de cada operação. Para garantir que apenas operações relevantes sejam contabilizadas, verifica se o trade foi aberto utilizando o mesmo Magic Number e símbolo do gráfico atual. Se a operação for identificada como uma entrada, o contador total de trades é incrementado. Após determinar o tipo da operação, o EA atualiza os contadores correspondentes. Isso assegura que a estratégia monitore corretamente as operações executadas e não ultrapasse o limite diário definido.

3.2.3. Prevenção de Operações Repetidas no Mesmo Candle

Em alguns casos, o EA pode abrir uma nova negociação imediatamente após o fechamento de uma posição existente, caso você queira que novas negociações sejam concluídas somente ao preço de abertura de uma nova barra. Isso é especialmente verdade se as condições de negociação permanecerem as mesmas. Isso pode resultar em negociações consecutivas não intencionais dentro do mesmo candle. Nesta seção, exploramos como evitar esse comportamento, garantindo que as operações sejam executadas apenas na abertura de um novo candle, melhorando o controle e evitando reentradas desnecessárias.

Exemplo:

// Declare an array to store time data
datetime time[];

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
// Ensure the time array is structured as a time series (most recent data first)
   ArraySetAsSeries(time, true);

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
// Retrieve the latest three time values from the current symbol and timeframe
   CopyTime(_Symbol, PERIOD_CURRENT, 0, 3, time);

// Select trading history from the earliest recorded time to the current time
   bool trade_control = HistorySelect(time[0], TimeCurrent());

// Variable to count the number of closed trades
   int total_deals_out = 0;

// If the trading history selection is successful, process the data
   if(trade_control)
     {
      // Loop through all closed trades in the history
      for(int i = 0; i < HistoryDealsTotal(); i++)
        {
         // Get the ticket number of the historical trade
         ulong ticket = HistoryDealGetTicket(i);

         // Check if the trade matches the current EA's Magic Number and symbol
         if(HistoryDealGetInteger(ticket, DEAL_MAGIC) == MagicNumber && HistoryDealGetString(ticket, DEAL_SYMBOL) == ChartSymbol(chart_id))
           {
            // If the trade was an exit trade, increment the counter
            if(HistoryDealGetInteger(ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT)
              {
               total_deals_out++;
              }
           }
        }
     }
  }

Explicação:

Essa funcionalidade impede que o EA abra uma nova operação dentro do mesmo candle após o fechamento de uma anterior. O processo começa utilizando CopyTime(), que retorna os timestamps das barras mais recentes do gráfico. Em seguida, o EA seleciona o histórico de trades no intervalo entre o tempo da barra mais recente (time[0]) e o tempo atual do mercado (TimeCurrent()).

Depois, percorre o histórico de trades para identificar operações fechadas que correspondam ao Magic Number e símbolo do EA. Se uma operação fechada — especificamente uma saída (DEAL_ENTRY_OUT) — for encontrada, o contador total_deals_out é incrementado. Esse contador ajuda a identificar se uma operação foi recentemente fechada dentro do mesmo candle. Para garantir que novas operações sejam executadas apenas no início de uma nova barra e evitar reentradas imediatas indesejadas, o EA não abrirá uma nova operação até que um novo candle seja formado.

3.2.4. Implementando Gerenciamento de Risco e Execução de Trades com Heikin Ashi

Para garantir que operações de compra e venda sejam executadas com base nos sinais do Heikin Ashi, definiremos nesta seção as condições de execução de trades. Além disso, incorporaremos gerenciamento de risco ao determinar o tamanho do lote com base em um valor fixo de risco por operação e uma relação risco-retorno (RRR). Essa abordagem evita exposição excessiva ao risco enquanto mantém um trading disciplinado.

Exemplo:

input  double dollar_risk = 12.0; // How Many Dollars($) Per Trade?
input double RRR = 3;

double ask_price;
double lot_size;
double point_risk;
double take_profit;

// Variable to store the time of the last executed trade
datetime lastTradeBarTime = 0;

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

// Get the opening time of the current bar
   datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);

// Check conditions for opening a buy position
// Ensures Heikin Ashi candle crosses above the moving average
// Limits trades per day and prevents multiple trades in the same candlestick
   if(heikin_open[1] < heikin_ma[1] && heikin_close[1] > heikin_ma[1] &&
      deal_type_buy < (daily_trades / 2) && total_deals_out < 1 &&
      totalPositions < 1 && currentBarTime != lastTradeBarTime)
     {
      // Calculate risk in points (distance from entry to stop loss)
      point_risk = ask_price - heikin_low[1];

      // Calculate take profit based on risk-to-reward ratio (RRR)
      take_profit = ((ask_price - heikin_low[1]) * RRR) + ask_price;

      // Determine lot size based on the dollar risk per trade
      lot_size = CalculateLotSize(_Symbol, dollar_risk, point_risk);

      // Execute a buy trade
      trade.Buy(lot_size, _Symbol, ask_price, heikin_low[1], take_profit);

      // Store the current bar time to prevent multiple trades in the same candle
      lastTradeBarTime = currentBarTime;
     }

// Check conditions for opening a sell position
// Ensures Heikin Ashi candle crosses below the moving average
// Limits trades per day and prevents multiple trades in the same candlestick
   if(heikin_open[1] > heikin_ma[1] && heikin_close[1] < heikin_ma[1] &&
      deal_type_sell < (daily_trades / 2) && total_deals_out < 1 &&
      totalPositions < 1 && currentBarTime != lastTradeBarTime)
     {
      // Calculate risk in points (distance from entry to stop loss)
      point_risk = heikin_high[1] - ask_price;

      // Calculate take profit based on risk-to-reward ratio (RRR)
      take_profit = MathAbs(((heikin_high[1] - ask_price) * RRR) - ask_price);

      // Determine lot size based on the dollar risk per trade
      lot_size = CalculateLotSize(_Symbol, dollar_risk, point_risk);

      // Execute a sell trade
      trade.Sell(lot_size, _Symbol, ask_price, heikin_high[1], take_profit);

      // Store the current bar time to prevent multiple trades in the same candle
      lastTradeBarTime = currentBarTime;
     }
  }

//+------------------------------------------------------------------+
//| Function to calculate the lot size based on risk amount and stop loss
//+------------------------------------------------------------------+
double CalculateLotSize(string symbol, double riskAmount, double stopLossPips)
  {
// Get symbol information
   double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
   double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);

// Calculate pip value per lot
   double pipValuePerLot = tickValue / point;

// Calculate the stop loss value in currency
   double stopLossValue = stopLossPips * pipValuePerLot;

// Calculate the lot size
   double lotSize = riskAmount / stopLossValue;

// Round the lot size to the nearest acceptable lot step
   double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
   lotSize = MathFloor(lotSize / lotStep) * lotStep;

   return lotSize;
  }

Explicação:

A lógica de execução de trades baseia-se no cruzamento entre os candles Heikin Ashi e uma Média Móvel (MA) para confirmar tendências. Uma reversão de alta é indicada quando o preço de abertura está abaixo da MA e o fechamento está acima; uma venda ocorre quando o oposto é verdadeiro. O sistema limita o número de operações diárias, garante que não haja posições abertas e executa trades apenas em novos candles para evitar excesso de operações. O gerenciamento de risco inclui definição de stop loss nos níveis anteriores de máxima ou mínima do Heikin Ashi, take profit baseado em uma relação risco-retorno (RRR) e dimensionamento dinâmico de lote.

3.2.5. Implementando Trailing Stop com Candles Heikin Ashi

O objetivo principal desta seção é implementar um mecanismo de trailing stop utilizando candles Heikin Ashi. Isso garante que os níveis de stop-loss sejam ajustados dinamicamente conforme as mudanças no preço Heikin Ashi.

Exemplo:

input bool    allow_trailing  = false; // Do you Allow Trailing Stop?

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

   // Check if trailing stop is enabled
   if(allow_trailing == true)
     {
      // Variables to store trade-related information
      double positionProfit = 0;
      double positionopen = 0;
      double positionTP = 0;
      double positionSL = 0;

      // Loop through all open positions
      for(int i = 0; i < PositionsTotal(); i++)
        {
         // Get the ticket number of the position
         ulong ticket = PositionGetTicket(i);

         // Select the position using its ticket number
         if(PositionSelectByTicket(ticket))
           {
            // Check if the position belongs to the EA by verifying the magic number and symbol
            if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetString(POSITION_SYMBOL) == ChartSymbol(chart_id))
              {
               // Retrieve trade details: open price, take profit, profit, and stop loss
               positionopen = PositionGetDouble(POSITION_PRICE_OPEN);
               positionTP = PositionGetDouble(POSITION_TP);
               positionProfit = PositionGetDouble(POSITION_PROFIT);
               positionSL = PositionGetDouble(POSITION_SL);

               // Apply trailing stop logic for buy positions
               if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
                 {
                  // Adjust stop loss if Heikin Ashi low is above the entry price and the candle is bullish
                  if(heikin_low[1] > positionopen && heikin_close[1] > heikin_open[1])
                    {
                     trade.PositionModify(ticket, heikin_low[1], positionTP);
                    }
                 }

               // Apply trailing stop logic for sell positions
               if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
                 {
                  // Adjust stop loss if Heikin Ashi high is below the entry price and the candle is bearish
                  if(heikin_high[1] < positionopen && heikin_close[1] < heikin_open[1])
                    {
                     trade.PositionModify(ticket, heikin_high[1], positionTP);
                    }
                 }
              }
           }
        }
     }
  }

Explicação:

Para proteger lucros e ajustar dinamicamente o stop-loss, esta seção utiliza candles Heikin Ashi na implementação do trailing stop. A variável de entrada allow_trailing controla se o trailing stop está habilitado; se estiver definida como true, o sistema percorre todas as posições abertas, recupera seus detalhes e verifica se pertencem ao EA por meio do Magic Number e do símbolo. Para facilitar a lógica do trailing stop, são extraídas informações importantes da operação, como preço de abertura, take profit, lucro e stop loss.

O sistema valida posições abertas verificando se a mínima Heikin Ashi anterior é maior que o preço de entrada e se o fechamento Heikin Ashi está acima da abertura, confirmando uma tendência de alta. Se essas condições forem atendidas, o stop loss é ajustado para a mínima Heikin Ashi, protegendo lucros enquanto permite a continuidade do movimento de alta. Para operações de venda, o sistema valida uma tendência de baixa verificando se a máxima Heikin Ashi anterior está abaixo do preço de entrada e se o fechamento Heikin Ashi está abaixo da abertura. Se essas condições forem atendidas, o stop loss é ajustado para a máxima Heikin Ashi, protegendo a operação e capturando movimentos adicionais do mercado.


Conclusão

Neste artigo, construímos um indicador Heikin Ashi do zero, integrando-o com uma Média Móvel baseada nos dados dos candles Heikin Ashi, e exploramos como incorporar um indicador personalizado em um EA, garantindo uma integração fluida para trading automatizado. Implementamos técnicas de gerenciamento de risco, como limitação de operações diárias, prevenção de múltiplas operações fechadas dentro do mesmo candle e cálculo dinâmico do tamanho de lote. Além disso, introduzimos um mecanismo de trailing stop utilizando candles Heikin Ashi para ajustar os níveis de stop-loss. Esses conceitos fornecem uma base sólida para construir e aprimorar estratégias de trading automatizadas em MQL5.

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

Últimos Comentários | Ir para discussão (2)
dhermanus
dhermanus | 31 mai. 2025 em 11:08

Oi Isreal,

Obrigado pelo blog, pelo tempo e pelo esforço.


Gostaria de perguntar sobre o código do indicador personalizado Heikin Ashi.

Sobre a fórmula do Heikin Ashi Open:

// FÓRMULA DE ABERTURA DO HEIKIN ASHI
HA_Open[i] = (HA_Open[i - 1] + HA_Close[i - 1]) / 2.0;

Como você não calculou o HA_Open[i - 1]. Esse valor não seria 0?


Minha sugestão:


se (i == 1){

HA_Open[i] = (open[i - 1] + close[i - 1])/2.0; // Na primeira barra do HA, use apenas os dados normais de abertura/fechamento

}

else{

// FÓRMULA DE ABERTURA DO HEIKIN ASHI

HA_Open[i] = (HA_Open[i - 1] + HA_Close[i - 1]) / 2,0;


}

ALGOYIN LTD
Israel Pelumi Abioye | 31 mai. 2025 em 12:28
dhermanus do indicador personalizado Heikin Ashi.

Sobre a fórmula do Heikin Ashi Open:

// FÓRMULA DE ABERTURA DO HEIKIN ASHI
HA_Open[i] = (HA_Open[i - 1] + HA_Close[i - 1]) / 2.0;

Como você não calculou o HA_Open[i - 1]. Esse valor não seria 0?


Minha sugestão:


se (i == 1){

HA_Open[i] = (open[i - 1] + close[i - 1])/2.0; // Na primeira barra do HA, use apenas os dados normais de abertura/fechamento

}

else{

// FÓRMULA DE ABERTURA DO HEIKIN ASHI

HA_Open[i] = (HA_Open[i - 1] + HA_Close[i - 1]) / 2.0;


}

Obrigado. Vou dar uma olhada nisso
Símbolos personalizados em MQL5: Criando um símbolo customizado de barras 3D Símbolos personalizados em MQL5: Criando um símbolo customizado de barras 3D
Este artigo apresenta um guia detalhado para criar o indicador inovador 3DBarCustomSymbol.mq5, que gera símbolos personalizados no MetaTrader 5, reunindo preço, tempo, volume e volatilidade em uma representação tridimensional única. São abordados os fundamentos matemáticos, a arquitetura do sistema, os aspectos práticos de implementação e o uso em estratégias de trading.
Multiple Symbol Analysis With Python And MQL5 (Part 3): Taxas de Câmbio Triangulares Multiple Symbol Analysis With Python And MQL5 (Part 3): Taxas de Câmbio Triangulares
Traders frequentemente enfrentam drawdowns causados por sinais falsos, enquanto esperar por confirmação pode levar à perda de oportunidades. Este artigo apresenta uma estratégia de trading triangular utilizando a cotação da Prata em Dólares (XAGUSD) e em Euros (XAGEUR), juntamente com a taxa de câmbio EURUSD, para filtrar ruído. Ao aproveitar relações entre mercados, traders podem descobrir sentimento oculto do mercado e refinar suas entradas em tempo real.
Do básico ao intermediário: Recursos Do básico ao intermediário: Recursos
Neste artigo você será apresentado a um conceito que pode ser de extrema utilidade em muitos casos. Facilitando em muito o compartilhamento de suas aplicações e projetos. Apesar de não ser um conceito muito simples de ser totalmente explicando em um único artigo. O que será explicado e exposto aqui, já nos irá permitir fazer diversas coisas no futuro. Inclusive algumas que de outra maneira não seriam possíveis de serem feitas. Justamente por que este artigo ainda não havia sido publicado, para que você, pudesse ter um material de apoio e uma base inicial de estudo.
Explorando modelos de regressão para inferência causal e trading Explorando modelos de regressão para inferência causal e trading
Neste artigo, foi realizado um estudo sobre a possibilidade de aplicar modelos de regressão no trading algorítmico. Os modelos de regressão, diferentemente da classificação binária, permitem criar estratégias de trading mais flexíveis por meio da avaliação quantitativa das variações de preço previstas.