English Русский 中文 Español Deutsch 日本語
preview
Construindo Expert Advisors Auto-Otimizáveis em MQL5 (Parte 5): Regras de Negociação Auto Adaptativas

Construindo Expert Advisors Auto-Otimizáveis em MQL5 (Parte 5): Regras de Negociação Auto Adaptativas

MetaTrader 5Exemplos |
30 0
Gamuchirai Zororo Ndawana
Gamuchirai Zororo Ndawana

Os indicadores técnicos tornaram-se uma ferramenta indispensável na maioria das aplicações de negociação algorítmica devido aos sinais de negociação bem definidos que oferecem, permitindo o rápido desenvolvimento de aplicações. Infelizmente, é comum que os traders se encontrem diante de condições adversas de mercado que se desviam das regras padronizadas sobre como usar qualquer indicador técnico. 

Por exemplo, o Indicador de Força Relativa é usado para medir a força das variações nos níveis de preço em um determinado mercado. É amplamente reconhecido como melhor prática que os traders definam suas entradas de compra quando o RSI fornece leituras abaixo de 30, e entradas de venda quando são observadas leituras do RSI acima de 70. 

Na Fig. 1, abaixo, aplicamos um RSI de período 20 ao preço Diário do Ouro em Dólares Americanos. O leitor pode observar que nenhuma das leituras esperadas foi observada por um período prolongado de 3 meses. Podemos perceber, ao observar a linha de tendência desenhada no gráfico, que de setembro de 2019 até dezembro de 2019, o preço do Ouro esteve em uma forte tendência de baixa.

No entanto, se o leitor prestar mais atenção, perceberá que durante esse período de tendência de baixa, nosso Indicador RSI não produziu os sinais esperados para entrar em uma posição vendida..

Captura de tela 1

Fig 1: É possível que as condições de mercado não consigam produzir a leitura esperada de um indicador técnico, levando a um comportamento não intencional.

Alguns leitores podem racionalizar que “Você pode tentar ajustar seu período de acordo, e obterá o resultado padronizado”. No entanto, ajustar o período nem sempre é uma solução válida. Por exemplo, membros da nossa comunidade interessados em análise de múltiplos símbolos podem ter períodos específicos que melhor expõem o padrão intermercado que estão procurando e, portanto, a necessidade de manter seus períodos fixos.

Além disso, leitores que negociam apenas um único mercado por vez devem ter em mente que aumentar o Período do RSI tornará o problema pior. Da mesma forma, diminuir o período do RSI capta mais ruído do mercado e reduz a qualidade geral dos sinais de negociação.

Em resumo, abordar esse problema de forma casual pode resultar em comportamento não intencional das aplicações de negociação, resultando em lucros perdidos por oportunidades não aproveitadas ou em uma exposição ao mercado maior do que o esperado, devido a condições de saída que não são totalmente satisfeitas.


Visão Geral da Metodologia

Está claro que precisamos projetar aplicações de uma forma que lhes permita adaptar suas regras de negociação aos dados históricos disponíveis. Discutiremos nossa solução proposta em detalhes nas seções subsequentes deste artigo. Por enquanto, nossa solução proposta pode ser melhor resumida pelo raciocínio de que, para saber o que é um movimento forte, você primeiro precisa saber como é um movimento médio naquele mercado específico. Dessa forma, o leitor pode configurar suas aplicações para aceitar apenas sinais de entrada que estejam acima da média, ou melhor ainda, ser mais específico e selecionar movimentos que estejam 2 ou 3 vezes acima da média. 

Ao definir que nossos sinais de negociação sejam decididos em relação ao tamanho de um movimento médio, eliminaremos efetivamente a possibilidade de passar por longos períodos de tempo sem receber um sinal de negociação e, com sorte, colocaremos fim à necessidade de otimizar incessantemente o período do cálculo do RSI. 


Primeiros Passos em MQL5

Nossa exploração começa estabelecendo um nível de desempenho base usando o Testador de Estratégias do MetaTrader 5. Nossa estratégia será usada como andaime que o leitor deverá substituir por suas estratégias de negociação privadas. Construiremos uma estratégia em MQL5 que negocia rompimentos de níveis-chave de suporte ou resistência. Nosso RSI nos dará a confirmação de que o nível foi rompido com sucesso. Fixaremos o tamanho do Stop Loss e do Take Profit em todas as versões da aplicação para garantir que as mudanças na lucratividade estejam vindo diretamente de decisões melhores da nossa parte. 

