English Русский Español Deutsch 日本語
preview
Experimentos com redes neurais (Parte 7): Transferência de indicadores

Experimentos com redes neurais (Parte 7): Transferência de indicadores

MetaTrader 5Sistemas de negociação | 26 março 2024, 13:25
107 0
Roman Poshtar
Roman Poshtar

Introdução

Boa tarde, caros usuários da comunidade MQL5.  Hoje falaremos mais sobre a importância de alimentar as redes neurais com dados significativos, isto é, com as chamadas séries temporais.  Em meus artigos anteriores dedicados a experimentos com redes neurais, mencionei isso várias vezes. Hoje, vamos abrir um novo capítulo e passar diretamente para a transferência dos indicadores amados por todos. Vamos fazer isso de forma séria, introduzindo alguns novos conceitos que uso quando trabalho com redes neurais. Embora eu pense que isso não seja o limite, e com o tempo, eu desenvolverei uma nova visão para entender exatamente o que passar e como. Mas, por enquanto, temos o que temos e é com isso que trabalharemos. Então vamos lá.


Antecedentes e observações

Quando me dou ao trabalho de ler diversos artigos sobre o assunto, vejo sempre uma imagem triste dos resultados imediatos obtidos com os sistemas de negociação baseados em redes neurais. Muitas ideias e algoritmos muito bons não produzem os resultados desejados.

Sempre se observa o mesmo cenário durante a passagem de parâmetros de entrada. Por exemplo, ao transferir diretamente os valores dos indicadores osciladores, valores esses que, na minha opinião, não têm nada a ver com o preço do ativo. Os osciladores têm um problema bem conhecido, lembremos da chamada divergência. Esses valores de abertura, fechamento, High e Low, que quando transferidos diretamente não fazem sentido, mas introduzem no sistema um ruído estranho que não se percebe, e com o qual muitos tentam treinar esses sistemas. Na verdade, esses valores não estão vinculados a nada e têm uma variação significativa com o passar do tempo. Por exemplo, abra o gráfico diário de qualquer par de moedas e observe o intervalo de variação dos preços de fechamento.



Teoria e conceitos

Nesta seção, vou detalhar alguns conceitos que classifiquei para mim mesmo e uso quando conduzo meus experimentos.

  1. Distâncias – distâncias de um indicador a outro ou ao seu valor zero. Na minha opinião, basicamente é vincular a situação atual a um valor estável no histórico. Se passarmos o valor atual do indicador MA 1, obteremos uma dispersão de amostra que não se percebe, pois o valor do preço muda com o tempo e não "se moveu" dentro de um determinado intervalo, o que sugere classificação ou a menor insinuação de comportamento estatístico. A situação é diferente quando passamos a diferença entre dois indicadores, por exemplo, MA 1 e MA 100 em pontos, ou a distância atual na vela zero do indicador MACD com seu valor 4 velas atrás. Assim, por meio de distâncias, podemos determinar o quão longe o mercado se moveu em relação ao seu valor médio; ou quão sobrecomprado ou sobrevendido está em comparação com a amostra do histórico no momento atual. Também por meio da distância, determinamos para onde o mercado está se movendo, para cima ou para baixo, e é aqui que o valor pode ser tanto um número positivo quanto negativo.

  2. Acumulação – cálculo do valor total do(s) indicador(es) em relação a outro(s) ou ao seu ponto zero, ou ao ponto de valor zero em alguns indicadores diferentes de zero. Assim, podemos determinar, por meio da acumulação, a duração de um determinado movimento em uma direção específica. Se a acumulação for pequena, possivelmente está ocorrendo uma consolidação no momento e, inversamente, se a acumulação for grande, poderá haver uma tendência prolongada. Dependendo do sinal, seja ele - ou +, é possível saber qual é a direção. Em outras palavras, os valores de acumulação não têm grande importância durante a "oscilação", uma vez que a consolidação tem valores maiores durante as tendências.

  3. Ângulos de inclinação – o ângulo de inclinação atual de um indicador é uma maneira muito boa de informar a rede neural sobre o movimento impulsivo no momento ou sua ausência e o declínio da atividade do instrumento. A capacidade de determinar os ângulos de inclinação dos indicadores ao longo de um certo histórico, por exemplo, 10 velas, provou ser eficaz na análise da situação atual em comparação com os resultados de amostras históricas. Lembro que eu meço os ângulos de inclinação em radianos, este é o único método que se adequou pessoalmente a mim e não depende da escala do gráfico. 



Exemplos

Exemplos de uso de distâncias:

  • Passagem de distâncias na atual vela zero. Indicador MA 1 em relação ao MA 100. Indicador MACD em relação ao seu valor atual e zero. Indicador CCI em relação ao seu valor atual e ao zero.
#property copyright   "2023, Roman Poshtar"
#property link        "https://www.mql5.com/ru/users/romanuch"
#property strict
#property version   "1.0"

input int    x1 = 1;
input int    x2 = 1;
input int    x3 = 1;

int handle_In1S1;
int handle_In2S1;
int handle_In3S1;
int handle_In4S1;

