English Русский 中文 Español Deutsch 日本語
preview
Funcionalidades do assistente MQL5 que você precisa conhecer (Parte 03): Entropia de Shannon

Funcionalidades do assistente MQL5 que você precisa conhecer (Parte 03): Entropia de Shannon

MetaTrader 5Testador | 20 janeiro 2023, 08:54
252 0
Stephen Njuki
Stephen Njuki

1.0 Introdução

Claude Shannon em 1948 apresentou o seu artigo “A mathematical theory of communication” que tinha o novo ideal da entropia de informação. A entropia é um conceito da física. É uma medida da extensão em que as partículas dentro de um objeto estão ativas. Se considerarmos os 3 estados da água, ou seja, gelo, líquido e vapor, por exemplo; podemos ver que a energia cinética da partícula é maior no vapor e menor no gelo. Esse mesmo conceito é aplicado na matemática via probabilidade. Considere os três conjuntos a seguir.

Conjunto 1: 

Conjunto 1


Conjunto 2: 

Conjunto 2


Conjunto 3: 

Conjunto 3


Se você adivinhasse qual desses conjuntos teria a maior entropia?
Se você escolheu o último, acertou, mas como validamos essa resposta? A maneira mais simples de responder a isso pode ser considerando o número de maneiras pelas quais você pode reorganizar cada conjunto como a estimativa de entropia, ignorando os trechos de cores semelhantes. Para o primeiro conjunto, há apenas uma maneira de 'reorganizá-lo', no entanto, quando olhamos para os conjuntos depois, claramente, o número de permutações em relação à cor aumenta significativamente, portanto, você pode argumentar que o último conjunto tem a maior entropia 

Existe uma maneira mais precisa de determinar a entropia baseada em informações. Se você escolhesse arbitrariamente uma bola do primeiro conjunto, antes de pegar essa bola, o que você saberia sobre ela? Bem, como o conjunto contém apenas bolas azuis, você pode ter certeza de que será uma bola azul. Você poderia dizer, portanto, que tenho informações completas sobre o que vou selecionar no conjunto 1. Conforme consideramos os conjuntos 2 e 3, nossas informações tornam-se cada vez menos completas, respectivamente. Em matemática, portanto, a Entropia está inversamente relacionada à informação. Quanto maior a entropia, mais incógnitas.  

Então, como derivamos uma fórmula para calcular a entropia? Se considerarmos os conjuntos mais uma vez, quanto mais variedade houver nos tipos de bola dentro de um conjunto, maior será a entropia. O fator mais sensível para medir a informação que temos sobre uma bola antes de sua seleção pode ser a probabilidade de selecionar cada bola em um conjunto. Portanto, se considerarmos cada conjunto na totalidade e encontrarmos a probabilidade de selecionar 8 bolas com todas as cores selecionadas com a frequência com que aparecem em seu conjunto, dado que a seleção de cada bola é um evento independente; então a probabilidade (e, portanto, 'informação conhecida') para cada conjunto é o produto das probabilidades individuais para cada bola.  

Conjunto 1: 

(1.0 x 1.0 x 1.0 x 1.0 x 1.0 x 1.0 x 1.0 x 1.0) = 1.0 


Conjunto 2: 

(0.625 x 0.625 x 0.625 x 0.625 x 0.625 x 0.375 x 0.375 x 0.375) ~ 0.0050 


Conjunto 3: 

(0.375 x 0.375 x 0.375 x 0.25 x 0.25 x 0.25 x 0.25 x 0.125) ~ 0.000025 


À medida que um conjunto aumenta em tamanho e variedade, os valores de probabilidade tornam-se muito pequenos para trabalhar, e é por isso que os logaritmos, especificamente os logaritmos negativos dessas probabilidades, são considerados na medição da entropia já que ele é inversamente proporcional à informação conhecida como mostrado acima. Esta equação de identidade é a base da normalização: 


equation_1


O logaritmo é multiplicado por menos um, pois o logaritmo de números menores que um é negativo. De fato, a fórmula da entropia como na Wikipédia é: 