Existem várias definições do que define um nível válido de suporte ou resistência. Mas, para nossas discussões, será suficiente sabermos que um nível de suporte é um nível de preço baixo que gerou um rali na ação do preço. E, de forma inversa, níveis de resistência são níveis de preço de interesse que produziram uma forte tendência de baixa em nossos gráficos. A duração exata em que esses níveis permanecerão válidos não é conhecida no início de nenhuma sessão de negociação. 

Quando qualquer um desses níveis é rompido com sucesso, eles normalmente são seguidos por uma ação de preço volátil. Nosso RSI será o nosso guia para decidir se devemos colocar uma operação quando o rompimento observado estiver em andamento. Estamos procurando oportunidades para entrar em posições compradas quando os níveis de preço tiverem rompido abaixo de níveis-chave de suporte, e apenas assumir posições vendidas se o oposto for verdadeiro no nível de resistência.

Nossos níveis de suporte e resistência serão encontrados comparando os níveis de preço atuais com seus respectivos níveis de 5 dias atrás. 

Captura de tela 2

Fig 2: Visualizando níveis de suporte e resistência no XAGUSD

Alguns parâmetros da nossa discussão permanecerão fixos. Portanto, para evitar duplicação desnecessária das mesmas informações, discutiremos esses parâmetros fixos aqui. Nossa discussão terá como objetivo negociar rompimentos em níveis de suporte e resistência no preço Diário da Prata em Dólares Americanos (XAGUSD). Testaremos nossa estratégia em dados históricos M15 de 1º de janeiro de 2017 até 28 de janeiro de 2025.

Captura de tela 3

Fig 3: O período de tempo que usaremos para nossos backtests

Além disso, utilizaremos configurações de “Atraso aleatório” durante nosso backtest, pois isso é semelhante à experiência da negociação real. E selecionamos “Cada tick baseado em ticks reais” para realizar nossos testes com dados reais de mercado, obtidos do nosso corretor.

Captura de tela 4

Fig 4: O segundo conjunto de configurações fixas em nosso backtest de hoje

Com isso resolvido, agora podemos focar nossa atenção na construção da nossa aplicação base usando MQL5. Começaremos definindo primeiro constantes críticas do sistema que não serão alteradas durante nossa conversa. Essas constantes do sistema definem parâmetros que controlam o comportamento da nossa aplicação de negociação, como a largura do stop loss e do take profit, quais períodos de tempo usar e o tamanho de cada posição que assumimos, apenas para citar algumas funções.

//+------------------------------------------------------------------+
//|                                  Self Adapting Trading Rules.mq5 |
//|                                               Gamuchirai Ndawana |
//|                    https://www.mql5.com/en/users/gamuchiraindawa |
//+------------------------------------------------------------------+
#property copyright "Gamuchirai Ndawana"
#property link      "https://www.mql5.com/en/users/gamuchiraindawa"
#property version   "1.00"

//+------------------------------------------------------------------+
//| System constants                                                 |
//+------------------------------------------------------------------+
#define RSI_PERIOD 10              //The period for our RSI indicator
#define RSI_PRICE  PRICE_CLOSE     //The price level our RSI should be applied to
#define ATR_SIZE   1.5             //How wide should our Stop loss be?
#define ATR_PERIOD 14              //The period of calculation for our ATR indicator
#define TF_1       PERIOD_D1       //The primary time frame for our trading application
#define TF_2       PERIOD_M15      //The secondary time frame for our trading application
#define VOL        0.1             //Our trading volume   

Agora iremos importar a biblioteca de negociação para nos ajudar a gerenciar nossas posições.

//+------------------------------------------------------------------+
//| Libraries we need                                                |
//+------------------------------------------------------------------+
#include <Trade/Trade.mqh>
CTrade Trade;

Em seguida, precisamos definir algumas variáveis globais importantes.

//+------------------------------------------------------------------+
//| Global variables                                                 |
//+------------------------------------------------------------------+
int rsi_handler,atr_handler;
double rsi[],atr[];
double support,resistance;