double ind_In1S1[];
double ind_In2S1[];
double ind_In3S1[];
double ind_In4S1[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {

   handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In1S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In2S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In3S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In4S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In1S1,true);
   if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In2S1,true);
   if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In3S1,true);
   if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In4S1,true);
   if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1))
     {
      return;
     }
//---

   perceptron1();

  }

//+------------------------------------------------------------------+
//|  The PERCEPRRON - a perceiving and recognizing function          |
//+------------------------------------------------------------------+
double perceptron1()
  {

   double w1 = x1 - 10.0;
   double w2 = x2 - 10.0;
   double w3 = x3 - 10.0;

   double a1 = ((ind_In1S1[0]-ind_In2S1[0])/Point());

   double a2 = ind_In3S1[0];

   double a3 = ind_In4S1[0];

   Print("a1 = ", a1);
   Print("a2 = ", a2);
   Print("a3 = ", a3);
   Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3));
   Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

   return (w1 * a1 + w2 * a2 + w3 * a3);

  }

Informações registradas no log:

Exemplo de distância 1

a1 - diferença em pontos do par de moedas entre o indicador MA 1 e MA 100. Pode ser tanto positivo quanto negativo.

a2 - valor atual do indicador MACD. Pode ser tanto positivo quanto negativo.

a3 - valor atual do indicador CCI. Pode ser tanto positivo quanto negativo.

  • Passagem de distâncias para N-quantidade de velas atrás. Indicador MA 1. Indicador MA 100. Indicador MACD. Indicador CCI.
#property copyright   "2023, Roman Poshtar"
#property link        "https://www.mql5.com/ru/users/romanuch"
#property strict
#property version   "1.0"

input int    Candles= 10;

input int    x1 = 1;
input int    x2 = 1;
input int    x3 = 1;
input int    x4 = 1;

int handle_In1S1;
int handle_In2S1;
int handle_In3S1;
int handle_In4S1;

double ind_In1S1[];
double ind_In2S1[];
double ind_In3S1[];
double ind_In4S1[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {

   handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In1S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In2S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In3S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In4S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In1S1,true);
   if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In2S1,true);
   if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In3S1,true);
   if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In4S1,true);
   if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1))
     {
      return;
     }
//---

   perceptron1();

  }

//+------------------------------------------------------------------+
//|  The PERCEPRRON - a perceiving and recognizing function          |
//+------------------------------------------------------------------+
double perceptron1()
  {

   double w1 = x1 - 10.0;
   double w2 = x2 - 10.0;
   double w3 = x3 - 10.0;
   double w4 = x4 - 10.0;

   double a1 = ((ind_In1S1[0]-ind_In1S1[Candles])/Point());

   double a2 = ((ind_In2S1[0]-ind_In2S1[Candles])/Point());

   double a3 = ind_In3S1[0]-ind_In3S1[Candles];
   
   double a4 = ind_In4S1[0]-ind_In4S1[Candles];

   Print("a1 = ", a1);
   Print("a2 = ", a2);
   Print("a3 = ", a3);
   Print("a3 = ", a4);
   Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4));
   Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

   return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4);

  }

Informações registradas no log:

Exemplo de distância 2

a1 - diferença em pontos do par de moedas pelo indicador MA 1 na vela 0 e na vela 10. Pode ser tanto positivo quanto negativo.

a2 - diferença em pontos do par de moedas pelo indicador MA 100 na vela 0 e na vela 10. Pode ser tanto positivo quanto negativo.

a3 - diferença no valor do indicador MACD na vela 0 e na vela 10. Pode ser tanto positivo quanto negativo.

a4 - diferença no valor do indicador CCI na vela 0 e na vela 10. Pode ser tanto positivo quanto negativo.

  • Passagem das distâncias do ponto de cruzamento dos indicadores MA1 e MA 100 em relação ao seu valor zero no passado. Indicador MACD em relação ao seu valor zero no passado. Indicador CCI em relação ao seu valor zero no passado.
#property copyright   "2023, Roman Poshtar"
#property link        "https://www.mql5.com/ru/users/romanuch"
#property strict
#property version   "1.0"

input int    Candles= 10;

input int    x1 = 1;
input int    x2 = 1;
input int    x3 = 1;
input int    x4 = 1;

int handle_In1S1;
int handle_In2S1;
int handle_In3S1;
int handle_In4S1;

double ind_In1S1[];
double ind_In2S1[];
double ind_In3S1[];
double ind_In4S1[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {

   handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In1S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In2S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In3S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In4S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In1S1,true);
   if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In2S1,true);
   if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In3S1,true);
   if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In4S1,true);
   if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1))
     {
      return;
     }
//---

   perceptron1();

  }