equação_2


Que se traduz como uma soma dos produtos de probabilidades e seu logaritmo. Portanto, para calcular as nossas entropias definidas; 


Conjunto 1: 

-(8 x 0.125 x log2(1.0)) = 0.0 


Conjunto 2: 

(-(0.625 x log2(0.625)) - (0.375 x log2(0.375))) ~ 0.9544 


Conjunto 3: 

(- (0.375 x log2(0.375)) - (2 x 0.25 x log2(0.25)) - (0.125 x log2(0.125))) ~ 1.906 


Foi mostrado que o número médio de questões binárias necessárias para determinar a cor de uma bola selecionada aleatoriamente de um conjunto é a entropia do conjunto. Além disso, a entropia máxima para um conjunto de n valores é: \

equação_3

Este valor máximo será útil para a normalização dos valores de entropia ao gerar os sinais que variam de 0.0 a 1.0. Para um trader, a entropia do histórico de preços pode servir como um precursor para saber se um sinal de negociação confiável pode ser processado a partir desse histórico. Mas supondo que nós usamos a própria entropia para gerar os sinais? Supondo que exploramos a ideia de que a entropia das barras em queda é maior do que a das barras em ascensão dentro de um conjunto fixo de barras recentes, implicando um sinal de compra e vice-versa? Vamos ver como isso pode ser desenvolvido como um sinal do expert para o assistente MQL5.


2.0 Criação da classe

Para este artigo, nós usaremos a classe Decision Forest da biblioteca MQL5. Especificamente, nós vamos abstrair a ideia de florestas aleatórias ao explorar a eficácia do nosso sinal de entropia de Shannon. Este artigo não é sobre florestas aleatórias, mas sobre a entropia de Shannon. 

Vamos revisitar a classe da floresta de decisão, pois ela é a base do modelo da floresta aleatória. É uma coisa boa, as florestas de decisão são bastante inatas. Todos nós já usamos uma árvore de decisão, conscientemente ou não, em algum momento e, portanto, o próprio conceito não é estranho.

f_d




Vejamos um exemplo para ilustrar melhor como ele funciona.

Supondo que nosso conjunto de dados consiste nas barras de preço indicadas acima. Temos três velas em queda e cinco velas ascendentes (considere os mercados de baixa e alta como nossas classes) e queremos separar as classes usando seus atributos. Os atributos são a direção do preço e a comparação do comprimento da cabeça à cauda, pois podem ser precursores de mudanças na direção. Então, como nós podemos fazer isso?

A direção do preço parece um atributo direto para separar, já que o branco representa velas de baixa e azul de alta. Então, nós podemos usar a pergunta: “O preço está caindo?” para separar a primeira junção. Uma junção em uma árvore como o ponto onde o ramo se divide em dois — atendendo aos critérios para escolher o ramo Sim e o ramo Não.

Todos os ramos Não (velas ascendentes) têm caudas mais longas do que as cabeças, então terminamos aqui, mas no ramo Sim, esse não é o caso, portanto, há mais trabalho a ser feito. Ao usar o segundo atributo, perguntamos: “As cabeças são mais longas que as caudas?” para fazer uma segunda divisão.

As duas velas em declínio com cabeças mais longas estão sob o sub-ramo Sim e uma vela em declínio com uma cauda mais longa é classificada no sub-ramo direito. Essa árvore de decisão foi capaz de usar os dois atributos para dividir os dados perfeitamente de acordo com os nossos critérios. 

Em sistemas de negociação reais, o volume de ticks, a hora do dia e uma série de outros indicadores de negociação podem ser usados na construção de uma árvore de decisão mais abrangente. No entanto, a premissa central de cada pergunta em um nó é encontrar o único atributo que divide (ou classifica) os dados acima em dois conjuntos diferentes, com os membros criados de cada conjunto sendo semelhantes.