Nossas aplicações MetaTrader 5 são conduzidas principalmente por eventos que acontecem em nosso Terminal. Construímos métodos personalizados que serão chamados, por sua vez, quando cada evento do Terminal for acionado.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   setup();
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   release();
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   update();
  }
//+------------------------------------------------------------------+

Quando nosso indicador for carregado pela primeira vez, configuraremos nossos indicadores técnicos e, em seguida, definiremos nossos níveis de suporte e resistência para os níveis de preço mais altos e mais baixos observados na semana anterior.

//+------------------------------------------------------------------+
//| User defined methods                                             |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Initialize our system variables                                  |
//+------------------------------------------------------------------+
void setup(void)
  {
//Load our technical indicators
   atr_handler = iATR(Symbol(),TF_1,ATR_PERIOD);
   rsi_handler = iRSI(Symbol(),TF_2,RSI_PERIOD,RSI_PRICE);
   resistance  = iHigh(Symbol(),TF_1,5);
   support     = iLow(Symbol(),TF_1,5);
  }

Se nossa aplicação de negociação não estiver mais em uso, precisamos liberar os indicadores técnicos que não estamos mais utilizando.

//+------------------------------------------------------------------+
//| Let go of resources we are no longer consuming                   |
//+------------------------------------------------------------------+
void release(void)
  {
//Free up resources we are not using
   IndicatorRelease(atr_handler);
   IndicatorRelease(rsi_handler);
  }

Nossa função de atualização é dividida em 2 partes. A primeira metade lida com tarefas rotineiras que precisam ser executadas uma vez por dia, enquanto a segunda metade lida com tarefas que precisam ser executadas com frequência em um período de tempo menor. Isso nos garante que não seremos pegos de surpresa por comportamentos abruptos ou anormais do mercado. 

//+------------------------------------------------------------------+
//| Update our system variables and look for trading setups          |
//+------------------------------------------------------------------+
void update(void)
  {
//Update our system variables
//Some duties must be performed periodically on the higher time frame
     {
      static datetime time_stamp;
      datetime current_time = iTime(Symbol(),TF_1,0);

      //Update the time
      if(time_stamp != current_time)
        {
         time_stamp = current_time;

         //Update indicator readings
         CopyBuffer(rsi_handler,0,0,1,rsi);
         CopyBuffer(atr_handler,0,0,1,atr);

         //Update our support and resistance levels
         support    = iLow(Symbol(),TF_1,5);
         resistance = iHigh(Symbol(),TF_1,5);
         ObjectDelete(0,"Support");
         ObjectDelete(0,"Resistance");
         ObjectCreate(0,"Suppoprt",OBJ_HLINE,0,0,support);
         ObjectCreate(0,"Resistance",OBJ_HLINE,0,0,resistance);
        }
     }

//While other duties need more attention, and must be handled on lower time frames.
     {
      static datetime time_stamp;
      datetime current_time = iTime(Symbol(),TF_2,0);
      double bid,ask;   
                  
      //Update the time
      if(time_stamp != current_time)
        {
         time_stamp = current_time;
         bid=SymbolInfoDouble(Symbol(),SYMBOL_BID);
         ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
         
         //Check if we have broken either extreme
         if(PositionsTotal() == 0)
            {
               //We are looking for opportunities to sell
               if(iLow(Symbol(),TF_2,0) > resistance)
                  {
                     if(rsi[0] > 70) Trade.Sell(VOL,Symbol(),bid,(ask + (ATR_SIZE * atr[0])),(ask - (ATR_SIZE * atr[0])));
                  }
              
              //We are looking for opportunities to buy
              if(iHigh(Symbol(),TF_2,0) < support)
                  {
                     if(rsi[0] < 30) Trade.Buy(VOL,Symbol(),ask,(bid - (ATR_SIZE * atr[0])),(bid + (ATR_SIZE * atr[0])));
                  }
            }
         }      
        }
     }

Por fim, devemos remover a definição das constantes do sistema que definimos no início da aplicação.