//+------------------------------------------------------------------+
//|  The PERCEPRRON - a perceiving and recognizing function          |
//+------------------------------------------------------------------+
double perceptron1()
  {
  
  int c1=0;
  int c2=0;
  int c3=0;

   double w1 = x1 - 10.0;
   double w2 = x2 - 10.0;
   double w3 = x3 - 10.0;
   double w4 = x4 - 10.0;
   
   for(int i=0; i<=1000; i++){
   
    if(ind_In1S1[0]>ind_In2S1[0]){if (ind_In1S1[i]<ind_In2S1[i]){c1=i; break;}}
    
    if(ind_In1S1[0]<ind_In2S1[0]){if (ind_In1S1[i]>ind_In2S1[i]){c1=i; break;}}
   
   }   

   double a1 = ((ind_In1S1[0]-ind_In1S1[c1])/Point());
   
   double a2 = ((ind_In2S1[0]-ind_In2S1[c1])/Point());
   
   for(int i=0; i<=1000; i++){
   
    if(ind_In3S1[0]>0){if (ind_In3S1[i]<0){c2=i; break;}}
    
    if(ind_In3S1[0]<0){if (ind_In3S1[i]>0){c2=i; break;}}
   
   }      

   double a3 = ind_In3S1[0]-ind_In3S1[c2];
   
   for(int i=0; i<=1000; i++){
   
    if(ind_In4S1[0]>0){if (ind_In4S1[i]<0){c3=i; break;}}
    
    if(ind_In4S1[0]<0){if (ind_In4S1[i]>0){c3=i; break;}}
   
   }       
   
   double a4 = ind_In4S1[0]-ind_In4S1[c3];

   Print("a1 = ", a1);
   Print("a2 = ", a2);
   Print("a3 = ", a3);
   Print("a4 = ", a4);
   Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4));
   Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

   return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4);

  }

Informações registradas no log:

Exemplo de distância 3

a1 - diferença em pontos do par de moedas pelo indicador MA 1 na vela 0 e a vela em que ocorreu o último cruzamento dos indicadores MA1 e MA 100. Pode ser tanto positivo quanto negativo.

a2 - diferença em pontos do par de moedas pelo indicador MA 100 na vela 0 e a vela em que ocorreu o último cruzamento dos indicadores MA1 e MA 100. Pode ser tanto positivo quanto negativo.

a3 - diferença no valor do indicador MACD na vela 0 e na vela onde ocorreu o último cruzamento com o valor 0. Pode ser tanto positivo quanto negativo.

a4 - diferença no valor do indicador CCI na vela 0 e na vela onde ocorreu o último cruzamento com o valor 0. Pode ser tanto positivo quanto negativo.

A busca por valores de cruzamento é previamente realizada em um laço.


Exemplos de uso do acúmulo para passagem ao perceptron:

  • Passagem do acúmulo por N-quantidade de velas do indicador.
#property copyright   "2023, Roman Poshtar"
#property link        "https://www.mql5.com/ru/users/romanuch"
#property strict
#property version   "1.0"

input int    Candles= 10;

input int    x1 = 1;
input int    x2 = 1;
input int    x3 = 1;

int handle_In1S1;
int handle_In2S1;
int handle_In3S1;
int handle_In4S1;

double ind_In1S1[];
double ind_In2S1[];
double ind_In3S1[];
double ind_In4S1[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {

   handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In1S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In2S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In3S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In4S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In1S1,true);
   if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In2S1,true);
   if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In3S1,true);
   if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In4S1,true);
   if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1))
     {
      return;
     }
//---

   perceptron1();

  }

//+------------------------------------------------------------------+
//|  The PERCEPRRON - a perceiving and recognizing function          |
//+------------------------------------------------------------------+
double perceptron1()
  {
   double sum1 = 0;
   double sum2 = 0;
   double sum3 = 0;

   double w1 = x1 - 10.0;
   double w2 = x2 - 10.0;
   double w3 = x3 - 10.0;

   for(int i=0; i<=Candles; i++)
     {

      sum1+=ind_In1S1[i]-ind_In2S1[i];

     }

   double a1 = sum1;

   for(int i=0; i<=Candles; i++)
     {

      sum2+=ind_In3S1[i];

     }

   double a2 = sum2;

   for(int i=0; i<=Candles; i++)
     {

      sum3+=ind_In4S1[i];

     }

   double a3 = sum3;

   Print("a1 = ", a1);
   Print("a2 = ", a2);
   Print("a3 = ", a3);
   Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3));
   Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

   return (w1 * a1 + w2 * a2 + w3 * a3);

  }

Informações registradas no log:

Exemplo de acúmulo 1

a1 - acúmulo da diferença entre os indicadores MA1 e MA 100 pelo número de velas do parâmetro Candles. Pode ser tanto positivo quanto negativo.

a2 - acúmulo do indicador MACD pelo número de velas do parâmetro Candles. Pode ser tanto positivo quanto negativo.

a3 - acúmulo do indicador CCI pelo número de velas do parâmetro Candles. Pode ser tanto positivo quanto negativo.

  • Passagem do acúmulo a partir do ponto zero do indicador no passado ou do último cruzamento dos indicadores no passado.
#property copyright   "2023, Roman Poshtar"
#property link        "https://www.mql5.com/ru/users/romanuch"
#property strict
#property version   "1.0"

input int    Candles= 10;

input int    x1 = 1;
input int    x2 = 1;
input int    x3 = 1;

int handle_In1S1;
int handle_In2S1;
int handle_In3S1;
int handle_In4S1;

