Русский
preview
Média Móvel em MQL5 do zero: Simples e acessível

Média Móvel em MQL5 do zero: Simples e acessível

MetaTrader 5Exemplos | 25 abril 2025, 15:07
28 0
Artyom Trishkin
Artyom Trishkin

Conteúdo



Introdução

A média móvel representa o preço médio de um par de moedas em um determinado intervalo de tempo, expresso em número de barras.  Trata-se de um dos indicadores técnicos mais antigos e, talvez, o mais popular e amplamente utilizado, pois serve de base para uma infinidade de outros indicadores.

As médias móveis são frequentemente utilizadas em larga escala para resolver diferentes tarefas práticas. Matematicamente, a média móvel simples é apenas a média aritmética de uma sequência específica de valores numéricos. Na criação de diferentes indicadores, scripts e EAs para o terminal MetaTrader 5, as médias móveis acabam sendo usadas de alguma forma nos cálculos. Para os traders, as médias móveis são uma ferramenta simples e bastante eficaz para determinar a direção das tendências, suavizar pequenas oscilações de preços (ruídos) ou criar estratégias de negociação baseadas em médias móveis e outros indicadores amplamente disponíveis tanto no terminal do cliente quanto no site mql5.com.

É interessante notar que as médias móveis são amplamente usadas não apenas nos mercados financeiros, mas também em outras áreas como meteorologia e economia. Alguns modelos de aprendizado de máquina também utilizam o conceito de médias móveis como uma das características para previsão de séries temporais.
As médias móveis são uma ferramenta poderosa que, quando usada corretamente, pode melhorar significativamente os resultados na negociação e na análise de dados.


Simple Moving Average (SMA) — média móvel simples

A média móvel simples é calculada como a média aritmética de uma quantidade definida de valores numéricos, por exemplo, os preços de fechamento das barras. Em cada ponto de cálculo, os valores da média móvel têm o mesmo peso em relação aos pontos vizinhos da sequência numérica calculada. Em outras palavras, aplicando isso ao indicador SMA, em cada barra da linha do indicador (N), vemos o valor médio das barras anteriores à esquerda (N + N-1 + N-2 + N-3 + N-x) / x, onde x é o período de suavização (quantidade de barras usadas no cálculo).

SMA é:

  • Um método simples de cálculo, fácil de computar e de entender,
  • Devido à sua simplicidade, a SMA pode apresentar atraso em relação às mudanças de preços, especialmente quando se utilizam períodos longos de cálculo,
  • Frequentemente utilizada em conjunto com outros indicadores para confirmar sinais.


Figura 1. Média móvel simples. SMA por preços Close, com período de cálculo 10

Cálculo

O cálculo do indicador SMA com base nos preços de fechamento das barras pode ser expresso assim:

SMA = SUM(CLOSE(i), N) / N 

onde:

  • SUM — soma;
  • CLOSE(i) — preço de fechamento do período atual;
  • N — número de períodos de cálculo.

No indicador, o cálculo da média móvel simples pode ser assim:

double result=0;
for(int j=0; j<period; j++)
   result+=close[i-j];
result/=period;

Aqui:

  • result — variável onde é armazenado o resultado do cálculo da SMA
  • period — período de cálculo da SMA: quantidade de dados na série numérica a ser calculada, neste caso, os preços de fechamento das barras
  • i — índice do laço principal do indicador
  • j — índice do laço para cálculo da média dos preços de fechamento das barras à esquerda da barra com índice i

Ou seja, ao calcular a média para um período de suavização igual a 5, percorremos em um laço a partir da barra com índice i e somamos todos os preços Close das barras com índice i-j (i-0 + i-1 + i-2 + i-3 + i-4).

Após somar todos os preços de fechamento das barras na quantidade definida por period, o resultado obtido é dividido pelo valor de period. O resultado final é a média aritmética comum dos preços Close para period barras.

Vamos ver o código do indicador:

//+------------------------------------------------------------------+
//|                                           SMAonPriceCloseRAW.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1

//--- plot MA
#property indicator_label1  "SMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- input parameters
input int      InpPeriod   =  10;   // SMA Period

//--- indicator buffers
double         MABuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MABuffer,INDICATOR_DATA);
   