Mudando para a floresta aleatória, como o próprio nome indica, ela consiste em um grande número de árvores de decisão individuais que funcionam como um grupo. Para cada árvore na floresta aleatória, se faz uma predição de classe e a classe com mais votos é selecionada como predição do modelo. O principal conceito por trás da floresta aleatória é fácil de ignorar, mas é muito poderoso — a sabedoria das massas. Ao fazer previsões, as árvores não correlacionadas superam as árvores individuais, independentemente da quantidade de dados em que os indivíduos são treinados. Baixa correlação é o ponto crucial. A razão para isso é que as árvores protegem umas às outras de seus erros individuais de acordo com Ton (desde que não errem todas constantemente na mesma direção). Para que as florestas aleatórias funcionem, o sinal de previsão precisa ser melhor que a média e as perdas/erros de cada árvore precisam ter uma correlação baixa entre si.

Por exemplo, se você tivesse dois sistemas de negociação, onde no primeiro você pode colocar até mil ordens de margem de um dólar em um ano e o outro você só pode colocar uma ordem de margem de 1000 dólares qual você prefere assumindo expectativa semelhante? Para a maioria das pessoas, é o primeiro sistema, pois dá ao trader "mais controle". 

Então, de que maneira os algoritmos de floresta aleatória garantem que a característica de cada árvore individual não esteja muito correlacionada com a característica de qualquer uma das outras árvores em uma floresta? Isso pode se resumir a dois recursos:

2.0.1 Bagging

As árvores de decisão são muito sensíveis aos dados de treinamento com pequenas alterações que podem resultar em florestas significativamente diferentes. As florestas aleatórias usam isso fazendo com que cada árvore faça uma amostra aleatória do conjunto de dados durante a substituição, resultando em árvores diferentes. Esse processo é conhecido como bagging, uma abreviação de bootstrap aggregation.

Observe que com o bagging não estamos substituindo os dados de treinamento em conjuntos menores, mas em vez dos dados de treinamento originais, pegamos uma amostra aleatória de tamanho N com algumas substituições. O tamanho de ajuste inicial N é mantido. Por exemplo, se nossos dados de treinamento forem [U, V, W, X, Y, Z], podemos fornecer a uma de nossas árvores a seguinte lista [U, U, V, X, X, Z]. Em ambas as listas o tamanho N (seis) é mantido e que “U” e “X” são ambos repetidos nos dados selecionados aleatoriamente.


2.0.2 Aleatoriedade de Características

Normalmente, em uma árvore de decisão, dividir o nó envolve considerar todas as características possíveis e selecionar uma que produza a distinção mais ampla entre as observações no eventual nó esquerdo versus aquelas no eventual nó direito. Por outro lado, em uma floresta aleatória, cada árvore pode escolher apenas um subconjunto aleatório de características. Isso tende a forçar mais variação dentro da floresta e, em última análise, leva a uma correlação mais baixa entre as árvores e a uma maior diversificação.

Vejamos um exemplo visual — na figura acima, a árvore de decisão tradicional (em azul) pode selecionar entre todos as quatro características ao decidir como dividir o nó. Ele decide usar a Característica 1 (preto e sublinhado), pois divide os dados em grupos tão separados quanto possível.

Agora vamos dar uma olhada em nossa floresta aleatória. Examinaremos apenas duas das árvores da floresta neste exemplo. Quando verificamos a Árvore 1 da floresta aleatória, descobrimos que ela só pode considerar as características 2 e 3 (selecionados aleatoriamente) para sua decisão de divisão de nós. Sabemos por nossa árvore de decisão tradicional (em azul) que a Característica 1 é o melhor recurso para divisão, mas a Árvore 1 não pode ver a Característica 1, então é forçado a ir com a Característica 2 (preto e sublinhado). A Árvore 2, por outro lado, só pode ver as Característica 1 e 3, portanto, pode escolher a Característica 1.

Portanto, em florestas aleatórias, árvores que não são apenas treinadas em conjuntos de dados (graças ao bagging), mas também usam várias características na tomada de decisões.



s_d



Ao usar florestas aleatórias, nosso expert processa os resultados das negociações anteriores e os sinais de mercado para chegar a uma decisão de compra ou venda. Ao obter um sinal e não apenas um rastreador da entropia, nós consideraremos separadamente a entropia das barras de preços positivas e negativas dentro de um conjunto recente. 