double ind_In1S1[];
double ind_In2S1[];
double ind_In3S1[];
double ind_In4S1[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {

   handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In1S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In2S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In3S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In4S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In1S1,true);
   if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In2S1,true);
   if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In3S1,true);
   if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In4S1,true);
   if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1))
     {
      return;
     }
//---

   perceptron1();

  }

//+------------------------------------------------------------------+
//|  The PERCEPRRON - a perceiving and recognizing function          |
//+------------------------------------------------------------------+
double perceptron1()
  {
   double sum1 = 0;
   double sum2 = 0;
   double sum3 = 0;

   double w1 = x1 - 10.0;
   double w2 = x2 - 10.0;
   double w3 = x3 - 10.0;

   for(int i=0; i<=1000; i++)
     {

      if(ind_In1S1[0]>ind_In2S1[0])
        {
         if(ind_In1S1[i]<ind_In2S1[i])
           {
            break;
           };
         sum1+=(ind_In1S1[i]-ind_In2S1[i]);
        }

      if(ind_In1S1[0]<ind_In2S1[0])
        {
         if(ind_In1S1[i]>ind_In2S1[i])
           {
            break;
           };
         sum1+=(ind_In1S1[i]-ind_In2S1[i]);
        }

     }

   double a1 = sum1;

   for(int i=0; i<=1000; i++)
     {

      if(ind_In3S1[0]>0)
        {
         if(ind_In3S1[i]<0)
           {
            break;
           };
         sum2+=ind_In3S1[i];
        }

      if(ind_In3S1[0]<0)
        {
         if(ind_In3S1[i]>0)
           {
            break;
           };
         sum2+=ind_In3S1[i];
        }

     }

   double a2 = sum2;

   for(int i=0; i<=1000; i++)
     {

      if(ind_In4S1[0]>0)
        {
         if(ind_In4S1[i]<0)
           {
            break;
           };
         sum3+=ind_In4S1[i];
        }

      if(ind_In4S1[0]<0)
        {
         if(ind_In4S1[i]>0)
           {
            break;
           };
         sum3+=ind_In4S1[i];
        }

     }

   double a3 = sum3;

   Print("a1 = ", a1);
   Print("a2 = ", a2);
   Print("a3 = ", a3);
   Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3));
   Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

   return (w1 * a1 + w2 * a2 + w3 * a3);

  }

Informações registradas no log:

Exemplo de acúmulo 2

a1 - acúmulo da diferença entre os indicadores MA1 e MA 100 a partir do ponto do último cruzamento. Pode ser tanto positivo quanto negativo.

a2 - acúmulo do indicador MACD a partir do ponto do último cruzamento com o valor 0. Pode ser tanto positivo quanto negativo.

a3 - acúmulo do indicador CCI a partir do ponto do último cruzamento com o valor 0. Pode ser tanto positivo quanto negativo.


Exemplos de uso dos ângulos de inclinação dos indicadores:

  • Passagem dos ângulos de inclinação por N quantidade de velas do indicador.
#property copyright   "2023, Roman Poshtar"
#property link        "https://www.mql5.com/ru/users/romanuch"
#property strict
#property version   "1.0"

input int    Candles= 10;

input int    x1 = 1;
input int    x2 = 1;
input int    x3 = 1;
input int    x4 = 1;

int handle_In1S1;
int handle_In2S1;
int handle_In3S1;
int handle_In4S1;

double ind_In1S1[];
double ind_In2S1[];
double ind_In3S1[];
double ind_In4S1[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {

   handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In1S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In2S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In3S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In4S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In1S1,true);
   if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In2S1,true);
   if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In3S1,true);
   if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In4S1,true);
   if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1))
     {
      return;
     }
//---

   perceptron1();

  }

//+------------------------------------------------------------------+
//|  The PERCEPRRON - a perceiving and recognizing function          |
//+------------------------------------------------------------------+
double perceptron1()
  {

   double w1 = x1 - 10.0;
   double w2 = x2 - 10.0;
   double w3 = x3 - 10.0;
   double w4 = x4 - 10.0;

   double a1 = (((ind_In1S1[0]-ind_In1S1[Candles])/Point())/Candles);

   double a2 = (((ind_In2S1[0]-ind_In2S1[Candles])/Point())/Candles);

   double a3 = ((ind_In3S1[0]-ind_In3S1[Candles])/Candles);

   double a4 = ((ind_In4S1[0]-ind_In4S1[Candles])/Candles);

   Print("a1 = ", a1);
   Print("a2 = ", a2);
   Print("a3 = ", a3);
   Print("a4 = ", a4);
   Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4));
   Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

   return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4);

  }

Informações registradas no log:

Exemplo de ângulos 1

a1 - ângulo de inclinação do indicador MA1 consoante a quantidade de velas do parâmetro Candles. Pode ser tanto positivo quanto negativo.

a2 - ângulo de inclinação do indicador MA100 consoante a quantidade de velas do parâmetro Candles. Pode ser tanto positivo quanto negativo.

a3 - ângulo de inclinação do indicador MACD consoante a quantidade de velas do parâmetro Candles. Pode ser tanto positivo quanto negativo.