//--- успешная инициализация
   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[])
  {
//--- в цикле от значения InpPeriod до текущего бара истории
   for(int i=InpPeriod; i<rates_total; i++)
     {
      //--- рассчитываем среднее цен close за InpPeriod баров
      double result=0;
      for(int j=0; j<InpPeriod; j++)
         result+=close[i-j];
      result/=InpPeriod;
      
      //--- Записываем результат расчёта в буфер
      MABuffer[i]=result;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

Este é um indicador bem simples, que permite visualizar no gráfico os valores médios dos preços Close no período especificado nas configurações para cada barra do histórico (InpPeriod). Os valores são exibidos na forma de uma linha no gráfico de preços.

Para calcular o valor da média de preços no número especificado de barras, é necessário, em um laço a partir da barra atual, também em um laço, somar a quantidade necessária de preços Close e dividir a soma obtida pela quantidade de barras sobre as quais se está buscando a média aritmética.

Assim, percorrendo em um laço desde o início do histórico, para cada barra do laço i calculamos o valor médio dos preços de fechamento das barras à esquerda, no laço j. É justamente por isso que o laço principal não começa do zero, mas sim a partir do valor correspondente à quantidade de barras para as quais se calcula a média — para que haja o número necessário de barras à esquerda no início do cálculo da SMA.

Acima, vimos o código mais simples e não otimizado que mostra o cálculo da média móvel simples. Essa forma de estruturar o laço do indicador faz com que ele recalcule todo o histórico novamente, e em cada barra ainda execute mais um laço para calcular as médias de preços. Com esse tipo de cálculo, cedo ou tarde — e mais provavelmente cedo — veremos no log uma mensagem como esta:

indicator is too slow, 66141 ms. rewrite the indicator, please

Aqui é informado que o indicador está muito lento e que é necessário reescrevê-lo. Naturalmente, ele precisa ser otimizado. E, em primeiro lugar, é preciso realizar um cálculo mais eficiente do indicador.

O arquivo do indicador SMAonPriceCloseRAW.mq5 pode ser encontrado nos arquivos anexados ao artigo.

Otimização dos cálculos

Por cálculo eficiente do indicador entende-se a seguinte sequência de operações:

  • Na primeira execução do indicador (ou em caso de alterações no histórico do símbolo), é realizado o cálculo completo do indicador em todo o histórico disponível. 
  • Após o cálculo completo, todos os dados calculados serão exibidos no gráfico e, a partir daí, será necessário calcular e modificar apenas os dados da barra atual a cada novo tick.

O cálculo do indicador começa quando ocorre o evento Calculate. Neste momento, é chamado o manipulador deste evento OnCalculate().

Normalmente, isso acontece quando chega um novo tick para o símbolo em que o indicador está sendo calculado.

Existem duas formas de definir o manipulador OnCalculate(). Dentro de um único indicador, não é permitido utilizar ambas as formas da função.

Primeira forma de chamada é destinada a indicadores que podem ser calculados em um único buffer de dados.

int OnCalculate (const int rates_total,      // размер массива price[]
                 const int prev_calculated,  // обработано баров на предыдущем вызове
                 const int begin,            // откуда начинаются значимые данные
                 const double& price[]       // массив для расчета
   );

Como array price[], pode ser passada uma das séries temporais de preços, ou então o buffer calculado de algum outro indicador.

A escolha da série temporal ou do indicador necessário para o array price[] é feita pelo usuário na aba "Parameters at start-up of the indicator.

Segunda forma de chamada é destinada a todos os outros indicadores, aqueles que utilizam mais de uma série temporal para o cálculo.

int OnCalculate (const int rates_total,      // размер входных таймсерий
                 const int prev_calculated,  // обработано баров на предыдущем вызове
                 const datetime& time[],     // Time
                 const double& open[],       // Open
                 const double& high[],       // High
                 const double& low[],        // Low
                 const double& close[],      // Close
                 const long& tick_volume[],  // Tick Volume
                 const long& volume[],       // Real Volume
                 const int& spread[]         // Spread
   );
  • Os parâmetros open[], high[], low[] e close[] contêm os arrays com os preços de abertura, máximos, mínimos e de fechamento do timeframe atual.
  • O parâmetro time[] contém o array com os valores do tempo de abertura.
  • O parâmetro spread[] é o array que contém o histórico dos spreads (caso o spread seja aplicável para o instrumento financeiro em questão).
  • Os parâmetros volume[] e tick_volume[] contêm, respectivamente, o histórico do volume de negociação e do volume de ticks.
  • O parâmetro rates_total contém o número de barras disponíveis para o indicador calcular, e corresponde ao número de barras disponíveis no gráfico.
  • O parâmetro prev_calculated , ao chamar a função, carrega o valor retornado pela função OnCalculate() na chamada anterior. Isso permite a implementação de algoritmos eficientes de cálculo do indicador personalizado, evitando recalcular as barras que não sofreram alterações desde a última execução dessa função. Para isso, geralmente basta retornar o valor do parâmetro rates_total, que contém a quantidade de barras no momento da chamada atual da função. Se, desde a última chamada da função OnCalculate(), os dados de preço tiverem sido alterados (por exemplo, carregamento de histórico mais profundo ou preenchimento de lacunas no histórico), o valor do parâmetro de entrada prev_calculated será automaticamente definido como zero pelo terminal.

Como podemos ver, para organizar o cálculo eficiente, precisamos do valor da variável prev_calculated. No primeiro lançamento, ou quando houver alteração nos dados históricos, essa variável conterá o valor zero, e ao controlar isso, podemos organizar o cálculo completo do indicador na primeira execução e, depois disso, calcular apenas a barra atual, uma vez que todo o indicador já terá sido processado e seus valores armazenados no buffer ao longo de todo o histórico.

Como o laço do indicador percorre os dados históricos, começando de um certo número até o valor rates_total-1, sabendo quantas barras foram calculadas na última execução do indicador (esse valor é armazenado na variável prev_calculated), podemos controlar o valor a partir do qual o laço de cálculo deve começar.

Suponhamos que isso seja feito usando a variável start, onde deverá ser armazenado o número da barra a partir da qual se inicia o laço do indicador. No primeiro lançamento, a variável prev_calculated conterá zero. Portanto, podemos iniciar o laço desde zero até o número total de barras do instrumento no qual o indicador foi iniciado.

Mas aqui existe uma observação: para calcular o valor da média móvel, precisamos percorrer o histórico voltando a partir da barra atual no laço, para calcular a média dos preços. Só que, se o laço principal começar do zero, à esquerda da barra zero (início dos dados históricos) não há nada, e não conseguiremos acessar valores de barras inexistentes. Por isso, o laço principal deve começar com um desvio a partir do início do histórico, equivalente à quantidade de barras necessárias para o cálculo da média. E essa quantidade é o período de cálculo do indicador (vamos supor, Period).

A configuração da quantidade de barras a serem calculadas na variável start deve ser feita assim:

//--- Если это первый запуск или изменение в исторических данных
   if(prev_calculated==0)
     {
      //--- инициализируем буфер индикатора пустым значением и
      //--- устанавливаем начало расчёта на значение Period
      ArrayInitialize(MABuffer,EMPTY_VALUE);
      start=Period;
     }
//--- Если это не первый запуск - началом расчёта будет текущий бар
   else
      start=prev_calculated-1;

No primeiro lançamento do indicador, primeiro é gravado no buffer o valor de inicialização. Aqui, é usado o EMPTY_VALUE , que representa um valor vazio do buffer do indicador, que não participa da plotagem. Em seguida, é atribuído à variável start o índice da barra de onde o laço principal do indicador começa. Se não for a primeira execução do indicador, a variável prev_calculated conterá a quantidade de barras já calculadas na chamada anterior do manipulador OnCalculate(). Portanto, nesse caso, como barra inicial para o laço, devemos usar o índice da barra atual, que na grande maioria dos casos será prev_calculated-1.

Como o manipulador OnCalculate() retorna um determinado valor (geralmente rates_total), nós mesmos podemos controlar a quantidade de barras que deve ser calculada na próxima chamada do manipulador. Se retornarmos a quantidade de barras calculadas, armazenada em rates_total, então, na próxima chamada do OnCalculate, esse valor será gravado na variável prev_calculated. Assim, se indicarmos o número da barra de início do laço como prev_calculated-1, na barra atual isso será o índice da própria barra atual. Já na abertura de uma nova barra, será o índice da barra anterior. Dessa forma, indicamos o número da barra para o início do laço:

  • no primeiro lançamento: a partir do valor do período de cálculo do indicador
  • na abertura de uma nova barra: a partir da barra anterior (calculando a barra anterior e a barra atual)
  • na barra atual, a cada novo tick: calculando apenas a barra atual

Vamos ver o código completo do indicador:

//+------------------------------------------------------------------+
//|                                           SMAonPriceCloseECO.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1

//--- plot MA
#property indicator_label1  "SMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- input parameters
input int      InpPeriod   =  10;   // SMA Period

//--- indicator buffers
double         MABuffer[];

//--- global variables
int   ExtPeriod;  // период расчёта SMA
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MABuffer,INDICATOR_DATA);
   
//--- успешная инициализация
   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[])
  {
//--- Корректируем введённое значение периода расчёта SMA
   ExtPeriod=(InpPeriod<1 ? 10 : InpPeriod);
   
//--- Если не хватает исторических данных для расчёта - возвращаем 0
   if(rates_total<ExtPeriod)
      return 0;
      
   int start=0;   // бар начала расчёта
   
//--- Если это первый запуск или изменение в исторических данных
   if(prev_calculated==0)
     {
      //--- инициализируем буфер индикатора пустым значением и
      //--- устанавливаем начало расчёта на значение ExtPeriod
      ArrayInitialize(MABuffer,EMPTY_VALUE);
      start=ExtPeriod;
     }
//--- Если это не первый запуск - началом расчёта будет текущий бар
   else
      start=prev_calculated-1;
      
//--- в цикле от значения start до текущего бара истории
   for(int i=start; i<rates_total; i++)
     {
      //--- рассчитываем среднее цен close за ExtPeriod баров
      double result=0;
      for(int j=0; j<ExtPeriod; j++)
         result+=close[i-j];
      result/=ExtPeriod;
      
      //--- Записываем результат расчёта в буфер
      MABuffer[i]=result;
     }
     
//--- возвращаем количество посчитанных баров для следующего вызова OnCalculate
   return(rates_total);
  }