A construção e o treinamento de florestas aleatórias ocorrerão apenas na otimização com uma única thread.

2.1 Classe Signal do Expert 

// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signals of'Shannon Entropy'                                |
//| Type=SignalAdvanced                                              |
//| Name=Shannon Entropy                                             |
//| ShortName=SE                                                     |
//| Class=CSignalSE                                                  |
//| Page=signal_se                                                   |
//| Parameter=Reset,bool,false,Reset Training                        |
//| Parameter=Trees,int,50,Trees number                              |
//| Parameter=Regularization,double,0.15,Regularization Threshold    |
//| Parameter=Trainings,int,21,Trainings number                      |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalSE.                                                 |
//| Purpose: Class of generator of trade signals based on            |
//|          the 'Shannon Entropy' signals.                          |
//| Is derived from the CExpertSignal class.                         |
//+------------------------------------------------------------------+
class CSignalSE : public CExpertSignal
   {
      public:
         
         //Decision Forest objects.
         CDecisionForest               DF;                                                   //Decision Forest
         CMatrixDouble                 DF_SIGNAL;                                            //Decision Forest Matrix for inputs and output
         CDFReport                     DF_REPORT;                                            //Decision Forest Report for results
         int                           DF_INFO;                                              //Decision Forest feedback

         double                        m_out_calculations[2], m_in_calculations[__INPUTS];   //Decision Forest calculation arrays

         //--- adjusted parameters
         bool                          m_reset;
         int                           m_trees;
         double                        m_regularization;
         int                           m_trainings;
         //--- methods of setting adjustable parameters
         void                          Reset(bool value){ m_reset=value; }
         void                          Trees(int value){ m_trees=value; }
         void                          Regularization(double value){ m_regularization=value; }
         void                          Trainings(int value){ m_trainings=value; }
         
         //Decision Forest FUZZY system objects
         CMamdaniFuzzySystem           *m_fuzzy;
         
         CFuzzyVariable                *m_in_variables[__INPUTS];
         CFuzzyVariable                *m_out_variable;

         CDictionary_Obj_Double        *m_in_text[__INPUTS];
         CDictionary_Obj_Double        *m_out_text;

         CMamdaniFuzzyRule             *m_rule[__RULES];
         CList                         *m_in_list;

         double                        m_signals[][__INPUTS];
         
         CNormalMembershipFunction     *m_update;
         
         datetime                      m_last_time;
         double                        m_last_signal;
         double                        m_last_condition;

                                       CSignalSE(void);
                                       ~CSignalSE(void);
         //--- method of verification of settings
         virtual bool                  ValidationSettings(void);
         //--- method of creating the indicator and timeseries
         virtual bool                  InitIndicators(CIndicators *indicators);
         //--- methods of checking if the market models are formed
         virtual int                   LongCondition(void);
         virtual int                   ShortCondition(void);

         bool                          m_random;
         bool                          m_read_forest;
         int                           m_samples;

         //--- method of initialization of the oscillator
         bool                          InitSE(CIndicators *indicators);
         
         double                        Data(int Index){ return(Close(StartIndex()+Index)-Close(StartIndex()+Index+1)); }
         
         void                          ReadForest();
         void                          WriteForest();
         
         void                          SignalUpdate(double Signal);
         void                          ResultUpdate(double Result);
         
         double                        Signal(void);
         double                        Result(void);
         
         bool                          IsNewBar(void);
  };

 

2.1.1 Sinais

Essa entropia será ponderada pelo índice de atualidade. 

            if(_data>0.0)
            {
               _long_entropy-=((1.0/__SIGNALS[i])*((__SIGNALS[i]-s)/__SIGNALS[i])*(fabs(_data)/_range)*(log10(1.0/__SIGNALS[i])/log10(2.0)));
            }
            else if(_data<0.0)
            {
               _short_entropy-=((1.0/__SIGNALS[i])*((__SIGNALS[i]-s)/__SIGNALS[i])*(fabs(_data)/_range)*(log10(1.0/__SIGNALS[i])/log10(2.0)));
            }