a4 - ângulo de inclinação do indicador CCI consoante a quantidade de velas do parâmetro Candles. Pode ser tanto positivo quanto negativo.

  • Passagem dos ângulos de inclinação a partir do ponto zero do indicador no passado ou do último cruzamento dos indicadores no passado.
#property copyright   "2023, Roman Poshtar"
#property link        "https://www.mql5.com/ru/users/romanuch"
#property strict
#property version   "1.0"

input int    x1 = 1;
input int    x2 = 1;
input int    x3 = 1;
input int    x4 = 1;

int handle_In1S1;
int handle_In2S1;
int handle_In3S1;
int handle_In4S1;

double ind_In1S1[];
double ind_In2S1[];
double ind_In3S1[];
double ind_In4S1[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {

   handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In1S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In2S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In3S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In4S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In1S1,true);
   if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In2S1,true);
   if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In3S1,true);
   if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In4S1,true);
   if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1))
     {
      return;
     }
//---

   perceptron1();

  }

//+------------------------------------------------------------------+
//|  The PERCEPRRON - a perceiving and recognizing function          |
//+------------------------------------------------------------------+
double perceptron1()
  {

   int c1=0;
   int c2=0;
   int c3=0;

   double w1 = x1 - 10.0;
   double w2 = x2 - 10.0;
   double w3 = x3 - 10.0;
   double w4 = x4 - 10.0;

   for(int i=0; i<=1000; i++)
     {

      if(ind_In1S1[0]>ind_In2S1[0])
        {
         if(ind_In1S1[i]<ind_In2S1[i])
           {
            c1=i;
            break;
           }
        }

      if(ind_In1S1[0]<ind_In2S1[0])
        {
         if(ind_In1S1[i]>ind_In2S1[i])
           {
            c1=i;
            break;
           }
        }

     }

   double a1 = (((ind_In1S1[0]-ind_In1S1[c1])/Point())/c1);

   double a2 = (((ind_In2S1[0]-ind_In2S1[c1])/Point())/c1);

   for(int i=0; i<=1000; i++)
     {

      if(ind_In3S1[0]>0)
        {
         if(ind_In3S1[i]<0)
           {
            c2=i;
            break;
           }
        }

      if(ind_In3S1[0]<0)
        {
         if(ind_In3S1[i]>0)
           {
            c2=i;
            break;
           }
        }

     }

   double a3 = ((ind_In3S1[0]-ind_In3S1[c2])/c2);

   for(int i=0; i<=1000; i++)
     {

      if(ind_In4S1[0]>0)
        {
         if(ind_In4S1[i]<0)
           {
            c3=i;
            break;
           }
        }

      if(ind_In4S1[0]<0)
        {
         if(ind_In4S1[i]>0)
           {
            c3=i;
            break;
           }
        }

     }

   double a4 = ((ind_In4S1[0]-ind_In4S1[c3])/c3);

   Print("a1 = ", a1);
   Print("a2 = ", a2);
   Print("a3 = ", a3);
   Print("a4 = ", a4);
   Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4));
   Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

   return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4);

  }

Informações registradas no log:

Exemplo de ângulos 2

a1 - ângulo de inclinação do indicador MA1 a partir do ponto do último cruzamento dos indicadores MA1 e MA100. Pode ser tanto positivo quanto negativo.

a2 - ângulo de inclinação do indicador MA100 a partir do ponto do último cruzamento dos indicadores MA1 e MA100. Pode ser tanto positivo quanto negativo.

a3 - ângulo de inclinação do indicador MACD a partir do ponto do último cruzamento com o valor 0. Pode ser tanto positivo quanto negativo.

a4 - ângulo de inclinação do indicador CCI a partir do ponto do último cruzamento com o valor 0. Pode ser tanto positivo quanto negativo.


Exemplo de uso de valores combinados para passagem ao perceptron:

  • Passagem combinada de valores dos dois indicadores MA1 e MA100.
#property copyright   "2023, Roman Poshtar"
#property link        "https://www.mql5.com/ru/users/romanuch"
#property strict
#property version   "1.0"

input int    Candles= 10;

input int    x1 = 1;
input int    x2 = 1;
input int    x3 = 1;
input int    x4 = 1;
input int    x5 = 1;
input int    x6 = 1;
input int    x7 = 1;

int handle_In1S1;
int handle_In2S1;

double ind_In1S1[];
double ind_In2S1[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {

   handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In1S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In2S1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In1S1,true);
   if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1))
     {
      return;
     }
//---

//--- get data from the three buffers of the i-Regr indicator
   ArraySetAsSeries(ind_In2S1,true);
   if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1))
     {
      return;
     }
//---

   perceptron1();

  }