O arquivo do indicador SMAonPriceCloseECO.mq5 pode ser encontrado nos arquivos anexados ao artigo.

Agora, ao executar o indicador no gráfico de um símbolo, não veremos mais a mensagem de que ele está muito lento. Porém, ainda resta uma questão de otimização: no cálculo do indicador na barra atual, o laço de cálculo da média dos preços para Period barras continua sendo executado. Como a média móvel simples é apenas a soma de uma certa quantidade de barras dividida pela mesma quantidade, podemos eliminar esse laço na barra atual.

Vamos observar como o indicador SMA na versão atual é calculado no histórico. Para exemplificar, vamos mostrar o início do cálculo da média móvel simples com um período de 5 barras.

Ao iniciar, o cálculo do indicador não começa na barra de índice zero, mas sim na barra de índice igual a (quantidade de barras do período de cálculo da SMA) - 1:

O laço principal começa na barra de índice 4. Para calcular o valor da SMA nesta barra, é executado um laço sobre as barras de índice 4, 3, 2, 1 e 0, somando-se os valores de preço dessas barras. Depois, o valor obtido é dividido pela quantidade de períodos de cálculo da SMA, que aqui é 5. Para facilitar os cálculos, na imagem são mostrados valores inteiros simples: 2, 4, 6, 8 e 10 nas respectivas barras como preços. No final, na barra de índice 4, o valor da SMA será 6 = (2+4+6+8+10)/5.

Após o deslocamento do índice do laço principal de cálculo da SMA, novamente é realizado o laço para calcular a SMA na próxima barra de índice 5:

Na próxima iteração do laço principal, novamente é executado um laço interno para calcular a SMA da barra de índice 6:

E assim sucessivamente. A cada deslocamento do índice no laço principal, dentro dos laços internos, são calculados os valores da SMA para cada barra subsequente.
E assim prossegue até que o laço principal atinja a barra atual:


Depois, no cálculo da SMA na barra atual, com a chegada de cada novo tick, será executado o laço interno para o cálculo da SMA na barra atual.

O que é a SMA? É a média aritmética dos preços em um determinado período. Já sabemos que, para calcular o valor da SMA em uma barra, é necessário somar os preços dos últimos Period e dividir essa soma pelo valor do período de cálculo Period. Podemos, ao iniciar o indicador, calcular o primeiro valor da SMA somando em um laço os preços dos últimos Period e dividir o resultado por Period. A partir daí, com o deslocamento da janela móvel de cálculo da SMA para a direita, já não é necessário fazer a soma em laço dos preços anteriores e dividir pela quantidade Period, pois já temos o valor da SMA calculado na barra anterior.