//+------------------------------------------------------------------+
//| Undefine the system constants                                    |
//+------------------------------------------------------------------+
#undef RSI_PERIOD
#undef RSI_PRICE
#undef ATR_PERIOD
#undef ATR_SIZE
#undef TF_1
#undef TF_2
#undef VOL
//+------------------------------------------------------------------+

Em conjunto, este é o aspecto atual da nossa base de código.

//+------------------------------------------------------------------+
//|                                  Self Adapting Trading Rules.mq5 |
//|                                               Gamuchirai Ndawana |
//|                    https://www.mql5.com/en/users/gamuchiraindawa |
//+------------------------------------------------------------------+
#property copyright "Gamuchirai Ndawana"
#property link      "https://www.mql5.com/en/users/gamuchiraindawa"
#property version   "1.00"

//+------------------------------------------------------------------+
//| System constants                                                 |
//+------------------------------------------------------------------+
#define RSI_PERIOD 10            //The period for our RSI indicator
#define RSI_PRICE  PRICE_CLOSE   //The price level our RSI should be applied to
#define ATR_SIZE   1.5             //How wide should our Stop loss be?
#define ATR_PERIOD 14            //The period of calculation for our ATR indicator
#define TF_1       PERIOD_D1     //The primary time frame for our trading application
#define TF_2       PERIOD_M15    //The secondary time frame for our trading application
#define VOL        0.1           //Our trading volume   

//+------------------------------------------------------------------+
//| Libraries we need                                                |
//+------------------------------------------------------------------+
#include <Trade/Trade.mqh>
CTrade Trade;

//+------------------------------------------------------------------+
//| Global variables                                                 |
//+------------------------------------------------------------------+
int rsi_handler,atr_handler;
double rsi[],atr[];
double support,resistance;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   setup();
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   release();
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   update();
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| User defined methods                                             |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Initialize our system variables                                  |
//+------------------------------------------------------------------+
void setup(void)
  {
//Load our technical indicators
   atr_handler = iATR(Symbol(),TF_1,ATR_PERIOD);
   rsi_handler = iRSI(Symbol(),TF_2,RSI_PERIOD,RSI_PRICE);
   resistance  = iHigh(Symbol(),TF_1,5);
   support     = iLow(Symbol(),TF_1,5);
  }

//+------------------------------------------------------------------+
//| Let go of resources we are no longer consuming                   |
//+------------------------------------------------------------------+
void release(void)
  {
//Free up resources we are not using
   IndicatorRelease(atr_handler);
   IndicatorRelease(rsi_handler);
  }

//+------------------------------------------------------------------+
//| Update our system variables and look for trading setups          |
//+------------------------------------------------------------------+
void update(void)
  {
//Update our system variables
//Some duties must be performed periodically on the higher time frame
     {
      static datetime time_stamp;
      datetime current_time = iTime(Symbol(),TF_1,0);

      //Update the time
      if(time_stamp != current_time)
        {
         time_stamp = current_time;

         //Update indicator readings
         CopyBuffer(rsi_handler,0,0,1,rsi);
         CopyBuffer(atr_handler,0,0,1,atr);

         //Update our support and resistance levels
         support    = iLow(Symbol(),TF_1,5);
         resistance = iHigh(Symbol(),TF_1,5);
         ObjectDelete(0,"Support");
         ObjectDelete(0,"Resistance");
         ObjectCreate(0,"Suppoprt",OBJ_HLINE,0,0,support);
         ObjectCreate(0,"Resistance",OBJ_HLINE,0,0,resistance);
        }
     }

//While other duties need more attention, and must be handled on lower time frames.
     {
      static datetime time_stamp;
      datetime current_time = iTime(Symbol(),TF_2,0);
      double bid,ask;

      //Update the time
      if(time_stamp != current_time)
        {
         time_stamp = current_time;
         bid=SymbolInfoDouble(Symbol(),SYMBOL_BID);
         ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK);

         //Check if we have broken either extreme
         if(PositionsTotal() == 0)
           {
            //We are looking for opportunities to sell
            if(iLow(Symbol(),TF_2,0) > resistance)
              {
               if(rsi[0] > 70)
                  Trade.Sell(VOL,Symbol(),bid,(ask + (ATR_SIZE * atr[0])),(ask - (ATR_SIZE * atr[0])));
              }

            //We are looking for opportunities to buy
            if(iHigh(Symbol(),TF_2,0) < support)
              {
               if(rsi[0] < 30)
                  Trade.Buy(VOL,Symbol(),ask,(bid - (ATR_SIZE * atr[0])),(bid + (ATR_SIZE * atr[0])));
              }
           }
        }
     }
  }