//+------------------------------------------------------------------+
//|  The PERCEPRRON - a perceiving and recognizing function          |
//+------------------------------------------------------------------+
double perceptron1()
  {

   int c1=0;
   double sum1 = 0;
   double sum2 = 0;

   double w1 = x1 - 10.0;
   double w2 = x2 - 10.0;
   double w3 = x3 - 10.0;
   double w4 = x4 - 10.0;
   double w5 = x5 - 10.0;
   double w6 = x6 - 10.0;
   double w7 = x7 - 10.0;

   double a1 = ((ind_In1S1[0]-ind_In2S1[0])/Point());

   for(int i=0; i<=Candles; i++)
     {

      sum1+=ind_In1S1[i]-ind_In2S1[i];

     }

   double a2 = sum1;

   for(int i=0; i<=1000; i++)
     {

      if(ind_In1S1[0]>ind_In2S1[0])
        {
         if(ind_In1S1[i]<ind_In2S1[i])
           {
            break;
           };
         sum2+=(ind_In1S1[i]-ind_In2S1[i]);
        }

      if(ind_In1S1[0]<ind_In2S1[0])
        {
         if(ind_In1S1[i]>ind_In2S1[i])
           {
            break;
           };
         sum2+=(ind_In1S1[i]-ind_In2S1[i]);
        }

     }

   double a3 = sum2;

   double a4 = (((ind_In1S1[0]-ind_In1S1[Candles])/Point())/Candles);

   double a5 = (((ind_In2S1[0]-ind_In2S1[Candles])/Point())/Candles);

   for(int i=0; i<=1000; i++)
     {

      if(ind_In1S1[0]>ind_In2S1[0])
        {
         if(ind_In1S1[i]<ind_In2S1[i])
           {
            c1=i;
            break;
           }
        }

      if(ind_In1S1[0]<ind_In2S1[0])
        {
         if(ind_In1S1[i]>ind_In2S1[i])
           {
            c1=i;
            break;
           }
        }

     }

   double a6 = (((ind_In1S1[0]-ind_In1S1[c1])/Point())/c1);

   double a7 = (((ind_In2S1[0]-ind_In2S1[c1])/Point())/c1);

   Print("a1 = ", a1);
   Print("a2 = ", a2);
   Print("a3 = ", a3);
   Print("a4 = ", a4);
   Print("a5 = ", a5);
   Print("a6 = ", a6);
   Print("a7 = ", a7);
   Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4 + w5 * a5 + w6 * a6 + w7 * a7));
   Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

   return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4 + w5 * a5 + w6 * a6 + w7 * a7);

  }

Informações exibidas no log:

Exemplo de passagem combinada 1

a1 - distância entre os indicadores MA1 e MA100 na vela atual. Pode ser tanto positivo quanto negativo.

a2 - acúmulo entre os indicadores MA1 e MA100 consoante a quantidade de velas do parâmetro Candles. Pode ser tanto positivo quanto negativo.

a3 - acúmulo entre os indicadores MA1 e MA100 a partir do ponto do último cruzamento dos indicadores. Pode ser tanto positivo quanto negativo.

a4 - ângulo de inclinação do indicador MA1 consoante a quantidade de velas do parâmetro Candles. Pode ser tanto positivo quanto negativo.

a5 - ângulo de inclinação do indicador MA100 consoante a quantidade de velas do parâmetro Candles. Pode ser tanto positivo quanto negativo.

a6 - ângulo de inclinação do indicador MA1 a partir do ponto do último cruzamento dos indicadores. Pode ser tanto positivo quanto negativo.

a7 - ângulo de inclinação do indicador MA100 a partir do ponto do último cruzamento dos indicadores. Pode ser tanto positivo quanto negativo.


Expert Advisors

 Hoje, desenvolveremos 2 EAs. Como exemplo, utilizaremos os valores das distâncias entre os indicadores. O primeiro é destinado à otimização e ajuste de parâmetros. O segundo, diretamente para negociar com os resultados obtidos pelo primeiro. Por que isso, você pode perguntar? Tudo é simples, já examinamos essa abordagem em meus artigos anteriores. Este método ajuda a experimentar e usar na negociação todos os resultados de otimização disponíveis, não apenas um deles. Por exemplo, se obtemos 50 bons resultados durante a otimização. Concorda que não é muito conveniente definir 50 gráficos em um EA. Por isso, usamos todos os resultados simultaneamente com a ajuda do segundo EA.

Para mais detalhes sobre o método aplicado, você pode ler no meu artigo Experimentos com redes neurais (Parte 3): Aplicação prática

A seguir, apresento o código principal do primeiro EA para otimização e descrevo o que foi passado ao perceptron:

Código principal para abertura de posições.

      //SELL++++++++++++++++++++++++++++++++++++++++++++++++
      if((perceptron1()<-Param) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (SpreadS1<=MaxSpread))
        {
         OpenSell(symbolS1.Name(), LotsXSell, TP, SL, EAComment);
        }

      //BUY++++++++++++++++++++++++++++++++++++++++++++++++
      if((perceptron1()>Param) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (SpreadS1<=MaxSpread))
        {
         OpenBuy(symbolS1.Name(), LotsXBuy, TP, SL, EAComment);
        }

Código do perceptron.  

  1. a1 - distância entre o indicador MA1 na vela atual e na vela no parâmetro Candles.  
  2. a2 - distância entre o indicador MA100 na vela atual e na vela no parâmetro Candles.  
  3. a3 - distância entre o indicador CCI na vela atual e na vela no parâmetro Candles.  
  4. a4 - distância entre o indicador StdDev na vela atual e na vela no parâmetro Candles. 