Basta subtrair desse valor o primeiro preço que participou do cálculo da média anterior, adicionar o preço atual e dividir o resultado por Period. Pronto. Ou seja, o primeiro valor da SMA é calculado através da soma em laço dos preços de Period barras e a divisão do total pelo valor de Period. Depois, são realizadas apenas operações aritméticas simples de adição, subtração e divisão:

Cálculo do primeiro valor da SMA:


Depois, ao deslocar o índice do laço principal, fazemos o cálculo:


E em seguida, continuamos da mesma maneira, mas com novos dados:


E a cada deslocamento do índice do laço principal.


A cada vez obtemos o novo valor da SMA a partir do valor já calculado.


Vamos analisar esse indicador:

//+------------------------------------------------------------------+
//|                                              SMAonPriceClose.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1

//--- plot MA
#property indicator_label1  "SMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- input parameters
input int      InpPeriod   =  10;   // SMA Period

//--- indicator buffers
double         MABuffer[];

//--- global variables
int   ExtPeriod;  // период расчёта SMA
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MABuffer,INDICATOR_DATA);
   
//--- успешная инициализация
   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[])
  {
//--- Корректируем введённое значение периода расчёта SMA
   ExtPeriod=(InpPeriod<1 ? 10 : InpPeriod);
   
//--- Если не хватает исторических данных для расчёта - возвращаем 0
   if(rates_total<ExtPeriod)
      return 0;
      
   int start=0;   // бар начала расчёта
   
//--- Если это первый запуск или изменение в исторических данных
   if(prev_calculated==0)
     {
      //--- инициализируем буфер индикатора пустым значением,
      //--- устанавливаем начало расчёта на значение ExtPeriod и
      //--- рассчитываем среднее цен close за ExtPeriod баров для первого значения SMA на баре start-1
      ArrayInitialize(MABuffer,EMPTY_VALUE);
      start=ExtPeriod;
      double value=0;
      for(int i=0; i<start; i++)
         value+=close[i];
      MABuffer[start-1]=value/ExtPeriod;
     }
//--- Если это не первый запуск - началом расчёта будет текущий бар
   else
      start=prev_calculated-1;
      
//--- в цикле от значения start до текущего бара истории
   for(int i=start; i<rates_total; i++)
     {
      //--- определяем цены для расчёта SMA
      double ma_prev=MABuffer[i-1];             // Предыдущее рассчитанное значение SMA
      double price_first=close[i-ExtPeriod];    // Цена close ExtPeriod баров назад
      //--- Записываем в буфер текущее значение SMA, рассчитанное как 
      //--- (прошлое значение SMA + (текущая цена close - цена close ExtPeriod баров назад) / период расчёта SMA ExtPeriod)
      MABuffer[i]=ma_prev+(close[i]-price_first)/ExtPeriod;
     }
     
//--- возвращаем количество посчитанных баров для следующего вызова OnCalculate
   return(rates_total);
  }

O indicador pode ser executado no gráfico e comparado com o SMA padrão, após configurar para ambos os mesmos períodos de cálculo. Esse indicador usa um único laço com extensão igual ao período de cálculo MA Period no início. Em seguida, a partir do primeiro valor da SMA calculado, ele realiza o cálculo dos valores da SMA para todo o histórico do instrumento. Na barra atual, ele realiza o cálculo matemático do valor da SMA a cada novo tick.

O arquivo do indicador SMAonPriceClose.mq5 pode ser encontrado nos arquivos anexados ao artigo.


Exponential Moving Average (EMA) — média móvel exponencial

A média móvel exponencial é definida pela adição a um valor anterior da média móvel de uma certa fração do preço de fechamento atual. Ao utilizar médias móveis exponenciais, as últimas cotações de fechamento recebem maior peso. No cálculo da EMA, os pesos dos preços das barras que participam do cálculo decrescem exponencialmente, com a velocidade controlada pela constante de suavização k (1 > k > 0). Normalmente, k é calculada com base no período de cálculo da média móvel: k = 2.0 / (N + 1), onde N é o número de períodos de cálculo.

EMA:

  • Reage mais rapidamente às mudanças de preço, o que a torna preferida para operações de curto prazo,
  • É mais eficiente para identificar tendências e sinais de Buy e Sell, pois leva em conta dados recentes,
  • Frequentemente usada em cruzamentos com outras EMAs (por exemplo, 50 e 200) para definir momentos de compra ou venda.

Figura 2. Média móvel exponencial. EMA por preços Close, com período de cálculo 10

Cálculo

A média móvel exponencial de P por cento será representada assim:

EMA = (CLOSE(i) * P) + (EMA(i - 1) * (1 - P))

onde:

  • CLOSE(i) — preço de fechamento do período atual;
  • EMA(i - 1) — valor da média móvel do período anterior;
  • P — fração de uso do valor dos preços (constante de suavização).

Vamos escrever um indicador simples que mostre o cálculo da média móvel exponencial:

//+------------------------------------------------------------------+
//|                                           EMAonPriceCloseRAW.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot MA
#property indicator_label1  "EMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- input parameters
input int      InpPeriod   =  10;   // EMA Period

//--- indicator buffers
double         MABuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MABuffer,INDICATOR_DATA);
   
