Redefinindo os Indicadores MQL5 e MetaTrader 5
Introdução
MQL5 não é mais uma linguagem de programação simples como costumava ser para criar robôs de negociação simples. Atualmente, a linguagem amadureceu e agora é possível criar programas de negociação de grande complexidade, implantar e testar de forma muito mais robusta e conveniente.
Todos nós já utilizamos, em algum momento da nossa jornada de trading, indicadores “nativos” ou “indicadores personalizados”. O MetaTrader 5 possui uma interface simples para carregar e anexar indicadores ao gráfico, o que permite que traders (principalmente traders manuais) analisem os mercados de forma conveniente utilizando indicadores; no entanto, quando se trata de trading algorítmico, não é o que você vê no gráfico que importa, mas sim os cálculos de um indicador.
No trading manual, por exemplo, pode ser necessário observar a linha do indicador de média móvel para identificar uma tendência, caso isso seja o que se busca; porém, no trading algorítmico, podemos procurar uma tendência positiva com base em se o preço de fechamento está acima ou abaixo do valor da média móvel calculada ao longo de um determinado número de barras.
Quando se trata de trading algorítmico para usar um determinado indicador, por exemplo, uma Média Móvel Simples (SMA) de período 20, você precisa:
int sma_handle; //Declare an indicator handle //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { sma_handle = iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE); //Initialize the indicator inside the OnInit function //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- double sma_buffer[]; CopyBuffer(sma_handle, 0, 0, 1, sma_buffer); //Copy the indicator buffers inside the Ontick function }
Essa abordagem é prática e funciona bem, para dizer o mínimo, mas parece rudimentar e não nos dá a flexibilidade e o controle sobre quais informações podem ser passadas ao indicador para cálculos imediatos.
Com base nessa abordagem, afirma-se que o indicador de Média Móvel (MA) deve ser aplicado apenas a uma das constantes de preço fornecidas na documentação.
| ID | Descrição |
|---|---|
| PRICE_CLOSE | Preço de fechamento |
| PRICE_OPEN | Preço de abertura |
| PRICE_HIGH | O preço máximo do período |
| PRICE_LOW | O preço mínimo do período |
| PRICE_MEDIAN | Preço mediano, (máxima + mínima)/2 |
| PRICE_TYPICAL | Preço típico, (máxima + mínima + fechamento)/3 |
| PRICE_WEIGHTED | Preço médio, (máxima + mínima + fechamento + fechamento)/4 |
Sem mencionar que você fica restrito aos métodos/técnicas de suavização conforme descritos na documentação.
| ID | Descrição |
|---|---|
| MODE_SMA | Suavização simples |
| MODE_EMA | Suavização exponencial |
| MODE_SMMA | Suavização suavizada |
| MODE_LWMA | Suavização linear ponderada |
O que acontece quando você quer experimentar algo fora do padrão? Por exemplo, querer calcular a média móvel da diferença entre os preços máximo e mínimo; isso é impossível com base na abordagem atual, pois estamos restritos e limitados ao que podemos fazer com os indicadores.
Eu entendo que a maioria dos indicadores é o que é com base em como foram definidos e derivados matematicamente, mas não seria incrível se pudéssemos passar diferentes entradas e parâmetros para os indicadores com o objetivo de observar novos padrões no mercado?
Inspirado pela biblioteca Python Technical Analysis (TA-Lib), essa abordagem inovadora tem como objetivo oferecer aos traders e desenvolvedores de sistemas algorítmicos mais controle sobre quais informações são fornecidas ao indicador para cálculos imediatos.
Neste artigo, implementaremos alguns indicadores (os mais utilizados) usando essa abordagem plug-and-play.
Agrupados em categorias.
Indicadores de Tendência
- Indicador de Média Móvel Simples
- Indicador de Média Móvel Exponencial
- Bandas de Bollinger
- O Parabolic SAR
- Desvio Padrão
Osciladores
- A Convergência e Divergência de Médias Móveis (MACD)
- Índice de Força Relativa (RSI)
- Osciladores Estocásticos
- Faixa Média Verdadeira (ATR)
- Indicador de Momentum
Bill Williams
- Oscilador Acelerador
- Oscilador Awesome
Indicador de Média Móvel Simples (SMA)
Este é um dos indicadores técnicos mais comumente utilizados. Ele calcula a média de uma série de preços ao longo de um valor de período especificado.