//+------------------------------------------------------------------+
//| Undefine the system constants                                    |
//+------------------------------------------------------------------+
#undef RSI_PERIOD
#undef RSI_PRICE
#undef ATR_PERIOD
#undef ATR_SIZE
#undef TF_1
#undef TF_2
#undef VOL
//+------------------------------------------------------------------+

Vamos agora avaliar o quão bem este algoritmo se comporta em dados históricos de mercado. Inicie seu terminal MetaTrader 5 e selecione a aplicação que acabamos de desenvolver juntos. Lembre-se de que as datas e configurações de teste são fornecidas para você no início desta seção do artigo.

Captura de tela 5

Fig 5: Iniciando nosso backtest no MetaTrader 5

Nosso expert advisor não possui parâmetros de entrada; depois que você carregar a aplicação e definir as datas de teste de acordo, inicie o Testador de Estratégias do MetaTrader 5. A Fig. 6, abaixo, é a curva de capital produzida ao seguir as regras clássicas de negociação construídas para o RSI. 

Captura de tela 6

Fig 6: A curva de capital produzida ao seguir a estratégia clássica de negociação com RSI

A Fig. 7 nos fornece um resumo detalhado de como nossa aplicação de negociação baseada em RSI se comportou no primeiro teste. Nosso lucro líquido total foi de US$ 588,60, com um índice de Sharpe de 0,85. Esses resultados são encorajadores até o momento e servirão como nossa meta a ser superada na próxima iteração da nossa aplicação de negociação.

Captura de tela 7

Fig 7: Um resumo detalhado dos resultados que obtivemos em nosso backtest



Aprimorando Nossos Resultados Iniciais

Agora chegamos à solução proposta que aborda os problemas potenciais causados por saídas não padronizadas do indicador. Para substituir os níveis clássicos 70 e 30 por níveis ótimos selecionados diretamente a partir do desempenho histórico do mercado, devemos primeiro observar o intervalo de saídas que o indicador gera no mercado em questão. Em seguida, iremos bisseccionar as 2 linhas paralelas que marcam a saída máxima e mínima gerada pelo indicador. Essa linha de bissecção se torna nosso novo ponto médio. Observe que, originalmente, o ponto médio do indicador RSI é o nível 50.

Depois de calcularmos nosso novo ponto médio, registraremos a diferença absoluta de cada leitura do RSI em relação ao ponto médio do indicador e faremos a média desses valores para obter nossa estimativa de um movimento médio naquele mercado específico. Posteriormente, instruiremos nossa aplicação de negociação a somente entrar em posições se observar uma variação no valor do RSI 2 vezes maior do que um movimento médio nesse mercado. Esse novo parâmetro nos permite controlar o quão sensível nossa aplicação de negociação é, mas se selecionarmos valores muito grandes, como 100, nossa aplicação não realizará nenhuma operação, nunca.

Para implementar essas mudanças em nossa aplicação, precisamos fazer as seguintes alterações:

Proposta de Alteração Finalidade Pretendida
Criação de novas constantes do sistema Essas novas constantes do sistema irão fixar a maioria dos parâmetros da versão inicial da aplicação, ao mesmo tempo em que introduzem alguns novos que precisamos.
Modificação dos nossos métodos definidos pelo usuário As funções personalizadas que escrevemos anteriormente precisam ser estendidas para fornecer a nova funcionalidade que desejamos.

Para começar, vamos primeiro criar as novas constantes do sistema de que precisamos. Precisamos decidir dinamicamente quantas barras devem ser usadas nos cálculos que queremos realizar. Essa será a responsabilidade da nova constante do sistema intitulada "BARS". Ela retornará um inteiro próximo à metade do número total de barras disponíveis. Além disso, também decidimos que estamos interessados apenas em variações no RSI que sejam 2 vezes maiores do que a média. Portanto, criamos uma nova constante chamada "BIG SIZE" que registra a força pretendida que queremos observar por trás dos movimentos.