E também será ponderado pela magnitude das barras de preço.

            if(_data>0.0)
            {
               _long_entropy-=((1.0/__SIGNALS[i])*((__SIGNALS[i]-s)/__SIGNALS[i])*(fabs(_data)/_range)*(log10(1.0/__SIGNALS[i])/log10(2.0)));
            }
            else if(_data<0.0)
            {
               _short_entropy-=((1.0/__SIGNALS[i])*((__SIGNALS[i]-s)/__SIGNALS[i])*(fabs(_data)/_range)*(log10(1.0/__SIGNALS[i])/log10(2.0)));
            }

O sinal gerado será a entropia das barras negativas menos a entropia das barras positivas. O raciocínio aqui é se a entropia das barras negativas exceder a das barras positivas, então temos menos informações sobre as barras negativas e, portanto, uma posição vendida do que para as barras positivas, que também implicam uma posição comprada. Na superfície, parece que este será um sistema de tendência 'perigoso'! No entanto, devido aos pesos anexados acima no cálculo da entropia, esse pode não ser o caso.

Os sinais serão atualizados quando a condição de compra ou venda exceder o limite de abertura, pois isso implica que uma posição será aberta. Isso acontecerá no timer, então modificaremos o expert montado pelo assistente para atender a isso.

//+------------------------------------------------------------------+
//| "Timer" event handler function                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   if(PositionSelect(Symbol()) && Signal_ThresholdClose<=fabs(filter0.m_last_condition))
     {
      filter0.ResultUpdate(filter0.Result());
     }
   //
   if(!PositionSelect(Symbol()) && Signal_ThresholdOpen<=fabs(filter0.m_last_condition))
     {
      filter0.SignalUpdate(filter0.m_last_signal);
     }
   ExtExpert.OnTimer();
  }

A função de origem na classe só será executada na otimização conforme já mencionado.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+  
void CSignalSE::SignalUpdate(double Signal)
   {
      if(MQLInfoInteger(MQL_OPTIMIZATION))
      {
         m_samples++;
         DF_SIGNAL.Resize(m_samples,__INPUTS+2);
         
         for(int i=0;i<__INPUTS;i++)
         {
            DF_SIGNAL[m_samples-1].Set(i,m_signals[0][i]);
         }
         //
         DF_SIGNAL[m_samples-1].Set(__INPUTS,Signal);
         DF_SIGNAL[m_samples-1].Set(__INPUTS+1,1-Signal);    
      }
   }

 

2.1.2 Resultados

Os resultados serão baseados no lucro da última posição fechada.  

      if(HistorySelect(0,m_symbol.Time()))
      {
         int _deals=HistoryDealsTotal();
         
         for(int d=_deals-1;d>=0;d--)
         {
            ulong _deal_ticket=HistoryDealGetTicket(d);
            if(HistoryDealSelect(_deal_ticket))
            {
               if(HistoryDealGetInteger(_deal_ticket,DEAL_ENTRY)==DEAL_ENTRY_OUT)
               {
                  _result=HistoryDealGetDouble(_deal_ticket,DEAL_PROFIT);
                  break;
               }
            }
         }
      }
   
      return(_result);

E eles serão atualizados quando a condição de compra ou venda exceder o limite de fechamento, pois isso implica que uma posição será fechada. Isso também acontecerá no cronômetro com a função de classe apenas atualizando os arquivos da floresta de decisão ao otimizar.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+  
void CSignalSE::ResultUpdate(double Result)
   {
      if(MQLInfoInteger(MQL_OPTIMIZATION))
      {
         int _err;
         if(Result<0.0) 
         {
            double _odds = MathRandomUniform(0,1,_err);
            //
            DF_SIGNAL[m_samples-1].Set(__INPUTS,_odds);
            DF_SIGNAL[m_samples-1].Set(__INPUTS+1,1-_odds);
         }
      }
   }