Dado pela fórmula.
![]()
Onde:
-
são preços (por exemplo, preços de fechamento) ao longo de
períodos. -
é o período do SMA.
Podemos implementar facilmente essa fórmula em uma função vetorizada.
Arquivo: ta-lib.mqh
vector CTrendIndicators::SMA(const vector &price, uint period, uint shift = 0) { uint size = (uint)price.Size(); if(!CheckShiftPeriod(size, period, shift)) return price; //--- vector ma(size); ma.Fill(NaN); for(uint i = shift + period - 1; i < size; i++) //Loop through all the prices considering the period and shift { double sum = 0; for(uint j = i - period + 1; j <= i; j++) sum += price[j]; //sum of the prices ma[i] = sum / period; //divided by period to find the mean of that period } return ma; }
É assim que um indicador de média móvel simples é calculado, sem buffers implantados, sem verificação de erros do MQL5 ao carregar o indicador para um determinado símbolo, etc., o que pode ser cansativo.
Essa abordagem minimalista apenas verifica se os valores de shift e period estão corretos; se estiverem, a função prossegue com os cálculos do indicador retornando os valores calculados em formato vetorial. Decidi usar o formato vetorial para obter mais controle e flexibilidade sobre o resultado final.
Como todas as funções em nossas classes de Indicadores são estáticas, podemos acessar facilmente os valores dos indicadores em nossos programas MQL5, por exemplo, em um script simples.
Arquivo: Custom Indicators test script.mq5
#include <ta-lib.mqh> //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { vector prices = {1,2,3,4,5,6,7,8,9,10}; int period = 3; Print("SMA values: ", CTrendIndicators::SMA(prices, period)); }
Saída
2025.01.21 09:57:35.727 Custom Indicators test script (EURUSD,H1) SMA values: [nan,nan,2,3,4,5,6,7,8,9]
Assim, conseguimos calcular o indicador de média móvel simples a partir de um vetor de alguns valores. Mais adiante, discutiremos como plotar esses valores para um indicador visual.
Indicador de Média Móvel Exponencial (EMA)
A EMA é calculada como a média de uma série de preços ao longo de um número específico de períodos, assim como a SMA, porém atribui mais peso aos preços mais recentes, tornando-a mais sensível às variações de preço em comparação com a Média Móvel Simples (SMA).

Dado pela fórmula.
Onde:
-
é a EMA no tempo t. - Pt é o preço no tempo t.
-
é a EMA do período anterior. -
é o fator de suavização (onde n é o período)
Podemos implementá-la em MQL5 da seguinte forma;
Arquivo: ta-lib.mqh
vector CTrendIndicators::EMA(const vector &price, uint period, uint shift = 0) { uint size = (uint)price.Size(); if(!CheckShiftPeriod(size, period, shift)) return price; //--- double alpha = 2.0 / (period + 1.0); // Smoothing factor vector res(size); res.Fill(NaN); // Initialize the EMA with the SMA of the first period vector sma = SMA(price, period, shift); res[period - 1 + shift] = sma[period - 1 + shift]; // Calculate EMA for the rest of the prices for(ulong i = period + shift; i < size; i++) res[i] = alpha * price[i] + (1 - alpha) * res[i - 1]; return res; }
Podemos obter os valores calculados do indicador de forma semelhante ao que fizemos para o SMA.
Arquivo: Custom Indicators test script.mq5
void OnStart() { vector prices = {1,2,3,4,5,6,7,8,9,10}; int period = 3; Print("EMA values: ", CTrendIndicators::EMA(prices, period)); }
Saída
2025.01.21 10:19:54.291 Custom Indicators test script (EURUSD,H1) EMA values: [nan,nan,2,3,4,5,6,7,8,9]
Calculamos os indicadores de Média Móvel Simples (SMA) e Média Móvel Exponencial (EMA) separadamente, diferentemente de como são calculados dentro do indicador embutido IMA, que oferece uma opção para o método de suavização de sua preferência.
Essa abordagem separada exige a escrita de linhas adicionais de código para implementar todos os métodos de suavização dos indicadores de média móvel.
Funções para métodos de suavização como MODE_SMMA (suavização suavizada) e (MODE_LWMA) suavização linear ponderada ainda não foram implementadas na biblioteca, pois acredito que não sejam tão comumente utilizadas quanto suas contrapartes (os métodos de suavização SMA e EMA).
O Indicador de Bandas de Bollinger
Este é um indicador de volatilidade composto por três bandas.

- A Banda Central é uma média móvel simples (SMA) dos preços de fechamento ao longo de um período específico.

- A Banda Superior é a banda central mais um múltiplo do desvio padrão dos preços de fechamento ao longo do mesmo período.

Onde:
-
é normalmente 2 (a configuração padrão para as Bandas de Bollinger), -
é o período para os cálculos da SMA e do desvio padrão.
Como este indicador precisa retornar três (3) valores unidimensionais (1D), conhecidos como buffers quando se utiliza o indicador de Bandas de Bollinger embutido, vamos fazer com que esta função retorne uma estrutura de 3 vetores.
Arquivo: ta-lib.mqh
struct BB_res_struct { vector upper_band; vector lower_band; vector middle_band; };
BB_res_struct CTrendIndicators::BollingerBands(const vector &price, uint period, uint shift = 0, double k = 2.0) { uint size = (uint)price.Size(); BB_res_struct res; //--- Check for valid parameters if(!CheckShiftPeriod(size, period, shift)) return res; //--- Initialize vectors res.upper_band.Resize(size); res.lower_band.Resize(size); res.upper_band.Fill(NaN); res.lower_band.Fill(NaN); //--- Calculate the middle band (SMA) res.middle_band = SMA(price, period, shift); //--- Calculate the upper and lower bands for(uint i = shift + period - 1; i < size; i++) { double sum_squared_diff = 0; for(uint j = i - period + 1; j <= i; j++) { sum_squared_diff += MathPow(price[j] - res.middle_band[i], 2); } double std_dev = MathSqrt(sum_squared_diff / period); res.upper_band[i] = res.middle_band[i] + (k * std_dev); res.lower_band[i] = res.middle_band[i] - (k * std_dev); } return res; }
Abaixo está como implementar facilmente o indicador de Bandas de Bollinger e obter seus valores.
Arquivo: Custom Indicators test script.mq5
void OnStart() { vector prices = {1,2,3,4,5,6,7,8,9,10}; int period = 3; BB_res_struct bb; bb = CTrendIndicators::BollingerBands(prices,period,0,2); Print("BB upper: ",bb.upper_band); Print("BB middle: ",bb.middle_band); Print("BB lower: ",bb.lower_band); }
Saída
RL 0 11:39:21.000 Custom Indicators test script (EURUSD,H1) BB upper: [nan,nan,3.632993161855452,4.632993161855453,5.632993161855453,6.632993161855453,7.632993161855453,8.632993161855453,9.632993161855453,10.63299316185545] RO 0 11:39:21.000 Custom Indicators test script (EURUSD,H1) BB middle: [nan,nan,2,3,4,5,6,7,8,9] FF 0 11:39:21.000 Custom Indicators test script (EURUSD,H1) BB lower: [nan,nan,0.3670068381445479,1.367006838144548,2.367006838144548,3.367006838144548,4.367006838144547,5.367006838144547,6.367006838144547,7.367006838144547]
O Parabolic SAR (Stop and Reverse)
Este é um indicador seguidor de tendência usado para identificar possíveis reversões no mercado. Ele posiciona pontos acima ou abaixo do preço com base na direção da tendência.

Dado pela fórmula.
Para tendência de alta
![]()
Para tendência de baixa
![]()
Onde:
-
= O valor do SAR do próximo período -
= Fator de Aceleração (inicia em um valor padrão, por exemplo 0.02, e aumenta em 0.02 a cada vez que um novo máximo/mínimo é atingido. Até um valor máximo de 0.2) -
= Ponto Extremo (o maior preço máximo em uma tendência de alta, o menor preço mínimo em uma tendência de baixa)
Este indicador pode ser implementado em MQL5 da seguinte forma.
Arquivo: ta-lib.mqh
vector CTrendIndicators::ParabolicSAR(const vector &high, const vector &low, const vector &close, double step = 0.02, double max = 0.2) { uint size = (uint)close.Size(); vector psar(size); psar.Fill(NaN); // Initialize variables double AF = step; // Acceleration Factor double EP = high[0]; // Extreme Point double SAR = low[0]; // Initial SAR bool isUptrend = true; // Assume uptrend at the start // Calculate Parabolic SAR for(uint i = 0; i < size; i++) { // Update SAR if(isUptrend) SAR = SAR + AF * (EP - SAR); else SAR = SAR + AF * (SAR - EP); // Determine if trend changes if(isUptrend && SAR > low[i]) { // Switch to downtrend isUptrend = false; SAR = EP; // Reset SAR to the most recent EP EP = low[i]; // Reset EP AF = step; // Reset AF } else if(!isUptrend && SAR < high[i]) { // Switch to uptrend isUptrend = true; SAR = EP; // Reset SAR to the most recent EP EP = high[i]; // Reset EP AF = step; // Reset AF } // Update EP and AF if(isUptrend) { if(high[i] > EP) { EP = high[i]; AF = MathMin(AF + step, max); } } else { if(low[i] < EP) { EP = low[i]; AF = MathMin(AF + step, max); } } // Store the SAR value psar[i] = SAR; } return psar; }
Diferentemente dos dois indicadores seguidores de tendência anteriores, que podem receber um único vetor como entrada de preço, o Parabolic SAR considera três (3) valores de preço (Máximo, Mínimo e valores de Fechamento).
Arquivo: Custom Indicators test script.mq5
void OnStart() { vector close = {1,2,3,4,5,6,7,8,9,10}; vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5}; vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5}; Print("Parabolic SAR values: ", CTrendIndicators::ParabolicSAR(high,low,close,0.02,0.2)); }
Saída
2025.01.21 11:11:03.525 Custom Indicators test script (EURUSD,H1) Parabolic SAR values: [1.5,0.5,0.54,0.6584000000000001,0.8888960000000001,1.25778432,1.782005888,2.46816518144,3.3126220560384,4.302602527072256]
O Indicador de Desvio Padrão
Este indicador mede a quantidade de variação ou dispersão do preço em relação à sua média. Este indicador é frequentemente utilizado para avaliar a volatilidade do mercado.

Um valor alto de desvio padrão indica alta volatilidade, enquanto um valor baixo de desvio padrão indica baixa volatilidade.
Dado pela fórmula.
![]()
Onde:
-
= Desvio padrão - n = Período
-
= Ponto de preço -
= Média dos pontos de dados 
Podemos implementar este indicador em MQL5 da seguinte forma;
Arquivo: ta-lib.mqh
vector CTrendIndicators::StandardDeviation(const vector &price, uint period, uint shift = 0) { uint size = (uint)price.Size(); // Check if the period and shift are valid if(!CheckShiftPeriod(size, period, shift)) return price; // Initialize standard deviation vector vector std_dev(size); std_dev.Fill(NaN); // Loop through the price data for(uint i = shift + period - 1; i < size; i++) { double sum = 0.0; double sum_sq_diff = 0.0; // Calculate mean for(uint j = i - period + 1; j <= i; j++) sum += price[j]; double mean = sum / period; // Calculate squared differences for(uint j = i - period + 1; j <= i; j++) sum_sq_diff += MathPow(price[j] - mean, 2); // Calculate standard deviation std_dev[i] = MathSqrt(sum_sq_diff / period); } return std_dev; }
Este é outro indicador simples que pode ser chamado da seguinte forma.
Arquivo: Custom Indicators test script.mq5
void OnStart() { vector prices = {1,2,3,4,5,6,7,8,9,10}; int period = 3; Print("Stddev values: ", CTrendIndicators::StandardDeviation(prices, period)); }
Saída
2025.01.21 11:55:11.657 Custom Indicators test script (EURUSD,H1) Stddev values: [nan,nan,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726]
A Convergência e Divergência de Médias Móveis (MACD)
Este oscilador mostra a relação entre duas médias móveis do preço de um ativo. Ele é amplamente utilizado como uma ferramenta de análise técnica.

Dado pela fórmula.
Linha Principal do MACD
![]()
Onde:
-
= Média Móvel Exponencial com um período mais curto (ex.: 12) -
= Média Móvel Exponencial com um período mais longo (ex.: 26)
Linha de Sinal
![]()
Esta é uma EMA suavizada da linha MACD, normalmente com um valor de período de 9
Histograma do MACD
Esta é a diferença entre a linha MACD e a linha de sinal.
![]()
De forma semelhante à maneira como retornamos múltiplos valores calculados das Bandas de Bollinger, definimos uma estrutura para retornar os valores do histograma, da linha principal e da linha de sinal do MACD.
Arquivo: ta-lib.mqh
struct MACD_res_struct { vector main; // The MACD Line vector signal; // The Signal Line vector histogram; // The MACD Histogram };
MACD_res_struct COscillatorIndicators::MACD(const vector &price, uint fast_ema = 12, uint slow_ema = 26, uint macd_sma = 9, uint shift = 0) { uint size = (uint)price.Size(); MACD_res_struct res; if(!CheckShiftPeriod(size, slow_ema, shift)) return res; //--- Calculate EMA(short), EMA(long), and MACD Line vector fast_ema_vector = CTrendIndicators::EMA(price, fast_ema, shift); vector slow_ema_vector = CTrendIndicators::EMA(price, slow_ema, shift); res.main.Resize(size); res.main.Fill(NaN); for(uint i = 0; i < size; i++) res.main[i] = fast_ema_vector[i] - slow_ema_vector[i]; //--- Calculate Signal Line (SMA of MACD Line) res.signal = CTrendIndicators::SMA(price, macd_sma, shift); //--- Calculate MACD Histogram res.histogram.Resize(size); res.histogram.Fill(NaN); for(uint i = 0; i < size; i++) res.histogram[i] = res.main[i] - res.signal[i]; return res; }
Podemos facilmente obter os valores calculados do oscilador MACD dentro de um script de teste da seguinte forma.
Arquivo: Custom Indicators test script.mq5
void OnStart() { vector prices = {1,2,3,4,5,6,7,8,9,10}; MACD_res_struct macd; macd = COscillatorIndicators::MACD(prices,2,3,4); Print("MACD main: ", macd.main); Print("MACD signal: ", macd.signal); }
Saída
RD 0 12:28:51.368 Custom Indicators test script (EURUSD,H1) MACD main: [nan,nan,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5] HO 0 12:28:51.368 Custom Indicators test script (EURUSD,H1) MACD signal: [nan,nan,nan,2.5,3.5,4.5,5.5,6.5,7.5,8.5]
O Indicador de Força Relativa (RSI)
Este é um oscilador de momentum que mede a velocidade e a magnitude dos movimentos de preço. Ele oscila entre 0 e 100, os traders o utilizam para identificar condições de sobrecompra e sobrevenda no mercado.

Os cálculos do indicador RSI envolvem as seguintes etapas:
01: Encontrar os ganhos médios e as perdas médias ao longo de um período especificado
![]()
![]()
02: Calcular a Força Relativa (RS)
![]()
03: Calcular o RSI
![]()
Implementação em MQL5
vector COscillatorIndicators::RSI(const vector &price, uint period, uint shift = 0) { uint size = (uint)price.Size(); //--- Check for valid parameters if(!CheckShiftPeriod(size, period, shift)) return price; //--- Initialize vectors vector rsi(size), gains(size), losses(size); rsi.Fill(NaN); gains.Fill(0.0); losses.Fill(0.0); //--- Calculate gains and losses for(uint i = shift + 1; i < size; i++) { double change = price[i] - price[i - 1]; gains[i] = (change > 0) ? change : 0; losses[i] = (change < 0) ? -change : 0; } //--- Initialize first average gain and loss (simple average for the first period) double avg_gain = 0, avg_loss = 0; for(uint i = shift + 1; i < shift + 1 + period; i++) { avg_gain += gains[i]; avg_loss += losses[i]; } avg_gain /= period; avg_loss /= period; //--- Compute RSI for the rest of the periods for(uint i = shift + period; i < size; i++) { // Apply smoothing for average gain and loss avg_gain = ((avg_gain * (period - 1)) + gains[i]) / period; avg_loss = ((avg_loss * (period - 1)) + losses[i]) / period; // Calculate RSI double rs = (avg_loss == 0) ? 0 : avg_gain / avg_loss; rsi[i] = (avg_loss == 0) ? 100 : (100 - (100 / (1 + rs))); } return rsi; }
Abaixo está como você pode obter valores do indicador RSI.
void OnStart() { vector prices = {1,2,3,4,5,6,7,8,9,10}; int period = 3; Print("RSI values: ", COscillatorIndicators::RSI(prices,period)); }
Saída
2025.01.21 12:51:29.640 Custom Indicators test script (EURUSD,H1) RSI values: [nan,nan,nan,100,100,100,100,100,100,100]
O Indicador Oscilador Estocástico
Este é um indicador de momentum que compara o preço de fechamento de um ativo com sua faixa de preços ao longo de um período especificado.
A fórmula para calcular este indicador consiste em;
Linha %K
![]()
Onde:
-
é o preço de fechamento atual -
é o menor preço ao longo do período de análise -
é o maior preço ao longo do período de análise
Linha %D
Esta é a média móvel da Linha %K, normalmente utilizando uma média móvel simples (SMA) de 3 períodos
Abaixo está como implementar este indicador em MQL5.
Stochastic_struct COscillatorIndicators::StochasticOscillator(const vector &high, const vector &low, const vector &close, uint k_period = 5, uint d_period = 3, uint period = 3, uint shift = 0) { uint size = (uint)close.Size(); Stochastic_struct res; // Check for valid parameters if(!CheckShiftPeriod(size, period, shift)) return res; // Initialize vectors for %K and %D vector K(size), D(size); K.Fill(NaN); D.Fill(NaN); // Calculate %K for(uint i = shift + period - 1; i < size; i++) { double H_max = -DBL_MAX, L_min = DBL_MAX; // Find the highest high and the lowest low over the lookback period for(uint j = i - period + 1; j <= i; j++) { H_max = MathMax(H_max, high[j]); L_min = MathMin(L_min, low[j]); } // Calculate %K double K_value = (H_max - L_min != 0) ? ((close[i] - L_min) / (H_max - L_min)) * 100 : 0; K[i] = K_value; } // Smooth %K with a simple moving average (k_period) vector smoothedK(size); smoothedK.Fill(NaN); for(uint i = shift + k_period - 1; i < size; i++) { double sum = 0; for(uint j = i - k_period + 1; j <= i; j++) { sum += K[j]; } smoothedK[i] = sum / k_period; } // Calculate %D (3-period moving average of %K) D = CTrendIndicators::SMA(smoothedK, period, shift); res.main = K; res.signal = D; return res; }
Retornamos a linha de sinal e a linha principal em uma estrutura.
void OnStart() { vector close = {1,2,3,4,5,6,7,8,9,10}; vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5}; vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5}; Stochastic_struct stoch; stoch = COscillatorIndicators::StochasticOscillator(high,low,close,5,3,3); Print("Stoch main: ", stoch.main); Print("Stoch signal: ", stoch.signal); }
O Indicador Average True Range (ATR)
Este é um indicador útil para entender a volatilidade do mercado. Ele mede a faixa média entre os preços máximo e mínimo ao longo de um período especificado.

Dado pela fórmula.
01: Cálculo do True Range (TR)
![]()
Onde:
- H é o máximo do período atual.
-
é o mínimo do período atual. -
é o fechamento do período anterior.
02: Cálculo do Average True Range (ATR)
ATR é a média móvel do true range ao longo de um período especificado.
SMA é a Média Móvel Simples.
Podemos implementar este indicador em MQL5 da seguinte forma.
vector COscillatorIndicators::ATR(const vector &high, const vector &low, const vector &close, uint period = 14, uint shift = 0) { uint size = (uint)close.Size(); // Check for valid parameters if(!CheckShiftPeriod(size, period, shift)) return close; // Initialize the True Range (TR) and ATR vectors vector TR(size); TR.Fill(NaN); // Calculate the True Range for each period for(uint i = shift + 1; i < size; i++) { double H = high[i]; double L = low[i]; double C_prev = close[i - 1]; // Calculate the three possible True Range values double TR1 = H - L; double TR2 = MathAbs(H - C_prev); double TR3 = MathAbs(L - C_prev); // True Range is the maximum of the three TR[i] = MathMax(TR1, MathMax(TR2, TR3)); } //--- Smooth the True Range using a simple moving average (SMA) over the specified period return CTrendIndicators::SMA(TR, period, shift); }
Abaixo está como podemos obter os valores deste indicador.
void OnStart() { vector close = {1,2,3,4,5,6,7,8,9,10}; vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5}; vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5}; Print("ATR values: ", COscillatorIndicators::ATR(high,low,close,3)); }
Saída
2025.01.21 13:57:59.943 Custom Indicators test script (EURUSD,H1) ATR values: [nan,nan,nan,1.5,1.5,1.5,1.5,1.5,1.5,1.5]
O Indicador de Momentum
Este é um indicador simples usado para medir a velocidade com que o preço de um ativo está se movendo ao longo de um período especificado. Ele ajuda a identificar tendências e possíveis reversões de tendência.

Dado por uma fórmula simples.
![]()
Onde:
- Momentum(t) = valor do momentum no tempo t
- Price(t) = o preço atual
- Price(t - n) = preço de n períodos atrás
- n = o período ao longo do qual o momentum é calculado
Algumas variações para o cálculo do momentum utilizam uma razão.
![]()
Vamos implementar o indicador de momentum utilizando esta variação.
Implementação em MQL5
vector COscillatorIndicators::MomentumIndicator(const vector &price, uint period, uint shift = 0) { uint size = (uint)price.Size(); // Check for valid input if(!CheckShiftPeriod(size, period, shift)) return price; // Initialize the momentum vector vector momentum(size); momentum.Fill(NaN); // Calculate Momentum for(uint i = shift + period; i < size; i++) { //momentum[i] = price[i] - price[i - period]; // Momentum difference formula // using the ratio formula: momentum[i] = (price[i] / price[i - period]) * 100; } return momentum; }
Indicador Awesome Oscillator
Este é um indicador de momentum que calcula a diferença entre duas Médias Móveis Simples (SMAs) do preço mediano.

Dado pela fórmula:
![]()
Onde:
-
= SMA com um período mais curto (comumente 5) -
= SMA com um período mais longo (comumente 34)
Abaixo está a implementação em MQL5.
vector CBillWilliamsIndicators::AwesomeOscillator(const vector &high, const vector &low, uint fast_period = 5, uint slow_period = 34, uint shift = 0) { uint size = (uint)high.Size(); if(size != low.Size()) return vector::Zeros(0); // Ensure high and low vectors are of the same size if(!CheckShiftPeriod(size, slow_period, shift)) return vector::Zeros(0); // Validate shift and slow period // Initialize vectors vector ao(size), median_price(size); ao.Fill(NaN); median_price.Fill(NaN); // Calculate Median Price for(uint i = 0; i < size; i++) median_price[i] = (high[i] + low[i]) / 2; // Calculate Fast and Slow SMAs of the Median Price vector sma_fast = CTrendIndicators::SMA(median_price, fast_period, shift); vector sma_slow = CTrendIndicators::SMA(median_price, slow_period, shift); // Calculate AO for(uint i = 0; i < size; i++) ao[i] = sma_fast[i] - sma_slow[i]; return ao; }
Como temos vetores muito simples para preços máximos e mínimos, podemos definir o período rápido como 3 e o período lento como 5.
void OnStart()
{
vector close = {1,2,3,4,5,6,7,8,9,10};
vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5};
vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5};
Print("AO values: ", CBillWilliamsIndicators::AwesomeOscillator(high,low,3,5));
} Saída.
2025.01.21 14:25:50.590 Custom Indicators test script (EURUSD,H1) AO values: [nan,nan,nan,nan,1,1,1,1,1,1]
Indicador Accelerator Oscillator
O Accelerator Oscillator (AC) é uma ferramenta de análise técnica que acompanha a velocidade das mudanças no momentum do preço. Ele mostra se a força motriz do mercado está acelerando ou desacelerando, ajudando os traders a antecipar possíveis reversões.

Ele é calculado como a diferença entre o Awesome Oscillator e a média móvel simples (SMA) de 5 períodos do AO.
Dado pela fórmula abaixo.
Podemos implementar este indicador em MQL5 da seguinte forma.
vector CBillWilliamsIndicators::AcceleratorOscillator(const vector &high, const vector &low, uint ao_period_fast = 5, // Fast period for AO uint ao_period_slow = 34, // Slow period for AO uint ac_period = 5 // Period for AC SMA ) { uint size = (uint)high.Size(); if(size != low.Size()) return vector::Zeros(0); // Ensure high and low vectors are of the same size // Validate shift and period if(!CheckShiftPeriod(size, ao_period_slow, 0)) return vector::Zeros(0); // Calculate AO (Awesome Oscillator) vector ao = AwesomeOscillator(high, low, ao_period_fast, ao_period_slow); // Calculate AC (Accelerator Oscillator) vector ac(size); ac.Fill(NaN); vector ao_sma_ac = CTrendIndicators::SMA(ao, ac_period); for(uint i = 0; i < size; i++) ac[i] = ao[i] - ao_sma_ac[i]; return ac; }
Como o Accelerator Oscillator é muito semelhante ao Awesome Oscillator, podemos chamar sua função com argumentos semelhantes.
void OnStart() { vector close = {1,2,3,4,5,6,7,8,9,10}; vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5}; vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5}; //--- Bill williams indicator Print("AO values: ", CBillWilliamsIndicators::AwesomeOscillator(high,low,3,5)); Print("AC values: ", CBillWilliamsIndicators::AcceleratorOscillator(high,low,3,5)); }
Saída
MQ 0 14:40:36.296 Custom Indicators test script (EURUSD,H1) AO values: [nan,nan,nan,nan,1,1,1,1,1,1] EL 0 14:40:36.296 Custom Indicators test script (EURUSD,H1) AC values: [nan,nan,nan,nan,nan,nan,nan,nan,0,0]
Coleta de Dados de Indicadores Simplificada
Agora que vimos como alguns dos indicadores foram implementados na biblioteca, podemos tentar coletar qualquer informação que desejarmos obter do mercado e construir um indicador com base nela. Por exemplo, vou calcular a média móvel para os preços de Abertura, Máxima, Mínima e Fechamento.
Começamos obtendo os valores OHLC.
int size = 1000; vector open, high, low, close; open.CopyRates(Symbol(), Period(), COPY_RATES_OPEN, 1, size); high.CopyRates(Symbol(), Period(), COPY_RATES_HIGH, 1, size); low.CopyRates(Symbol(), Period(), COPY_RATES_LOW, 1, size); close.CopyRates(Symbol(), Period(), COPY_RATES_CLOSE, 1, size);
Começando com a média móvel simples de período 20 aplicada aos preços de abertura.
vector sma_open = CTrendIndicators::SMA(open, 20);
Podemos coletar vários indicadores SMA, dado um período diferente e um preço diferente, sem esforço.
vector sma_open = CTrendIndicators::SMA(open, 20); vector sma_high = CTrendIndicators::SMA(high, 50); vector sma_low = CTrendIndicators::SMA(low, 100); vector sma_close = CTrendIndicators::SMA(close, 20);
Vamos inseri-los em uma matriz e observá-los todos em conjunto.
matrix Indicators(size, 4); Indicators.Col(CTrendIndicators::SMA(open, 20), 0); Indicators.Col(CTrendIndicators::SMA(high, 50), 1); Indicators.Col(CTrendIndicators::SMA(low, 100), 2); Indicators.Col(CTrendIndicators::SMA(close, 20), 3); Print("Indicators matrix\n",Indicators);
Saída
NK 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0485715,1.0484514,nan,1.048488] LL 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0484425,1.0485544,nan,1.0484265] RP 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.048381,1.0486754,nan,1.048299] QG 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0483055,1.0488004,nan,1.048152] KK 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0481585,1.0489198,nan,1.048296] HL 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.048303,1.049033,nan,1.0485255] DS 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.048533,1.0491756,nan,1.0487015] OK 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.048658,1.0493158,1.0475226,1.0488295] KD 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0487895,1.0494628,1.047473,1.0488985] JR 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0488575,1.0494916,1.0474256,1.0489465] FR 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0489055,1.049475,1.0473723,1.0490045] LL 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.048964,1.0494814,1.0473137,1.049052] HK 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0490075,1.0494728,1.0472494,1.0491065] CF 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.049062,1.0494618,1.0471845,1.049044] RE 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0489995,1.0494452,1.047114,1.048892] FQ 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.048848,1.0494558,1.047044,1.0487065] CL 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0486625,1.0495002,1.0469762,1.0486305] DK 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.048586,1.0496014,1.0469234,1.048582] EE 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0485375,1.0496714,1.0468866,1.048646] RE 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0486015,1.0497982,1.046857200000001,1.04877] IP 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0487245,1.0498646,1.0468378,1.0490025] DO 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0489565,1.0499466,1.046833500000001,1.0492415] GN 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0491975,1.050113,1.046846700000001,1.0497525] CK 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0497085,1.0502838,1.046881000000001,1.0502025] IJ 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.050159,1.0503826,1.046898100000001,1.0506915] PF 0 18:30:25.100 Custom Indicators test script (EURUSD,H1) [1.0506475,1.0504916,1.046935200000001,1.051158…]
Digamos que eu queira medir o momentum dessas variáveis que tenho, criando um indicador de momentum baseado nelas.
Indicators.Col(COscillatorIndicators::MomentumIndicator(open, 20), 4); Indicators.Col(COscillatorIndicators::MomentumIndicator(high, 50), 5); Indicators.Col(COscillatorIndicators::MomentumIndicator(low, 100), 6); Indicators.Col(COscillatorIndicators::MomentumIndicator(close, 20), 7);
Saída
IN 0 18:39:34.172 Custom Indicators test script (EURUSD,H1) [1.0441885,nan,nan,1.0438975,99.43679181343492,nan,nan,99.44502817843157] LN 0 18:39:34.172 Custom Indicators test script (EURUSD,H1) [1.0438975,1.0495116,nan,1.043593,99.44407828753189,nan,nan,99.41864350150351] QS 0 18:39:34.172 Custom Indicators test script (EURUSD,H1) [1.0435925,1.0492638,nan,1.0433225,99.4176888931316,98.82473464044848,nan,99.4833645288208] HG 0 18:39:34.172 Custom Indicators test script (EURUSD,H1) [1.0436275,1.049148199999999,nan,1.043363,100.0668474731655,99.45161810609009,nan,100.0773424743863] EH 0 18:39:34.172 Custom Indicators test script (EURUSD,H1) [1.0436685,1.0490618,nan,1.043385,100.0782973197491,99.59030385797199,nan,100.0420047732697] KO 0 18:39:34.172 Custom Indicators test script (EURUSD,H1) [1.0436925,1.0489454,nan,1.0434175,100.0458251389074,99.4479854313681,nan,100.0620536907626] JQ 0 18:39:34.172 Custom Indicators test script (EURUSD,H1) [1.0437225,1.048834,nan,1.043484,100.0572803299347,99.47183265534476,nan,100.1270939444036] JE 0 18:39:34.172 Custom Indicators test script (EURUSD,H1) [1.043788,1.048718,nan,1.0435725,100.1251839535195,99.45010144680205,nan,100.1690625149243] LE 0 18:39:34.172 Custom Indicators test script (EURUSD,H1) [1.043877,1.048595199999999,nan,1.0435315,100.1700192943244,99.41799844546816,nan,99.92180198737388] MI 0 18:39:34.172 Custom Indicators test script (EURUSD,H1) [1.0438365,1.048457,nan,1.0437085,99.92275488503829,99.34503611305946,nan,100.3389538390831] HN 0 18:39:34.172 Custom Indicators test script (EURUSD,H1) [1.044013,1.0483164,nan,1.044095,100.3379931060896,99.33386396801032,nan,100.7431263218612] KS 0 18:39:34.172 Custom Indicators test script (EURUSD,H1) [1.0443985,1.048186,nan,1.044364,100.7411964891704,99.38227742565063,nan,100.5158345877638] EE 0 18:39:34.172 Custom Indicators test script (EURUSD,H1) [1.0446665,1.0480502,nan,1.044532,100.5139219145509,99.35649569733499,nan,100.3225558712848…]
Plotagem de Indicadores Criados com Funções Personalizadas
Vamos tentar tornar visíveis ao olho humano os cálculos dos indicadores obtidos a partir desta biblioteca.
Apesar de esta abordagem ser voltada para coleta de dados em vez de visualização, vamos visualizar os cálculos dos indicadores em um indicador personalizado do MetaTrader 5.
Visualizando o indicador SMA (20).
#property indicator_chart_window #property indicator_buffers 1 #property indicator_plots 1 #property indicator_color1 clrDodgerBlue #property indicator_type1 DRAW_LINE #property indicator_style1 STYLE_SOLID #include <ta-lib.mqh> input int period_ = 20; //SMA period double buffer[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0, buffer, INDICATOR_DATA); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0); PlotIndexSetString(0,PLOT_LABEL,"SMA("+string(period_)+")"); PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,period_+1); //--- 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 (prev_calculated==0) //Initial indicator calculation, For Plotting the entire past { vector buffer_vector = CTrendIndicators::SMA(close, period_); VectorToArray(buffer_vector, buffer); //We assign the calculations into an array format } else //For plotting the current value { for (int i=prev_calculated-1; i<rates_total; i++) //Loop from the prev_calculated bars -1 to the total bars present { double temp_close[]; //For storing temporary close values int size = period_*2; //We are going to copy an equivalent of period x 2 to leave a room for NaN values if (ArrayCopy(temp_close, close, 0, i - size, size) < 0) { printf("Failed to copy closing price values to a temporary array, err = %d",GetLastError()); continue; } vector indicator_values = CTrendIndicators::SMA(temp_close, period_); ulong last_index = indicator_values.Size() - 1; //The last value in the vector is the recent calculated indicator value buffer[i] = indicator_values[last_index]; //Assing the last indicator value to the last value in the buffer } } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| A crude way to convert a vector into Array | //+------------------------------------------------------------------+ template <typename T> void VectorToArray(const vector<T> &v, T &arr[]) { ArrayResize(arr, (uint)v.Size()); for (uint i=0; i<(uint)v.Size(); i++) arr[i] = v[i]; }
Saída

