English Русский 中文 Español Deutsch 日本語
preview
Testando o conteúdo informativo de diferentes tipos de médias móveis

Testando o conteúdo informativo de diferentes tipos de médias móveis

MetaTrader 5Testador | 29 janeiro 2024, 11:12
350 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Introdução

Em um dos meus artigos anteriores, examinamos os tipos mais populares de médias móveis (simples, ponderadas, exponenciais): "Como desenvolver sistemas baseados em médias móveis". Aqui, continuaremos esse tema e compararemos os resultados da média móvel simples com os resultados de outros tipos de médias móveis. Muitos traders usam médias móveis de diferentes tipos de acordo com suas preferências. Dito isso, neste artigo, vamos examinar detalhadamente os diferentes tipos de médias móveis, testar sua eficácia e comparar os resultados para determinar qual tipo funciona melhor.

Para os propósitos deste artigo, criaremos um aplicativo simples para testar médias móveis no testador de estratégias embutido do MetaTrader 5. Para entender o que considerar ao estudar os resultados do teste, leia meu artigo anterior "Domine e utilize o testador de estratégias MQL5 de forma eficiente". Nele, você pode encontrar muitas informações úteis.

Vamos considerar os seguintes tópicos:

Observe: embora eu tente otimizar as configurações de cada média móvel para obter os melhores resultados, é necessário que você realize uma verificação adicional e teste por conta própria. Este artigo é escrito exclusivamente para fins educacionais. Por isso, você deve testar, otimizar e encontrar as melhores configurações que podem lhe oferecer os melhores resultados. Pode acontecer que um ou todos esses tipos não se adequem ao seu estilo de trading. Mas espero que você encontre ideias que ajudem a melhorar sua negociação. Sempre verifique a eficácia de qualquer estratégia de trading antes de usá-la em uma conta real.

Atenção! Todo o conteúdo deste artigo é fornecido "como está", destinado apenas para fins educacionais e não é uma recomendação de trading. O artigo não oferece garantias de resultados. Tudo o que você aplicar na prática com base neste artigo, você faz exclusivamente por sua conta e risco, o autor não garante nenhum resultado.

Testando um sistema baseado em Média Móvel Simples (SMA)

Nesta parte, compartilharei os resultados de um sistema simples baseado apenas na Média Móvel Simples. Ela identifica o cruzamento do preço e a linha da média móvel, gerando sinais de compra e venda. Criaremos um sistema que possa executar automaticamente negociações com base nesses sinais.

Para realizar operações de trading, usaremos os seguintes sinais:


Sinal de compra:

O preço de fechamento é maior que o valor da Média Móvel Simples.

E também: o preço de fechamento anterior é menor que o valor anterior da Média Móvel Simples.

Sinal de venda:

O preço de fechamento é menor que o valor da Média Móvel Simples.

E também: o preço de fechamento anterior é maior que o valor anterior da Média Móvel Simples.

Você pode aprender mais sobre a Média Móvel Simples e outros tipos deste popular indicador em um dos meus artigos anteriores "Como desenvolver sistemas baseados em médias móveis".

Abaixo estão os passos para criar esse tipo de sistema de trading, que pode executar automaticamente ordens de compra e venda com base nos sinais mencionados.

Em um nível global, adicionaremos ao programa um arquivo Trade para executar ordens com base em nossos sinais usando o pré-processador #include. No artigo "Tudo que você precisa saber sobre a estrutura do programa MQL5", você pode aprender mais sobre o pré-processador.

#include <Trade\Trade.mqh>

Vamos criar três entradas personalizadas para a variável double lotSize, a variável ENUM_TIMEFRAMES timeFrame, e a variável inteira MAPeriod, que podem ser alteradas conforme a vontade do usuário, definindo valores padrão para elas:

input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;

Criamos duas variáveis inteiras simpleMA e barTotal sem atribuição, pois vamos defini-las mais tarde na parte OnInit().

int simpleMA;
int barsTotal;

Vamos criar trade como um objeto da classe CTrade para acesso rápido às funções de trading.

CTrade trade;