//--- успешная инициализация
   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[])
  {
//--- в цикле от нуля (начало истории) до текущего бара
   for(int i=0; i<rates_total; i++)
     {
      double result=0;
      double smf=2.0/(InpPeriod+1.0);                       // фактор сглаживания
      double prev_value=(i>=1 ? MABuffer[i-1] : close[i]);  // предыдущее рассчитанное значение EMA
      
      //--- рассчитываем EMA на основании цены Close бара, прошлого значения EMA и фактора сглаживания
      result=close[i]*smf+prev_value*(1-smf);
      
      //--- Записываем результат расчёта в буфер
      MABuffer[i]=result;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

Assim como na média móvel simples, aqui é mostrado o cálculo da EMA sem qualquer verificação dos valores inseridos como período de cálculo e sem a organização de um cálculo eficiente do indicador. No primeiro lançamento, o indicador calcula todo o histórico disponível e, depois, a cada novo tick, ele recalcula toda a história novamente. E assim continuamente, o que inevitavelmente levará à mensagem informando que o indicador está muito lento.

O indicador EMAonPriceCloseRAW.mq5 pode ser encontrado nos arquivos anexados ao artigo.

Otimização dos cálculos

Vamos tornar o cálculo do indicador mais eficiente. No primeiro lançamento ele calculará todo o histórico, e depois, a cada novo tick, recalculará apenas a barra atual:

//+------------------------------------------------------------------+
//|                                              EMAonPriceClose.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot MA
#property indicator_label1  "EMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- input parameters
input int      InpPeriod   =  10;   // EMA Period

//--- indicator buffers
double         MABuffer[];

//--- global variables
int   ExtPeriod;  // период расчёта EMA
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MABuffer,INDICATOR_DATA);
   
//--- успешная инициализация
   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[])
  {
//--- Корректируем введённое значение периода расчёта EMA
   ExtPeriod=(InpPeriod<1 ? 10 : InpPeriod);
   
//--- Если не хватает исторических данных для расчёта - возвращаем 0
   if(rates_total<ExtPeriod)
      return 0;
      
   int start=0;   // бар начала расчёта
   
//--- Если это первый запуск или изменение в исторических данных
   if(prev_calculated==0)
     {
      //--- инициализируем буфер индикатора пустым значением и устанавливаем начало расчёта на значение 0
      ArrayInitialize(MABuffer,EMPTY_VALUE);
      start=0;
     }
//--- Если это не первый запуск - началом расчёта будет текущий бар
   else
      start=prev_calculated-1;
      
//--- в цикле от значения start до текущего бара истории
   for(int i=start; i<rates_total; i++)
     {
      double result=0;
      double smf=2.0/(ExtPeriod+1.0);                       // фактор сглаживания
      double prev_value=(i>=1 ? MABuffer[i-1] : close[i]);  // предыдущее рассчитанное значение EMA
      
      //--- рассчитываем значение EMA для текущего бара цикла
      result=close[i]*smf+prev_value*(1-smf);
      
      //--- Записываем результат расчёта в буфер
      MABuffer[i]=result;
     }
     
//--- возвращаем количество посчитанных баров для следующего вызова OnCalculate
   return(rates_total);
  }

Se for inserido um valor de período de cálculo menor que 1, definimos o valor padrão para médias móveis como 10.
O cálculo da média móvel exponencial usa o valor da EMA calculado na barra anterior.

No primeiro lançamento, esse cálculo ainda não foi realizado, então usamos como dados iniciais o valor do preço de fechamento Close.

Neste indicador foi implementado um cálculo eficiente dos dados: no primeiro lançamento, é calculado todo o histórico disponível, e nas chamadas subsequentes do OnCalculate(), apenas a barra atual é recalculada.

O arquivo do indicador EMAonPriceClose.mq5 pode ser encontrado nos arquivos anexados ao artigo.


Smoothed Moving Average (SMMA) — média móvel suavizada

A média móvel suavizada, diferentemente da média móvel simples, é menos sensível às flutuações de preço, atribuindo maior importância à direção geral do movimento dos preços.

SMMA:

  • É menos suscetível a flutuações do que a SMA e a EMA, o que a torna útil para analisar tendências mais estáveis,
  • É adequada para análises de longo prazo, pois suaviza oscilações abruptas nos preços,
  • Pode ser usada para formar sinais de negociação mais confiáveis.

Figura 3. Média móvel suavizada. SMMA por preços Close, com período de cálculo 10

Cálculo

O primeiro valor da média móvel suavizada é calculado como uma média móvel simples (SMA):

SUM1  = SUM(CLOSE(i), N)
SMMA1 = SUM1 / N 

O segundo valor é calculado pela fórmula a seguir:

SMMA(i) = (SMMA1*(N-1) + CLOSE(i)) / N

Todos os valores subsequentes da média móvel são calculados pela fórmula:

PREVSUM = SMMA(i - 1) * N
SMMA(i) =(PREVSUM - SMMA(i - 1) + CLOSE(i)) / N 

onde:

  • SUM — soma;
  • SUM1 — soma dos preços de fechamento dos N períodos, contados a partir da barra anterior;
  • PREVSUM — soma suavizada da barra anterior;
  • SMMA(i-1) — média móvel suavizada da barra anterior;
  • SMMA(i) — média móvel suavizada da barra atual (exceto o primeiro);
  • CLOSE(i) — preço de fechamento atual;
  • N — período de suavização.

Após transformações aritméticas, a fórmula pode ser simplificada:

SMMA(i) = (SMMA(i - 1) * (N - 1) + CLOSE(i)) / N 

Vamos escrever um indicador simples que calcula a média móvel suavizada:

//+------------------------------------------------------------------+
//|                                          SMMAonPriceCloseRAW.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1

//--- plot MA
#property indicator_label1  "SMMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- input parameters
input int      InpPeriod=10;  // SMMA Period

//--- indicator buffers
double         MABuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MABuffer,INDICATOR_DATA);
   