Considerações Finais
Esta abordagem personalizada de coleta de valores de indicadores é mais prática quando se trata de coleta de dados do que para qualquer outra tarefa específica, sendo bem adequada para análise de dados e para entusiastas que buscam maneiras inovadoras de coletar dados de indicadores para fins de análise.
Frequentemente me vi precisando de uma maneira rápida de obter múltiplos valores de indicadores sem ter que inicializar o indicador e fazer todas as tarefas entediantes que, muitas vezes, resultam em erros no MetaTrader 5. Com a crescente demanda por dados em MQL5, que se deve à sua capacidade recém-introduzida de lidar com modelos sofisticados de IA e ML, precisamos de maneiras diferentes e eficazes de extrair e visualizar dados de indicadores para fins de análise e treinamento de ML.
Até mais.
Tabela de Anexos
| Nome do arquivo | Descrição/Uso |
|---|---|
| Include\ta-lib.mqh | Biblioteca MQL5 com todo o código dos indicadores discutidos neste artigo. |
| Indicators\Trend Indicators Redefined.mq5 | Um indicador contendo um indicador de média móvel simples implementado para fins de demonstração. |
| Scripts\Custom Indicators test script.mq5 | Um script simples criado para testar e depurar o código dos indicadores. |
Fontes & Referências
- Indicador Índice de Força Relativa (RSI) Explicado com Fórmula
- Média Móvel (MA): Propósito, Usos, Fórmula e Exemplos
- Como usar as Bandas de Bollinger para avaliar tendências
- Indicador SAR Parabólico: Definição, Fórmula, Estratégias de Negociação
- Fórmula do desvio padrão e suas aplicações versus variância
- O que é MACD?
- Oscilador Estocástico: O que É, Como Funciona, Como Calcular
- Fórmula do Average True Range (ATR), O que Significa e Como Usar
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/16931
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.
Algoritmo baseado em fractais - Fractal-Based Algorithm (FBA)
Modelos ocultos de Markov em sistemas de trading com aprendizado de máquina
Redes neurais em trading: Previsão de séries temporais com o auxílio da decomposição modal adaptativa (ACEFormer)
- 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