Por fim, nossos níveis de suporte e resistência serão encontrados comparando o preço atual com seu valor de uma semana atrás, ou seja, 5 dias atrás.

//+---------------------------------------------------------------+
//| System constants                                              |
//+---------------------------------------------------------------+
#define RSI_PERIOD     10                                          //The period for our RSI indicator
#define RSI_PRICE      PRICE_CLOSE                                 //The price level our RSI should be applied to
#define ATR_SIZE       1.5                                         //How wide should our Stop loss be?
#define ATR_PERIOD     14                                          //The period of calculation for our ATR indicator
#define TF_1           PERIOD_D1                                   //The primary time frame for our trading application
#define TF_2           PERIOD_M15                                  //The secondary time frame for our trading application
#define VOL            0.1                                         //Our trading volume   
#define BARS           (int) MathFloor((iBars(Symbol(),TF_2) / 2)) //How many bars should we use for our calculation?
#define BIG_SIZE       2                                           //How many times bigger than the average move should the observed change be?
#define SUPPORT_PERIOD 5                                           //How far back into the past should we look to find our support and resistance levels?

Agora, iremos modificar as condições que definem se abriremos ou não nossas posições. Observe que não colocamos mais nossas entradas em níveis fixos do indicador, mas sim em níveis calculados, que são derivados do buffer de memória do indicador.

//While other duties need more attention, and must be handled on lower time frames.
     {
      static datetime time_stamp;
      datetime current_time = iTime(Symbol(),TF_2,0);
      double bid,ask;

      //Update the time
      if(time_stamp != current_time)
        {
         time_stamp = current_time;
         bid=SymbolInfoDouble(Symbol(),SYMBOL_BID);
         ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK);

         //Copy the rsi readings into a vector
         vector rsi_vector   = vector::Zeros(BARS);
         rsi_vector.CopyIndicatorBuffer(rsi_handler,0,1,BARS);

         //Let's see how far the RSI tends to deviate from its centre
         double rsi_midpoint = ((rsi_vector.Max() + rsi_vector.Min()) / 2);
         vector rsi_growth   = MathAbs(rsi_vector - rsi_midpoint);

         //Check if we have broken either extreme
         if(PositionsTotal() == 0)
           {
            //We are looking for opportunities to sell
            if(iLow(Symbol(),TF_2,0) > resistance)
              {
               if((rsi[0] - rsi_midpoint) > (rsi_growth.Mean() * BIG_SIZE))
                  Trade.Sell(VOL,Symbol(),bid,(ask + (ATR_SIZE * atr[0])),(ask - (ATR_SIZE * atr[0])));
              }

            //We are looking for opportunities to buy
            if(iHigh(Symbol(),TF_2,0) < support)
              {
               if((rsi[0] - rsi_midpoint) < (-(rsi_growth.Mean() * BIG_SIZE)))
                  Trade.Buy(VOL,Symbol(),ask,(bid - (ATR_SIZE * atr[0])),(bid + (ATR_SIZE * atr[0])));
              }
           }
        }
     }

Por fim, precisamos remover a definição das novas constantes do sistema que criamos.

//+------------------------------------------------------------------+
//| Undefine the system constants                                    |
//+------------------------------------------------------------------+
#undef RSI_PERIOD
#undef RSI_PRICE
#undef ATR_PERIOD
#undef ATR_SIZE
#undef TF_1
#undef TF_2
#undef VOL
#undef BARS
#undef BIG_SIZE
#undef SUPPORT_PERIOD
//+------------------------------------------------------------------+

Agora estamos prontos para testar nossas novas regras dinâmicas de negociação para o RSI. Certifique-se de selecionar a versão apropriada do Expert Advisor no testador de estratégias antes de iniciar o teste. Lembre-se de que as configurações de data serão as mesmas que afirmamos na introdução do artigo.

Captura de tela 8

Fig 8: Selecione a versão correta da aplicação de negociação para nosso teste

A curva de capital produzida por nossa nova versão do algoritmo de negociação com RSI parece semelhante aos resultados iniciais que obtivemos. No entanto, vamos analisar o resumo detalhado dos resultados para obter uma perspectiva clara sobre qual diferença foi gerada.