//---
   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[])
  {
//---
   double result=0.0;
   for(int i=InpPeriod-1; i<rates_total; i++)
     {
      //--- первый расчёт
      if(i==InpPeriod-1)
        {
         //--- рассчитаем простую скользящую среднюю для InpPeriod первых баров
         for(int j=0; j<InpPeriod; j++)
           {
            double price=close[i-j];
            result+=price;
           }
         result/=InpPeriod;
         //--- записываем первое отображаемое значение SMMA, рассчитанное как SMA
         MABuffer[InpPeriod-1]=result;
        }
      //--- все последующие расчёты
      else
         result=(MABuffer[i-1]*(InpPeriod-1)+close[i])/InpPeriod;
      
      //--- Записываем результат расчёта в буфер
      MABuffer[i]=result;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

O indicador apenas exibe o cálculo da SMMA, recalculando completamente todos os barras em todo o histórico disponível tanto na primeira execução quanto a cada novo tick. Isso não é otimizado nem correto, pois o indicador ficará muito lento. É necessário otimizar seus cálculos.

Otimização dos cálculos

É necessário implementar a verificação do valor inserido para o período de cálculo da SMMA, realizar o cálculo completo do histórico na primeira execução e, depois, a cada novo tick, calcular apenas a barra atual:

//+------------------------------------------------------------------+
//|                                             SMMAonPriceClose.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot MA
#property indicator_label1  "SMMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- input parameters
input int      InpPeriod=10;

//--- indicator buffers
double         MABuffer[];

//--- global variables
int   ExtPeriod;  // период расчёта SMMA
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MABuffer,INDICATOR_DATA);
   
//--- успешная инициализация 
   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[])
  {
//--- Корректируем введённое значение периода расчёта SMMA
   ExtPeriod=(InpPeriod<1 ? 10 : InpPeriod);
   
//--- Если не хватает исторических данных для расчёта - возвращаем 0
   if(rates_total<ExtPeriod)
      return 0;
      
   double result=0;
   int    start =0;
   
//--- Если это первый запуск или изменение в исторических данных
   if(prev_calculated==0)
     {
      //--- инициализируем буфер индикатора пустым значением и устанавливаем начало расчёта на значение ExtPeriod
      ArrayInitialize(MABuffer,EMPTY_VALUE);
      start=ExtPeriod;

      //--- рассчитаем простую скользящую среднюю для ExtPeriod первых баров
      for(int i=0; i<start; i++)
         result+=close[i];
      result/=ExtPeriod;
      //--- записываем первое отображаемое значение SMMA, рассчитанное как SMA
      MABuffer[start-1]=result;
     }
   else
      start=prev_calculated-1;
      
//--- в цикле от значения start до текущего бара истории
//--- рассчитываем значение SMMA для текущего бара цикла
   for(int i=start; i<rates_total; i++)
      MABuffer[i]=(MABuffer[i-1]*(ExtPeriod-1)+close[i])/ExtPeriod;
      
//--- возвращаем количество посчитанных баров для следующего вызова OnCalculate
   return(rates_total);
  }

Agora o indicador calculará de forma eficiente o histórico e a barra atual. O arquivo do indicador SMMAonPriceClose.mq5 pode ser encontrado nos arquivos anexados ao artigo.


Linear Weighted Moving Average (LWMA) — média móvel linearmente ponderada

Na média móvel ponderada, os dados mais recentes recebem peso maior, enquanto os dados mais antigos recebem peso menor. Isso permite que a LWMA seja mais sensível às mudanças recentes nos preços. Nesta média móvel, o peso dos preços dos barras diminui linearmente: para a barra zero (barra atual) o peso é máximo e para a barra de número N-1 o peso é zero.

LWMA:

  • Reage mais rapidamente às mudanças de preço em comparação com a SMA tradicional,
  • Permite analisar dados de maneira que as mudanças mais recentes tenham o maior impacto nos cálculos,
  • Pode ser usada na criação de diversas estratégias de negociação, especialmente em condições de alta volatilidade.

Figura 4. Média móvel linearmente ponderada. LWMA por preços Close, com período de cálculo 10

Cálculo

A média móvel ponderada é calculada multiplicando cada preço de fechamento da sequência considerada por um determinado coeficiente de peso:

LWMA = SUM(CLOSE(i) * i, N) / SUM(i, N) 

onde:

  • SUM — soma;
  • CLOSE(i) — preço de fechamento atual;
  • SUM(i, N) — soma dos coeficientes de peso;
  • N — período de suavização.

Vamos escrever um indicador simples que mostre o cálculo da média móvel linearmente ponderada:

//+------------------------------------------------------------------+
//|                                          LWMAonPriceCloseRAW.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot MA
#property indicator_label1  "LWMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input int      InpPeriod=10;  // LWMA Period
//--- indicator buffers
double         MABuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MABuffer,INDICATOR_DATA);
   