O parâmetro Candles, neste caso, não foi otimizado e teve o valor 8.

//+------------------------------------------------------------------+
//|  The PERCEPRRON - a perceiving and recognizing function          |
//+------------------------------------------------------------------+
double perceptron1()
  {

   double w1 = x1 - 10.0;
   double w2 = x2 - 10.0;
   double w3 = x3 - 10.0;
   double w4 = x4 - 10.0;

   double a1 = ((ind_In1S1[0]-ind_In1S1[Candles])/PointS1);

   double a2 = ((ind_In2S1[0]-ind_In2S1[Candles])/PointS1);

   double a3 = (ind_In3S1[0]-ind_In3S1[Candles]);

   double a4 = (ind_In4S1[0]-ind_In4S1[Candles]);

   return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4);
  }


Aqui fornecerei todos os parâmetros para otimização e teste para não repetir mais adiante no texto:

  • Mercado Forex;
  • Par de moedas EURUSD;
  • Período H1;
  • Indicadores: MA 1 SMA CLOSE, MA 200 SMA CLOSE, CCI 42, StdDev 60.
  • StopLoss e TakeProfit, 400 e 830;
  • Modo de otimização e teste "1 Minute OHLC" e "Máxima Rentabilidade". Nosso EA inicialmente opera com base nos preços de abertura M1. Hoje, como experimento, usaremos o modo "Máxima Rentabilidade".
  • Intervalo de otimização de 1 ano. De 2021.10.10 a 2022.10.10. 1 ano não é um critério específico. Você pode tentar mais ou menos por conta própria;
  • Intervalo de teste forward de 1 ano. De 2022.10.10 a 2023.10.10;
  • No teste forward, foram utilizados os 50 melhores resultados da otimização simultaneamente;
  • Depósito inicial de 10000;
  • Alavancagem de 1:500.

As configurações de otimização são mostradas na captura de tela abaixo:

Configurações de otimização

Resultados da otimização nas capturas de tela abaixo:

Resultado da otimização 1


Resultado da otimização 2

Após a conclusão da otimização, formamos um arquivo em formato CSV usando o Excel. Lembro que pegamos os primeiros 50 melhores resultados. Inserimos o arquivo obtido no código do segundo EA para teste. No código, isso será mostrado assim.

string EURUSD[][8]=
  {
   {"Profit","Trades","x1","x2","x3","x4","Param"},
   {"266.45","239","2","1","9","8","5000"},
   {"266.45","239","2","1","9","13","5000"},
   {"266.45","239","2","1","9","11","5000"},
   {"266.45","239","2","1","9","10","5000"},
   {"266.45","239","2","1","9","8","5000"},
   {"266.45","239","2","1","9","12","5000"},
   {"266.45","239","2","1","9","20","5000"},
   {"266.45","239","2","1","9","14","5000"},
   {"266.45","239","2","1","9","2","5000"},
   {"266.45","239","2","1","9","3","5000"},
   {"259.69","239","0","0","12","17","5500"},
   {"259.69","239","0","0","12","8","5500"},
   {"259.69","239","0","0","12","1","5500"},
   {"259.69","239","0","0","12","9","5500"},
   {"259.69","239","0","0","12","16","5500"},
   {"259.69","239","0","0","12","18","5500"},
   {"259.69","239","0","0","12","11","5500"},
   {"259.69","239","0","0","12","7","5500"},
   {"259.69","239","0","0","12","15","5500"},
   {"259.69","239","0","0","12","8","5500"},
   {"259.69","239","0","0","12","9","5500"},
   {"259.69","239","0","0","12","17","5500"},
   {"259.69","239","0","0","12","6","5500"},
   {"259.69","239","0","0","12","15","5500"},
   {"259.69","239","0","0","12","4","5500"},
   {"259.69","239","0","0","12","7","5500"},
   {"259.69","239","0","0","12","11","5500"},
   {"259.69","239","0","0","12","14","5500"},
   {"259.69","239","0","0","12","1","5500"},
   {"259.69","239","0","0","12","5","5500"},
   {"259.69","239","0","0","12","3","5500"},
   {"259.69","239","0","0","12","0","5500"},
   {"259.69","239","0","0","12","12","5500"},
   {"259.69","239","0","0","12","16","5500"},
   {"259.69","239","0","0","12","8","5500"},
   {"259.69","239","0","0","12","10","5500"},
   {"259.69","239","0","0","12","16","5500"},
   {"259.69","239","0","0","12","18","5500"},
   {"259.69","239","0","0","12","13","5500"},
   {"259.69","239","0","0","12","9","5500"},
   {"259.69","239","0","0","12","12","5500"},
   {"259.69","239","0","0","12","11","5500"},
   {"259.69","239","0","0","12","7","5500"},
   {"259.69","239","0","0","12","15","5500"},
   {"259.69","239","0","0","12","14","5500"},
   {"259.69","239","0","0","12","3","5500"},
   {"259.69","239","0","0","12","19","5500"},
   {"259.69","239","0","0","12","0","5500"},
   {"259.69","239","0","0","12","17","5500"},
   {"259.69","239","0","0","12","2","5500"}
  };