Captura de tela 9

Fig 9: A curva de capital produzida por nossa versão do algoritmo de negociação com regras dinâmicas

Em nosso teste inicial, nosso lucro líquido total foi de US$ 588,60 obtidos em um total de 136 operações. Nossa nova estratégia produziu um lucro de US$ 703,20 em 121 operações. Portanto, nossa lucratividade aumentou em aproximadamente 19,5% enquanto, por outro lado, o número total de operações realizadas caiu cerca de 11%. É evidente que nosso novo sistema está nos oferecendo uma clara vantagem competitiva sobre as regras clássicas que definem como normalmente devemos usar o indicador. 

Captura de tela 10

Fig 10: Os resultados detalhados que resumem o desempenho da nossa nova estratégia de negociação



Conclusão

A solução que exploramos hoje forneceu a você um padrão de projeto sobre como usar seu terminal MetaTrader 5 para oferecer um nível refinado de controle sobre a sensibilidade das suas aplicações de negociação. Traders que analisam múltiplos símbolos se beneficiarão de uma nova perspectiva sobre como comparar a força das variações nos níveis de preço em diferentes mercados de forma objetiva, bem estruturada e que elimina as chances de bugs não intencionais que podem facilmente comprometer seus esforços.

Além disso, nosso algoritmo proposto para substituir cuidadosamente os níveis clássicos 30 e 70 por níveis ótimos selecionados diretamente a partir do intervalo observado do indicador quando ele é aplicado a qualquer mercado específico pode nos dar uma vantagem material sobre participantes casuais do mercado que aguardam que o resultado padronizado seja observado. 

Arquivo Anexado Descrição
Regras de Negociação Auto Adaptativas Versão de referência da nossa aplicação de negociação com regras estáticas e fixas.
Regras de Negociação Auto Adaptativas V2 Versão refinada da nossa aplicação de negociação que adapta suas regras com base nos dados de mercado disponíveis.

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

Critério de Independência de Hilbert-Schmidt (HSIC) Critério de Independência de Hilbert-Schmidt (HSIC)
O artigo examina o teste estatístico não paramétrico HSIC (Hilbert-Schmidt Independence Criterion) destinado a identificar dependências lineares e não lineares nos dados. São propostas implementações de dois algoritmos para o cálculo do HSIC na linguagem MQL5: o teste exato por permutação e a aproximação gama. A eficácia do método é demonstrada em dados sintéticos que modelam uma relação não linear entre os atributos e a variável-alvo.
Desenvolvimento do Kit de Ferramentas de Análise de Price Action (Parte 10): Fluxo Externo (II) VWAP Desenvolvimento do Kit de Ferramentas de Análise de Price Action (Parte 10): Fluxo Externo (II) VWAP
Domine o poder do VWAP com o nosso guia abrangente! Aprenda como integrar a análise de VWAP à sua estratégia de negociação usando MQL5 e Python. Maximize seus insights de mercado e melhore suas decisões de trading hoje mesmo.
Algoritmo do camelo — Camel Algorithm (CA) Algoritmo do camelo — Camel Algorithm (CA)
O Algoritmo do camelo, desenvolvido em 2016, modela o comportamento dos camelos no deserto para resolver problemas de otimização, levando em conta fatores de temperatura, reservas e resistência. Neste trabalho é apresentada ainda uma versão modificada dele (CAm), com melhorias-chave, como a aplicação da distribuição gaussiana na geração de soluções e a otimização dos parâmetros do efeito de oásis.
Redes Adversariais Generativas (GANs) para Dados Sintéticos em Modelagem Financeira (Parte 2): Criação de Símbolo Sintético para Testes Redes Adversariais Generativas (GANs) para Dados Sintéticos em Modelagem Financeira (Parte 2): Criação de Símbolo Sintético para Testes
Neste artigo, estamos criando um símbolo sintético usando uma Rede Adversarial Generativa (GAN), o que envolve a geração de dados financeiros realistas que imitam o comportamento de instrumentos reais do mercado, como o EURUSD. O modelo GAN aprende padrões e volatilidade a partir de dados históricos do mercado e cria dados de preços sintéticos com características semelhantes.