2.1.3 Escrita da Floresta

A floresta será gravada no tick antes de uma leitura, portanto, modificamos o expert montado pelo assistente para acomodar isso. 

//+------------------------------------------------------------------+
//| "Tick" event handler function                                    |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(!signal_se.m_read_forest) signal_se.WriteForest();
   
   ExtExpert.OnTick();
  }


2.1.4 Leitura da Floresta

A floresta será lida no testador no final de uma passagem do testador, então modificamos o expert montado pelo assistente para acomodar isso. 

//+------------------------------------------------------------------+
//| "Tester" event handler function                                  |
//+------------------------------------------------------------------+  
double OnTester()
   {
    signal_se.ReadForest();
    return(0.0);
   }


2.2 Classe Money do Expert

Para este artigo, também estamos explorando a criação de uma classe de dimensionamento de posição personalizada para ser usada com o assistente. Pegaremos a classe 'Money Size Optimized' e a modificaremos para normalizar os tamanhos das posições com base na entropia de Shannon. Nossa nova interface ficará assim: 

// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Trading with 'Shannon Entropy' optimized trade volume      |
//| Type=Money                                                       |
//| Name=SE                                                          |
//| Class=CMoneySE                                                   |
//| Page=money_se                                                    |
//| Parameter=ScaleFactor,int,3,Scale factor                         |
//| Parameter=Percent,double,10.0,Percent                            |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CMoneySE.                                                  |
//| Purpose: Class of money management with 'Shannon Entropy' optimized volume.          |
//|              Derives from class CExpertMoney.                    |
//+------------------------------------------------------------------+
class CMoneySE : public CExpertMoney
  {
protected:
   int               m_scale_factor;

public:
   double            m_absolute_condition;
   
                     CMoneySE(void);
                    ~CMoneySE(void);
   //---
   void              ScaleFactor(int scale_factor) { m_scale_factor=scale_factor; }
   void              AbsoluteCondition(double absolute_condition) { m_absolute_condition=absolute_condition; }
   virtual bool      ValidationSettings(void);
   //---
   virtual double    CheckOpenLong(double price,double sl);
   virtual double    CheckOpenShort(double price,double sl);

protected:
   double            Optimize(double lots);
  };

 A variável 'm_absolute_condition' será o valor absoluto do(s) inteiro(s) retornado(s) pelas funções 'LongCondition' e 'ShortCondition'. Como ele é um valor normalizado, nós podemos usar o seu tamanho para dimensionar o nosso tamanho da posição. Essa variável será passada da classe signal para a classe money por meio das modificações no expert montado pelo assistente.

//+------------------------------------------------------------------+
//| Global expert object                                             |
//+------------------------------------------------------------------+
CExpert ExtExpert;
CSignalSE *signal_se;
CMoneySE *money_se;

E na função tick

//+------------------------------------------------------------------+
//| "Tick" event handler function                                    |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(!signal_se.m_read_forest) signal_se.WriteForest();
   
   money_se.AbsoluteCondition(fabs(signal_se.m_last_condition));
   
   ExtExpert.OnTick();
  }

E as principais modificações estarão na função 'Optimize' abaixo: 