Também apresentarei o código do segundo EA para negociação. Como vemos, no loop, percorremos todos os valores obtidos na otimização e os comparamos com os resultados atuais da execução do perceptron. Se os valores coincidirem, a posição correspondente de compra ou venda é aberta. A limitação no número de posições abertas simultaneamente é controlada pelo parâmetro MaxSeries e pela função CalculateSeries, que conta as posições por comentários.

      for(int i=1; i<=(ArraySize(EURUSD)/8)-1; i++)
        {

         comm=(EURUSD[i][0]+EURUSD[i][1]);

         x1=(int)StringToInteger(EURUSD[i][2]);
         x2=(int)StringToInteger(EURUSD[i][3]);
         x3=(int)StringToInteger(EURUSD[i][4]);
         x4=(int)StringToInteger(EURUSD[i][5]);

         Param=(int)StringToInteger(EURUSD[i][6]);

         //SELL++++++++++++++++++++++++++++++++++++++++++++++++
         if((NewOpen==true) && (CalculateSeries(Magic)<MaxSeries) && (perceptron1()<-Param) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment+" En_"+comm)==0) && (SpreadS1<=MaxSpread))
           {
            OpenSell(symbolS1.Name(), LotsXSell, TP, SL, EAComment+" En_"+comm);
           }

         //BUY++++++++++++++++++++++++++++++++++++++++++++++++
         if((NewOpen==true) && (CalculateSeries(Magic)<MaxSeries) && (perceptron1()>Param) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment+" En_"+comm)==0) && (SpreadS1<=MaxSpread))
           {
            OpenBuy(symbolS1.Name(), LotsXBuy, TP, SL, EAComment+" En_"+comm);
           }

        }
//+------------------------------------------------------------------+
//| Calculate Positions                                              |
//+------------------------------------------------------------------+
int CalculateSeries(ulong mag)
  {
   int total=0;
   string com="";

   for(int i=PositionsTotal()-1; i>=0; i--)
     {
      if(position.SelectByIndex(i))
        {
         if(position.Magic()==mag)
           {
            if(com!=position.Comment())
              {
               com=position.Comment();
               total++;
              }
           }
        }
     }
//---
   return(total);
  }

Resultado do teste backward:

Resultado do teste backward

Resultado do teste forward:

Resultado do teste forward


Resultado do teste forward 2


Considerações finais

Lista de arquivos anexados:

  1. Distance 1, Distance 2, Distance 3, - EAs com exemplos de passagem de distâncias ao perceptron;
  2. Accumulation 1, Accumulation 2 - EAs com exemplos de passagem de acumulação ao perceptron;
  3. Angle 1, Angle 2 - EAs com exemplos de passagem de ângulos de inclinação dos indicadores ao perceptron;
  4. Combo 1 - EA com exemplo de passagem de dados combinados de indicadores ao perceptron;
  5. Perceptron – opt - EA para otimização.
  6. Perceptron – trade – EA para negociação com parâmetros otimizados.

 Conforme observado nos resultados do teste forward, nossa abordagem para a passagem de indicadores funciona bem. Nos primeiros seis meses, o EA impulsiona o saldo de forma bastante confiante. No artigo visto, dei todos os tipos de exemplos de passagem de indicadores que acredito que meus leitores terão interesse em testar. Muito trabalho foi feito desta vez, mas sempre há objetivos para alcançar.

Para quaisquer perguntas, você pode entrar em contato no fórum ou por mensagens privadas. Estarei sempre feliz em ajudar.

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

Arquivos anexados |
EA.zip (23.32 KB)
Preparação de indicadores com vários símbolos/períodos Preparação de indicadores com vários símbolos/períodos
Neste artigo, examinaremos os princípios para criar indicadores com vários símbolos/períodos e recuperar dados deles dentro de EAs e indicadores. Veremos as nuances mais importantes ao usar multi-indicadores em EAs e indicadores, e sua plotagem mediante buffers de indicador personalizado.
Redes neurais de maneira fácil (Parte 60): transformador de decisões on-line (ODT) Redes neurais de maneira fácil (Parte 60): transformador de decisões on-line (ODT)
As últimas 2 partes foram dedicadas ao método transformador de decisões (DT), que modela sequências de ações no contexto de um modelo autorregressivo de recompensas desejadas. Neste artigo, vamos considerar outro algoritmo de otimização deste método.
Permutação das barras de preços no MQL5 Permutação das barras de preços no MQL5
Neste artigo, apresentamos um algoritmo de permutação das barras de preços e detalhamos como os testes de permutação podem ser usados para identificar casos em que o desempenho de uma estratégia é inventado com o objetivo de enganar potenciais compradores de Expert Advisors.
Trabalho com datas e horas no MQL5 Trabalho com datas e horas no MQL5
É muito importante que os operadores e desenvolvedores de ferramentas de negociação entendam como manusear datas e horas de forma adequada e eficiente. Neste artigo, mostrarei como podemos trabalhar com datas e horas ao criar ferramentas de negociação eficientes.