Em OnInit(), definiremos simpleMA usando a função iMA para retornar o handle do indicador de média móvel, e seus parâmetros:

  • symbol - nome do símbolo; para o símbolo atual é _Symbol
  • period - timeframe utilizado. Por padrão é 1 hora
  • ma_period - período da média móvel simples. Por padrão é 50
  • ma_shift - para deslocamento horizontal usamos 0 
  • applied_price - tipo de preço; para calcular a média móvel simples, usamos o preço de fechamento.
simpleMA = iMA(_Symbol, timeFrame, MAPeriod, 0, MODE_SMA, PRICE_CLOSE);

E definimos barTotal usando a função iBars para retornar o número de barras. Seus parâmetros:

  • symbol - símbolo. O símbolo atual é (_Symbol)
  • timeframe - período utilizado. Por padrão é 1 hora
   barsTotal=iBars(_Symbol,timeFrame);

Em OnTick(), criaremos dois arrays: um para preços usando MqlRates para armazenar informações sobre preços, volumes e spreads, e outro para a média móvel simples:

   MqlRates priceArray[];
   double mySMAArray[];

Se definirmos a flag AS_SERIES para esses dois arrays criados usando a função ArraySetAsSeries, seus parâmetros serão:

  • array[] - especifica o array por referência
  • flag - especifica a direção da indexação do array
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(mySMAArray,true);

Definição de preços Ask e Bid após criar duas variáveis double a partir deles

   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);

Obtemos dados históricos MqlRates usando a função CopyRates. Seus parâmetros:

  • symbol_name - nome do símbolo
  • timeframe - período gráfico
  • start_pos - posição inicial
  • count - quantidade de dados para copiar
  • rates_array[] - array de destino para a cópia
int Data=CopyRates(_Symbol,_Period,0,3,priceArray);

Obtemos dados do buffer do indicador usando a função CopyBuffer. Seus parâmetros:

  • indicator_handle - identificador do indicador, aqui é simpleMA
  • buffer_num - número do buffer do indicador, igual a 0
  • start_pos - posição de início do cálculo, 0 é a vela atual
  • count - volume copiado, igual a 3
  • buffer[]: array de destino, que precisamos copiar, ou seja, mySMAArray
CopyBuffer(simpleMA,0,0,3,mySMAArray);

Definiremos o último preço de fechamento e o valor da média móvel simples da mesma vela após criar duas variáveis double desses dois valores.

   double lastClose=(priceArray[1].close);
   double SMAVal = NormalizeDouble(mySMAArray[1],_Digits);

Definiremos o preço de fechamento anterior e o valor da média móvel simples da mesma vela após criar duas variáveis double desses dois valores.

   double prevClose=(priceArray[2].close);
   double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);

Criaremos uma variável inteira bars para comparação com a variável barsTotal criada.

int bars=iBars(_Symbol,timeFrame);

Verificamos a existência de um novo barra através da verificação do valor de barsTotal; se ele não for igual a bars.

if(barsTotal != bars)

Se o valor de barsTotal não for igual a bars, precisamos atualizar o valor de BarsTotal, atribuindo o valor de bars.

barsTotal=bars;

Se barsTotal não for igual a bars, também precisamos verificar nossas condições de estratégia, se o fechamento anterior for menor que o valor da média móvel simples da mesma vela e ao mesmo tempo o último preço de fechamento for maior que a média móvel simples da mesma vela. Precisamos que o programa feche a posição aberta atual e abra uma posição de compra.

      if(prevClose<prevSMAVal && lastClose>SMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }

Se o fechamento anterior for maior que o valor da média móvel simples da mesma vela e ao mesmo tempo o último preço de fechamento for menor que a média móvel simples da mesma vela. Precisamos que o programa feche a posição aberta atual e abra uma posição de venda.

      if(prevClose>prevSMAVal && lastClose<SMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }

Em seguida, compilaremos o código e veremos que ele é compilado sem erros ou avisos.

A seguir, o código completo em um bloco:

//+------------------------------------------------------------------+
//|                                                   SMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
int simpleMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   simpleMA = iMA(_Symbol, timeFrame, MAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double mySMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(mySMAArray,true);
   int Data=CopyRates(_Symbol,_Period,0,3,priceArray);
   CopyBuffer(simpleMA,0,0,3,mySMAArray);
   double lastClose=(priceArray[1].close);
   double SMAVal = NormalizeDouble(mySMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(prevClose<prevSMAVal && lastClose>SMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(prevClose>prevSMAVal && lastClose<SMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

Compilaremos o EA e executaremos no EURUSD para testar a estratégia com base no histórico. O período de teste será de 1 de janeiro a 30 de junho de 2022, como para todos os tipos mencionados de médias móveis. Nossas configurações para SMA serão as seguintes:

  • Tamanho do lote: 1
  • Timeframe: 1 hora
  • Período MA: 50

Resultados do teste:

Resultados do SMA

Estamos especialmente interessados nos seguintes indicadores:

  • Lucro líquido: 2700.30 (27%)
  • Rebaixamento relativo do saldo: 37.07%
  • Rebaixamento relativo dos fundos: 41.76%
  • Fator de lucro: 1.10
  • Expectativa de ganho: 12.68
  • Fator de recuperação: 0.45
  • Índice de Sharpe: 0.57

Média Móvel Adaptativa (iAMA)

A Média Móvel Adaptativa (iAMA, também conhecida como KAMA) foi desenvolvida por Perry Kaufman. A ideia principal é reduzir o ruído no movimento dos preços. Ela segue o movimento do preço, independentemente de sua volatilidade, e se adapta a ele. Trata-se de um indicador de tendência, por isso pode ser usado para determinar a tendência e os pontos de reversão.

O indicador é calculado em várias etapas.

Primeira etapa: Cálculo da AMA ou KAMA

Etapa 1

Segunda etapa: Cálculo do coeficiente de suavização (SC)

Etapa 2

Terceira etapa: cálculo do coeficiente de eficiência (ER)

Etapa 3

Agora sabemos como calcular manualmente o indicador AMA, mas não precisamos disso, pois podemos inseri-lo automaticamente no MetaTrader 5, selecionando-o entre os indicadores prontos disponíveis. Chegou a hora de criar um sistema de trading que possa executar ordens de compra e venda com base no cruzamento do preço de fechamento e do indicador AMA. Usaremos os seguintes sinais para nossa estratégia.

Sinal de compra:

O preço de fechamento é maior que a média móvel adaptativa.

E também: o preço de fechamento anterior é menor que o valor anterior da média móvel adaptativa

Sinal de venda:

O preço de fechamento é menor que o valor da média móvel adaptativa.

E também: o preço de fechamento anterior é maior que o valor anterior da média móvel adaptativa

A seguir, o código completo para criar esse tipo de sistema de trading:

//+------------------------------------------------------------------+
//|                                                  iAMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
input int fastMAPeriod= 5;
input int slowMAPeriod= 100;
int adaptiveMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   adaptiveMA = iAMA(_Symbol, timeFrame, MAPeriod,fastMAPeriod,slowMAPeriod, 0, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double myAMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(myAMAArray,true);
   int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray);
   CopyBuffer(adaptiveMA,0,0,3,myAMAArray);
   double lastClose=(priceArray[1].close);
   double AMAVal = NormalizeDouble(myAMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevAMAVal = NormalizeDouble(myAMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(lastClose>AMAVal && prevClose<prevAMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(lastClose<AMAVal && prevClose>prevAMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

A diferença deste código está no uso da função iAMA, que retorna o handle do indicador de média móvel adaptativa. Seus parâmetros:

  • symbol - nome do símbolo; para o símbolo atual é _Symbol
  • period - timeframe utilizado. Por padrão é 1 hora
  • ama_period - período da média móvel adaptativa
  • fast_ma_period - período da média móvel rápida
  • slow_ma_period - período da média móvel lenta
  • ama_shift - para deslocamento horizontal, usamos 0
  • applied_price - tipo de preço usado para cálculo; usamos o preço de fechamento

Vamos testar o indicador AMA no mesmo período para ver seus resultados:

  • Tamanho do lote = 1
  • Timeframe = 1 hora
  • MAperiod = 50
  • MA rápida = 5
  • MA lenta = 100

Resultados:

Resultados do AMA

Estamos especialmente interessados nos seguintes indicadores:

  • Lucro líquido: 3638.20 (36.39%)
  • Rebaixamento relativo do saldo: 22.48%
  • Rebaixamento relativo dos fundos: 35.53%
  • Fator de lucro: 1.31
  • Expectativa de ganho: 35.67
  • Fator de recuperação: 0.65
  • Índice de Sharpe: 0.86

Média Móvel Exponencial Dupla (iDEMA)

Esta variação da média móvel foi desenvolvida por Patrick Mulloy. O objetivo principal deste indicador é reduzir o atraso da EMA, mas torná-la mais sensível ao movimento do mercado.

Este indicador pode ser usado para determinar a tendência ou pontos de reversão da tendência, identificando a posição dos preços em relação a essa média móvel. As etapas para calcular o indicador são mostradas abaixo:

1. Cálculo da primeira média móvel exponencial (EMA)

EMA one = EMA do n-ésimo período de preço.

2. Cálculo da EMA da EMA one

EMA two = EMA da EMA one

3. Cálculo da DEMA

DEMA = (2 * EMA one) - EMA two

Não precisamos fazer esses cálculos manualmente. Eles são úteis para entender melhor o indicador, mas temos este indicador da mesma forma que muitos indicadores técnicos no MetaTrader 5. Agora precisamos criar o mesmo sistema de trading que fizemos anteriormente, mas usando DEMA. Este sistema de trading executará as mesmas ordens de compra e venda com base no cruzamento, mas desta vez será o cruzamento do preço com o indicador DEMA.

Sinal de compra:

O preço de fechamento é maior que o valor da Média Móvel Exponencial Dupla (DEMA).

E também: o preço de fechamento anterior é menor que o valor anterior da DEMA.

Sinal de venda:

O preço de fechamento é menor que o valor da DEMA.

E também: o preço de fechamento anterior é maior que o valor anterior da DEMA.

A seguir está o código completo do sistema de trading com uma pequena diferença no uso da função iDEMA para retornar o handle do indicador da Média Móvel Exponencial Dupla. Seus parâmetros:

  • symbol - nome do símbolo; para o símbolo atual é (_Symbol)
  • period - timeframe utilizado. Por padrão é 1 hora
  • ma_period - período de média da média móvel. Com um valor padrão de 50
  • ma_shift - indicamos 0 para deslocamento horizontal, pois não é necessário
  • applied_price - tipo de preço; para o cálculo da média móvel, usamos o preço de fechamento

O código é apresentado abaixo:

//+------------------------------------------------------------------+
//|                                                 iDEMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
int DEMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   DEMA = iDEMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double myDEMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(myDEMAArray,true);
   int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray);
   CopyBuffer(DEMA,0,0,3,myDEMAArray);
   double lastClose=(priceArray[1].close);
   double DEMAVal = NormalizeDouble(myDEMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevDEMAVal = NormalizeDouble(myDEMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(lastClose>DEMAVal && prevClose<prevDEMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(lastClose<DEMAVal && prevClose>prevDEMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

Após a compilação, testaremos o código no mesmo período que os anteriores. As configurações do indicador serão as seguintes:

  • Tamanho do lote = 1
  • Timeframe = 1 hora
  • Período MA = 50

Após executar o teste, obtemos os seguintes resultados:

Resultados da DEMA

Estamos especialmente interessados nos seguintes indicadores:

  • Lucro líquido: -961.60 (-9.62%)
  • Rebaixamento relativo do saldo: 39.62%
  • Rebaixamento relativo dos fundos: 41.15%
  • Fator de lucro: 0.97
  • Expectativa de ganho: -3.12
  • Fator de recuperação: -0.18
  • Índice de Sharpe: -0.21

Média Móvel Exponencial Tripla (iTEMA)

Este tipo de média móvel foi desenvolvido por Patrick Mulloy para tornar o indicador mais sensível e adequado para trading de curto prazo. O indicador utiliza médias móveis exponenciais com suavização tripla, dupla e simples. Assim, este indicador estará mais próximo do preço, tornando-o mais sensível. Da mesma forma que usamos a Média Móvel Exponencial Dupla, podemos aplicar a TEMA da mesma maneira, adicionando sua reação mais rápida ao preço. Além disso, ela pode ser usada para determinar a tendência e pontos de reversão ou mudanças na tendência.

Abaixo estão as etapas para calcular o indicador TEMA (Média Móvel Exponencial Tripla):

1. Cálculo da primeira média móvel exponencial (EMA)

EMA one = EMA do n-ésimo período de preço.

2. Cálculo da EMA da EMA one

EMA two = EMA da EMA one

3. Cálculo da EMA a partir da EMA two

EMA three = EMA da EMA two

4. Cálculo da TEMA

TEMA = (3 * EMA one) - (3 * EMA two) + EMA three

Podemos inserir esse indicador a partir dos indicadores técnicos prontos disponíveis no MetaTrader 5 sem a necessidade de cálculo manual. Após isso, precisamos criar nosso sistema de trading usando o indicador TEMA para testá-lo e comparar seus resultados com outros tipos. Segue o código completo para a criação desse sistema de trading. Ele é semelhante aos anteriores, com a diferença de usar a função iTEMA para retornar o handle do indicador Triple Exponential Moving Average, e seus parâmetros são os mesmos mencionados para DEMA e SMA.

//+------------------------------------------------------------------+
//|                                                 iTEMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
int TEMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   TEMA = iTEMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double myTEMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(myTEMAArray,true);
   int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray);
   CopyBuffer(TEMA,0,0,3,myTEMAArray);
   double lastClose=(priceArray[1].close);
   double TEMAVal = NormalizeDouble(myTEMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevTEMAVal = NormalizeDouble(myTEMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(lastClose>TEMAVal && prevClose<prevTEMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(lastClose<TEMAVal && prevClose>prevTEMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

Após a compilação e execução deste software, podemos testar o mesmo período para comparar seus resultados com outros tipos de médias móveis. Abaixo estão as configurações ou entradas que serão usadas para tentar padronizar todos os parâmetros neste processo de teste:

  • Tamanho do lote = 1
  • Timeframe = 1 hora
  • Período MA = 50

Após executar e concluir este teste, podemos obter os seguintes resultados:

Resultados da TEMA

Estamos especialmente interessados nos seguintes indicadores:

  • Lucro líquido: -3973.10 (-39.74%)
  • Rebaixamento relativo do saldo: 63.98%
  • Rebaixamento relativo dos fundos: 66.06%
  • Fator de lucro: 0.90
  • Expectativa de ganho: -10.59
  • Fator de recuperação: -0.52
  • Índice de Sharpe: -0.83

Média Móvel Adaptativa Fractal (iFrAMA)

Este tipo de média móvel foi desenvolvido por John Ehlers. Este indicador de tendência se baseia na ideia de que os preços de mercado são fractais. Ele também pode ser usado para identificar tendências e pontos de reversão. A seguir, são apresentadas as etapas de seu cálculo:

FrAMA

Podemos usar o indicador técnico pronto disponível no conjunto de ferramentas do MetaTrader 5. Vamos criar uma estratégia de trading já familiar. A estratégia consiste no cruzamento do preço e do indicador FrAMA. Quando o preço cruza acima do nível do FrAMA, isso será um sinal de compra, e quando o preço cruza abaixo do FrAMA, será um sinal de venda.

Sinal de compra:

O preço de fechamento está acima do valor da Média Móvel Adaptativa Fractal (FrAMA).

E também: o preço de fechamento anterior é menor que o valor anterior do FrAMA

Sinal de venda:

O preço de fechamento está abaixo do valor do FrAMA.

E também: o preço de fechamento anterior é maior que o valor anterior do FrAMA

Segue o código completo do sistema de trading com uma pequena diferença no uso da função (iFrAMA) para retornar o handle da Média Móvel Adaptativa Fractal. Seus parâmetros:

  • symbol - nome do símbolo; para o símbolo atual é _Symbol
  • period - timeframe utilizado. Por padrão é 1 hora
  • ma_period - período de média da média móvel. Com um valor padrão de 50
  • ma_shift - para deslocamento horizontal usamos 0 
  • applied_price - tipo de preço usado para cálculo; usamos o preço de fechamento
//+------------------------------------------------------------------+
//|                                                iFrAMA_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input double lotSize = 1;
input ENUM_TIMEFRAMES timeFrame = PERIOD_H1;
input int MAPeriod= 50;
int FrAMA;
int barsTotal;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   FrAMA = iFrAMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,timeFrame);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates priceArray[];
   double myFrAMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(myFrAMAArray,true);
   int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray);
   CopyBuffer(FrAMA,0,0,3,myFrAMAArray);
   double lastClose=(priceArray[1].close);
   double FrAMAVal = NormalizeDouble(myFrAMAArray[1],_Digits);
   double prevClose=(priceArray[2].close);
   double prevFrAMAVal = NormalizeDouble(myFrAMAArray[2],_Digits);
   int bars=iBars(_Symbol,timeFrame);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(lastClose>FrAMAVal && prevClose<prevFrAMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Buy(lotSize,_Symbol,Ask,0,0,NULL);
        }
      if(lastClose<FrAMAVal && prevClose>prevFrAMAVal)
        {
         trade.PositionClose(_Symbol);
         trade.Sell(lotSize,_Symbol,Bid,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+

Após a compilação do código e a execução do EA, testaremos a estratégia usando o indicador FrAMA com as seguintes configurações:

  • Tamanho do lote: 1
  • Timeframe: 1 hora
  • Período MA: 50

Testaremos este EA no mesmo período que os outros tipos de médias móveis mencionados e obteremos os seguintes resultados:

Resultados do FrAMA

Estamos especialmente interessados nos seguintes indicadores:

  • Lucro líquido: -2993.70 (-29.94%)
  • Rebaixamento relativo do saldo: 73.28%
  • Rebaixamento relativo dos fundos: 74.81%
  • Fator de lucro: 0.93
  • Expectativa de ganho: -6.45
  • Fator de recuperação: -0.33
  • Índice de Sharpe: -0.46

Comparação dos resultados com os resultados da SMA

Vamos comparar os resultados de cada tipo de média móvel mencionado. No entanto, cada média móvel pode apresentar resultados diferentes se a otimizarmos e mudarmos os períodos. Também a média móvel pode fornecer resultados diferentes dependendo das configurações e das condições de mercado.

O objetivo principal aqui é garantir o máximo de condições uniformes possível, para avaliar objetivamente as variações da média móvel com base nas melhores configurações, na nossa opinião. Vamos considerar os indicadores mais importantes:

  • Lucro líquido: quanto maior, melhor
  • Rebaixamento (DD): quanto menor, melhor
  • Fator de lucro: quanto maior, melhor
  • Expectativa de ganho: quanto maior, melhor
  • Fator de recuperação: quanto maior, melhor
  • Índice de Sharpe: quanto maior, melhor

Comparemos os resultados da média móvel simples com outros tipos de médias móveis com base nesses parâmetros usando a seguinte tabela:

Parâmetro SMA AMA DEMA TEMA FrAMA
Lucro líquido 2700.30 (27%) 3638.20 (36.39%) - 961.60 (- 9.62%) - 3973.10 (- 39.74%) - 2993.70 (- 29.94%)
Rebaixamento relativo do saldo: 37.07% 22.48% 39.62% 63.98% 73.28%
Rebaixamento relativo dos fundos:  41.76% 35.53% 41.15% 66.06% 74.81%
Fator de lucro 1.10 1.31 0.97 0.90 0.93
Expectativa de ganho 12.68 35.67 - 3.12 - 10.59 - 6.45
Fator de recuperação 0.45 0.65 - 0.18 - 0.52 - 0.33
Índice de Sharpe 0.57 0.86 - 0.21 - 0.83 - 0.46

De acordo com os resultados de todos os nossos testes, temos dois tipos com o melhor desempenho dependendo das configurações e do período de teste. Estes são as médias móveis simples e adaptativas. A melhor delas é a média móvel adaptativa. Ela mostra:

  • O mais alto lucro líquido
  • O menor rebaixamento relativo do saldo
  • O menor rebaixamento relativo dos fundos
  • O melhor fator de lucro
  • A mais alta expectativa matemática de ganho
  • Alto fator de recuperação
  • Alto índice de Sharpe

Como eu já disse, podemos obter melhores resultados com uma maior otimização das configurações e estratégias, mas o objetivo aqui era entender e aplicar o processo de teste em um exemplo real, para então usar o mesmo processo para quaisquer outros objetivos de teste.

Considerações finais

Neste artigo, examinamos os resultados do trabalho com os seguintes tipos de médias móveis:

  • Média Móvel Adaptativa (AMA)
  • Média Móvel Exponencial Dupla (DEMA)
  • Média Móvel Exponencial Tripla (TEMA)
  • Média Móvel Adaptativa Fractal (FrAMA)

Criamos sistemas de trading para cada tipo e comparamos seus resultados com os da média móvel simples. Conforme os resultados dos testes, as melhores performances foram observadas com a média móvel simples e a adaptativa, sendo a Média Móvel Adaptativa (AMA) a que apresentou os melhores resultados. Para determinar o vencedor, analisamos e comparamos os seguintes indicadores:

  • Lucro líquido
  • Rebaixamento (DD)
  • Fator de lucro
  • Expectativa de ganho
  • Fator de recuperação
  • Índice de Sharpe

Testes são um aspecto crucial no trading. Por isso, encorajo você a realizar mais testes com uma variedade maior de estratégias. Além de avaliar a própria estratégia, os testes podem levar a ideias inesperadas, já que cada teste aprofunda nosso entendimento.

Muito obrigado pela atenção! Espero que este artigo tenha sido útil e expandido seu conhecimento. Na seção "Publicações", você pode explorar outros artigos meus, incluindo aqueles dedicados à criação de sistemas de trading baseados em indicadores técnicos populares como RSI, MACD, Estocástico e Bandas de Bollinger. Espero que eles também sejam úteis para você.

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

Arquivos anexados |
SMA_System.mq5 (2.07 KB)
iAMA_System.mq5 (2.15 KB)
iDEMA_System.mq5 (2.06 KB)
iTEMA_System.mq5 (2.06 KB)
iFrAMA_System.mq5 (2.08 KB)
Redes neurais de maneira fácil (Parte 54): usando o codificador aleatório para exploração eficiente (RE3) Redes neurais de maneira fácil (Parte 54): usando o codificador aleatório para exploração eficiente (RE3)
A cada vez que consideramos métodos de aprendizado por reforço, nos deparamos com a questão da exploração eficiente do ambiente. A solução deste problema frequentemente leva à complexificação do algoritmo e ao treinamento de modelos adicionais. Neste artigo, vamos considerar uma abordagem alternativa para resolver esse problema.
Biblioteca de análise numérica ALGLIB em MQL5 Biblioteca de análise numérica ALGLIB em MQL5
Neste artigo, vamos brevemente revisar a biblioteca de análise numérica ALGLIB 3.19, suas aplicações e novos algoritmos que aumentam a eficácia da análise de dados financeiros.
Teoria das Categorias em MQL5 (Parte 17): funtores e monoides Teoria das Categorias em MQL5 (Parte 17): funtores e monoides
Este é o último artigo da série dedicada a funtores. Nele, reconsideramos monoides como uma categoria. Os monoides, que já apresentamos nesta série, são usados aqui para ajudar na definição do tamanho da posição juntamente com perceptrons multicamadas.
Teoria das Categorias em MQL5 (Parte 16): funtores com perceptrons multicamadas Teoria das Categorias em MQL5 (Parte 16): funtores com perceptrons multicamadas
Continuamos a examinar funtores e como eles podem ser implementados usando redes neurais artificiais. Vamos temporariamente deixar de lado a abordagem que incluía a previsão de volatilidade, e tentar implementar nossa própria classe de sinais para estabelecer sinais para entrar e sair de uma posição.