//+------------------------------------------------------------------+
//| Optimizing lot size for open.                                    |
//+------------------------------------------------------------------+
double CMoneySE::Optimize(double lots)
  {
   double lot=lots;
   
      //--- normalize lot size based on magnitude of condition
      lot*=(20*m_scale_factor/fmax(20.0,((100.0-m_absolute_condition)/100.0)*20.0*m_scale_factor*m_scale_factor));
      
      //--- reduce lot based on number of losses orders without a break
      if(m_scale_factor>0)
      {
         //--- select history for access
         HistorySelect(0,TimeCurrent());
         //---
         int       orders=HistoryDealsTotal();  // total history deals
         int       losses=0;                    // number of consequent losing orders
         CDealInfo deal;
         //---
         for(int i=orders-1;i>=0;i--)
         {
            deal.Ticket(HistoryDealGetTicket(i));
            if(deal.Ticket()==0)
            {
               Print("CMoneySE::Optimize: HistoryDealGetTicket failed, no trade history");
               break;
            }
            //--- check symbol
            if(deal.Symbol()!=m_symbol.Name())
               continue;
            //--- check profit
            double profit=deal.Profit();
            if(profit>0.0)
               break;
            if(profit<0.0)
               losses++;
         }
         //---
         if(losses>1){
         lot*=m_scale_factor;
         lot/=(losses+m_scale_factor);
         lot=NormalizeDouble(lot,2);}
      }
      //--- normalize and check limits
      double stepvol=m_symbol.LotsStep();
      lot=stepvol*NormalizeDouble(lot/stepvol,0);
      //---
      double minvol=m_symbol.LotsMin();
      if(lot<minvol){ lot=minvol; }
      //---
      double maxvol=m_symbol.LotsMax();
      if(lot>maxvol){ lot=maxvol; }
//---
   return(lot);
  }

 

3.0 Assistente MQL5

Nós vamos desenvolver dois expert advisors, um com apenas a classe signal que criamos, mais a negociação de volume mínimo para gestão do dinheiro, e o segundo com as classes signal e gestão de dinheiro que criamos.


4.0 Testador de Estratégia

A otimização em execução para o primeiro expert fornece um fator de lucro de 2.89 e um índice de Sharpe de 4.87 versus um fator de lucro de 3.65 e índice de Sharpe de 5.79 da otimização do segundo expert.

 

Primeiro relatório

 

s_r

 

Primeira curva de patrimônio


s_c

 

Segundo relatório

 

m_r

 

Segunda curva de patrimônio

 

m_c


5.0 Conclusão

Os experts anexados foram otimizados nos preços de abertura do período de 4 horas para os níveis ideais de take profit e stop loss. Isso significa que você não pode replicar esses resultados em uma conta real ou mesmo no testador de estratégia em todos os modos de tick. Não era esse o objetivo do artigo. Em vez de tentar criar um graal de que todos devem replicar essas séries de artigos, procure expor ideias distintas que podem ser personalizadas ainda mais para que cada trader possa apresentar sua vantagem. Os mercados em geral ainda estão fortemente correlacionados, e é por isso que procurar uma vantagem pode ser útil em uma alta volatilidade. Obrigado por ler!

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

Arquivos anexados |
expert_se.mq5 (7.48 KB)
se.mq5 (7.75 KB)
SignalSE.mqh (24.84 KB)
MoneySE.mqh (6.55 KB)
DoEasy. Controles (Parte 23): apurando os objetos WinForms TabControl e SplitContainer DoEasy. Controles (Parte 23): apurando os objetos WinForms TabControl e SplitContainer
Neste artigo, incluiremos novos eventos de mouse relacionados aos limites das áreas de trabalho dos objetos WinForms e corrigiremos algumas falhas na funcionalidade dos controles TabControl e SplitContainer.
Redes neurais de maneira fácil (Parte 31): Algoritmos evolutivos Redes neurais de maneira fácil (Parte 31): Algoritmos evolutivos
No último artigo, iniciamos a análise dos métodos de otimização sem gradiente, e nos familiarizamos com o algoritmo genético. Hoje, continuaremos a discutir o mesmo assunto e também examinaremos outra classe de algoritmos evolutivos.
Indicadores adaptativos Indicadores adaptativos
Neste artigo, exploraremos diferentes enfoques para desenvolver indicadores adaptativos. Esses indicadores se destacam pelo uso de feedback entre as entradas e saídas, o que permite que eles se adaptem de forma autônoma para processar séries temporais financeiras de forma eficiente.
Algoritmos de otimização populacionais: Otimização de colônia de formigas (ACO) Algoritmos de otimização populacionais: Otimização de colônia de formigas (ACO)
Desta vez, vamos dar uma olhada no algoritmo de otimização de colônia de formigas ("Ant Colony optimization algorithm", em inglês). O algoritmo é muito interessante e ambíguo. Trata-se de uma tentativa de criar um novo tipo de ACO.