//---
   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[])
  {
//--- в цикле от InpPeriod-1 до текущего бара
   double result=0.0;
   for(int i=InpPeriod-1; i<rates_total; i++)
     {
      //--- рассчитываем веса (wsum) и сумму весовых коэффициентов (sum) InpPeriod баров
      double sum =0.0;
      int    wsum=0;
      for(int j=InpPeriod; j>0; j--)
        {
         wsum+=j;
         sum +=close[i-j+1]*(InpPeriod-j+1);
        }
      //--- получаем значение LWMA для текущего бара цикла
      result=sum/wsum;
      //--- Записываем результат расчёта в буфер
      MABuffer[i]=result;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

O indicador exibe no gráfico o resultado do cálculo da LWMA para cada barra do histórico. O recálculo completo de todos os dados históricos acontece a cada novo tick. Isso torna o cálculo do indicador muito lento e nada otimizado, por isso vamos otimizar o processo realizando um cálculo mais eficiente e adicionando a verificação dos parâmetros de entrada inseridos.

O arquivo do indicador LWMAonPriceCloseRAW.mq5 pode ser encontrado nos arquivos anexados ao artigo.

Otimização dos cálculos

Vamos otimizar o cálculo do indicador para que não haja recálculo de todo o histórico a cada novo tick, e também vamos incluir a verificação do valor inserido para o período de cálculo da LWMA:

//+------------------------------------------------------------------+
//|                                             LWMAonPriceClose.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot MA
#property indicator_label1  "LWMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- input parameters
input int      InpPeriod   =  10;   // LWMA Period

//--- indicator buffers
double         MABuffer[];

//--- global variables
int   ExtPeriod;  // период расчёта LWMA
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MABuffer,INDICATOR_DATA);
   
//--- успешная инициализация
   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[])
  {
//--- Корректируем введённое значение периода расчёта LWMA
   ExtPeriod=(InpPeriod<1 ? 10 : InpPeriod);
   
//--- Если не хватает исторических данных для расчёта - возвращаем 0
   if(rates_total<ExtPeriod)
      return 0;
      
   double result=0;
   int    start =0;
   
//--- Если это первый запуск или изменение в исторических данных
   if(prev_calculated==0)
     {
      //--- инициализируем буфер индикатора пустым значением и устанавливаем начало расчёта на значение ExtPeriod-1
      ArrayInitialize(MABuffer,EMPTY_VALUE);
      start=ExtPeriod-1;
     }
//--- Если это не первый запуск - началом расчёта будет текущий бар
   else
      start=prev_calculated-1;
      
//--- в цикле от значения start до текущего бара истории
//--- рассчитываем значение LWMA для текущего бара цикла
   for(int i=start; i<rates_total; i++)
     {
      //--- рассчитываем веса (wsum) и сумму весовых коэффициентов (sum) ExtPeriod баров
      double sum =0.0;
      int    wsum=0;
      for(int j=ExtPeriod; j>0; j--)
        {
         wsum+=j;
         sum +=close[i-j+1]*(ExtPeriod-j+1);
        }
      //--- получаем значение LWMA для текущего бара цикла
      result=sum/wsum;
      //--- Записываем результат расчёта в буфер
      MABuffer[i]=result;
     }
      
//--- возвращаем количество посчитанных баров для следующего вызова OnCalculate
   return(rates_total);
  }

Os princípios do cálculo eficiente de indicadores foram detalhados na seção de otimização da média móvel simples.

O arquivo do indicador pode ser consultado nos anexos do artigo.


Vantagens e desvantagens dos quatro tipos de médias

Com o tempo, surgiram vários tipos de médias móveis, como a simples, exponencial, ponderada e muitas outras, utilizando tanto seus próprios métodos de cálculo quanto adaptações baseadas na SMA. Cada uma serve a propósitos diferentes e pode abrir novas perspectivas interessantes na análise dos dados.

Aqui estão, de forma resumida, as vantagens e desvantagens das quatro médias móveis básicas:

  1. SMA (média móvel simples) é frequentemente usada para determinar a direção geral da tendência e identificar níveis de suporte e resistência. É popular entre traders e investidores de longo prazo porque suaviza as flutuações de preço, permitindo uma visão mais clara da tendência principal.

    Vantagens:
    • Facilidade de cálculo e interpretação,
    • Suaviza as flutuações de preço, oferecendo uma visão mais limpa das tendências,
    • Útil para identificar tendências de longo prazo.

    Desvantagens:
    • Reage lentamente às mudanças, o que pode resultar em sinais atrasados,
    • É igualmente sensível a todas as flutuações de preço dentro do período de cálculo (os pesos de todos os preços são iguais).

  2. EMA (média móvel exponencial) dá maior peso aos preços mais recentes, tornando-a mais sensível às novas mudanças de preço. É usada para sinais mais rápidos de abertura e fechamento de posições. É preferida por traders de curto prazo e scalpers que buscam entradas e saídas rápidas no mercado.

    Vantagens:
    • Focada em uma resposta mais rápida às mudanças de preço devido ao maior peso dado aos dados mais recentes,
    • Geralmente usada em conjunto com outros indicadores para sinais mais precisos,
    • Fornece informações mais atualizadas sobre a tendência atual.

    Desvantagens:
    • Pode gerar sinais falsos durante oscilações bruscas do mercado,
    • Mais complexa de calcular em comparação à SMA.

  3. SMMA (média móvel suavizada) é considerada uma versão mais suavizada da EMA e da SMA, permitindo evitar flutuações abruptas enquanto mantém a relevância das informações. É adequada para traders que desejam evitar sinais falsos e é prática para a análise e confirmação de tendências.

    Vantagens:
    • Suaviza os dados de forma mais intensa em comparação à SMA e EMA,
    • É menos suscetível a oscilações, o que pode ser útil em mercados instáveis,
    • Preserva a informação dos valores anteriores, permitindo uma melhor análise de tendências.

    Desvantagens:
    • Pode reagir lentamente às mudanças do mercado, de forma semelhante à SMA,
    • Podem ocorrer atrasos na identificação de tendências.

  4. LWMA (média móvel linearmente ponderada) atribui diferentes influências a cada valor de preço dependendo da sua antiguidade, dando mais peso aos dados mais recentes. É aplicada para análises mais detalhadas (por exemplo, em estratégias que usam múltiplos timeframes), quando os traders querem reagir mais rapidamente às mudanças.

    Vantagens:
    • Atribui maior peso aos preços mais recentes, permitindo refletir com mais precisão as últimas mudanças,
    • É mais flexível em comparação à SMA e EMA, o que permite reagir melhor a novos dados,
    • Pode ser útil para estratégias de curto prazo.

    Desvantagens:
    • É mais complexa de calcular, especialmente se comparada à SMA e EMA,
    • Também pode gerar sinais falsos em mercados instáveis.



Considerações finais

Exploramos os princípios de cálculo dos principais tipos de médias móveis disponíveis nas configurações do indicador padrão Moving Average no terminal cliente. Os cálculos apresentados neste artigo podem ser usados tanto em indicadores com otimização de cálculos (como também demonstrado no artigo) quanto como códigos independentes para calcular médias de conjuntos sequenciais de dados em seus próprios programas.

Na imagem acima, foi mostrada a diferença entre médias móveis com o mesmo período de cálculo (10), mas de tipos diferentes:

Vermelha - SMA, verde - EMA, dourada - SMMA, azul - LWMA.

É possível ver que a média móvel suavizada é a menos afetada por pequenas flutuações de preço e mostra de maneira mais clara a tendência geral do movimento dos preços.
As médias móveis exponencial e linearmente ponderada reagem de maneira mais intensa às oscilações do mercado, pois em seus cálculos o maior peso é atribuído aos dados mais recentes.

Resumindo:

A média móvel (SMA) é um método estatístico usado para analisar séries temporais e suavizar dados, permitindo identificar tendências e movimentos direcionais de curto prazo, níveis dinâmicos de suporte/resistência, limites de canais e assim por diante. As primeiras aplicações da média móvel remontam ao início do século XX, quando economistas e engenheiros começaram a usá-la para analisar dados e prever valores futuros. Curiosamente, durante a Segunda Guerra Mundial, os cálculos das baterias antiaéreas para a orientação de alvos utilizavam métodos de cálculo da SMA.

As médias móveis ganharam ampla popularidade na análise financeira, especialmente com o desenvolvimento do comércio nos mercados acionários, em meados do século XX. Nesse período, os investidores começaram a buscar métodos que permitissem suavizar as flutuações dos preços das ações e identificar tendências de longo prazo. Desde então, as médias móveis se tornaram uma ferramenta padrão da análise técnica, considerada tanto por traders quanto por analistas.

No mesmo gráfico de preços, médias móveis com o mesmo período de cálculo, mas de tipos diferentes, exibirão os dados de formas distintas:

  • A SMA será mais suave e mostrará níveis de suporte ou resistência, mas com atraso,
  • A EMA seguirá mais de perto os preços, ficando próxima ao preço e reagindo mais rapidamente às mudanças de tendência,
  • A SMMA representará uma linha ainda mais suavizada que a SMA, com menor resposta a alterações bruscas,
  • A LWMA também reagirá rapidamente às mudanças, mas seu comportamento será mais volátil em comparação à EMA e à SMMA.

A escolha entre esses tipos de médias móveis depende da estratégia específica e das condições de mercado. É importante considerar seus objetivos de negociação, os prazos e a volatilidade do ativo ao usar médias móveis nas operações. Muitas vezes, os traders combinam diferentes tipos de médias móveis para maximizar a eficácia da análise.


Tabela-lista dos arquivos anexados:

#
Tipo
Nome 
 Descrição
1
Indicador
SMAonPriceCloseRAW.mq5
Indicador com exemplo de cálculo da SMA. Apenas cálculo bruto, sem organização de cálculo eficiente e sem otimização dos cálculos.
2
Indicador
SMAonPriceCloseECO.mq5
Indicador que calcula a SMA. Organização de cálculo eficiente sem otimização dos cálculos.
3
Indicador
SMAonPriceClose.mq5
Indicador que calcula a SMA. Organização de cálculo eficiente com otimização dos cálculos da SMA.
4
Indicador
EMAonPriceCloseRAW.mq5
Indicador com exemplo de cálculo da EMA. Apenas cálculo bruto, sem organização de cálculo eficiente.
5
Indicador
EMAonPriceClose.mq5
Indicador que calcula a EMA. Organização de cálculo eficiente.
6
Indicador
SMMAonPriceCloseRAW.mq5
Indicador com exemplo de cálculo da SMMA. Apenas cálculo bruto, sem organização de cálculo eficiente.
7
Indicador
SMMAonPriceClose.mq5
Indicador que calcula a SMMA. Organização de cálculo eficiente.
8
Indicador
LWMAonPriceCloseRAW.mq5
Indicador com exemplo de cálculo da LWMA. Apenas cálculo bruto, sem organização de cálculo eficiente.
9
Indicador
LWMAonPriceClose.mq5
Indicador que calcula a LWMA. Organização de cálculo eficiente.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/16308

Redes neurais em trading: Otimizando Transformer para previsão de séries temporais (LSEAttention) Redes neurais em trading: Otimizando Transformer para previsão de séries temporais (LSEAttention)
O framework LSEAttention propõe caminhos para aprimorar a arquitetura Transformer, tendo sido desenvolvido especificamente para a previsão de séries temporais multivariadas de longo prazo. As abordagens sugeridas pelos autores do método permitem resolver problemas comuns no Transformer tradicional, como o colapso entrópico e a instabilidade no treinamento.
Análise volumétrica com redes neurais como chave para tendências futuras Análise volumétrica com redes neurais como chave para tendências futuras
O artigo explora a possibilidade de melhorar a previsão de preços com base na análise do volume de negociações, integrando os princípios da análise técnica com a arquitetura de redes neurais LSTM. Dá-se atenção especial à identificação e interpretação de volumes anômalos, uso de clusterização e criação de características baseadas em volume, além de sua definição no contexto de aprendizado de máquina.
Reimaginando Estratégias Clássicas (Parte VII): Mercados de Forex e Análise da Dívida Soberana no USDJPY Reimaginando Estratégias Clássicas (Parte VII): Mercados de Forex e Análise da Dívida Soberana no USDJPY
No artigo de hoje, analisaremos a relação entre as taxas de câmbio futuras e os títulos do governo. Os títulos estão entre as formas mais populares de títulos de renda fixa e serão o foco da nossa discussão. Junte-se a nós enquanto exploramos se podemos melhorar uma estratégia clássica usando IA.
Testador rápido de estratégias de trading em Python usando Numba Testador rápido de estratégias de trading em Python usando Numba
O artigo apresenta um testador rápido de estratégias para modelos de aprendizado de máquina com o uso do Numba. Em termos de velocidade, ele supera o testador de estratégias feito em Python puro em 50 vezes. O autor recomenda o uso dessa biblioteca para acelerar cálculos matemáticos, especialmente em casos que envolvem laços.