CopyBuffer - página 2

 
Gustavo Barbeiro Alonso:

e se carregar no ontime() sera que daria?

Fica lento também...


Ao anexar o EA ao gráfico, não é perceptível problema de desempenho. O problema é ao executar no Testador: um teste que levaria 1 hora para concluir carregando em OnInit(), leva 20 horas ou mais carregando / encerrando em OnTick() / OnTimer().

 

Como o Rogerio disse acima, a contrução do handler se faz na inicialização, ou seja;


meu_handler=iMa(.....);



ja a copia dos valores deve ser feito sob demanda, ou seja, quando há necessidade. Não há como fugir disso, o que eu sugiro é que crie uma função que verifica as condiçãos, e que é chamada quando necessário, e não deixe um monte de código amontoado dentro da OnTick.
Alguma coisa assim....a copia dos valores só ocorre quando GetSignal é chamado, consequentemente essa função só é chamada quando uma nova barra chega, porem, é uma ESPECIFICAÇÃO DA ESTRATEGIA, ser a cada nova barra.



 
Jonathan Pereira:

Como o Rogerio disse acima, a contrução do handler se faz na inicialização, ou seja;


meu_handler=iMa(.....);



ja a copia dos valores deve ser feito sob demanda, ou seja, quando há necessidade. Não há como fugir disso, o que eu sugiro é que crie uma função que verifica as condiçãos, e que é chamada quando necessário, e não deixe um monte de código amontoado dentro da OnTick.
Alguma coisa assim....a copia dos valores só ocorre quando GetSignal é chamado, consequentemente essa função só é chamada quando uma nova barra chega, porem, é uma ESPECIFICAÇÃO DA ESTRATEGIA, ser a cada nova barra.



Boa tarde Jonathan! Muito obrigado pelas sugestões! Muito importantes.


O que eu destaquei em azul é como eu já faço atualmente; em amarelo, não tem como implementar porque preciso dos valores dos indicadores pros meus sinais.


Eu vou pesquisar mais e ver se encontro uma forma de contornar esse problema através de alguns "arranjos técnicos", né? 😃 e qualquer novidade compartilho aqui.

 
Vinicius de Oliveira:

O que eu destaquei em azul é como eu já faço atualmente; em amarelo, não tem como implementar porque preciso dos valores dos indicadores pros meus sinais.

A parte amarela é justamente o sinal, eu organizo em uma função única, fica mais simples dar manutenção depois ;)

 
Gustavo Barbeiro Alonso:

. . .

Boa tarde Gustavo!


Resolvi o meu problema transcrevendo o código dos indicadores pro EA mesmo (com pequenas adaptações), como eu tinha cogitado. Praticamente o EA não perdeu velocidade de execução. Estou anexando abaixo uma versão das funções que retorna os valores dos indicadores para o índice de barra (shift) passado como parâmetro. Outra versão (que é a que eu uso) seria declarar as funções do tipo void, declarar as variáveis ExtSARBuffer[] e ExtMABuffer[] como globais, e o EA lê os valores que for utilizar dessas variáveis. A vantagem da segunda versão em relação à primeira é, claro, menos execuções das funções.

#define MINIBARS 1000


//+--------------------------------------------------------------------------------------------------------------------+
//| Parabolic Stop and Reverse function                                                                                |
//+--------------------------------------------------------------------------------------------------------------------+
double ParabolicSAR(double SARStep, int SARShift)
  {
   //--- Local variables
   double SARMaximum = 0.20, ExtSARBuffer[MINIBARS], ExtEPBuffer[MINIBARS], ExtAFBuffer[MINIBARS], high[], low[];
   int    pos = 1, ExtLastRevPos = 0, i;
   bool   ExtDirectionLong = false;

   //--- Parameter validation
   SARStep = MathMin(MathMax(SARStep, 0.001), SARMaximum);

   //--- Initializes / Defines variables
   ArrayInitialize(ExtSARBuffer, 0.0);
   ArrayInitialize(ExtEPBuffer,  0.0);
   ArrayInitialize(ExtAFBuffer,  0.0);
   CopyHigh(_Symbol, PERIOD_CURRENT, 0, MINIBARS, high);
   CopyLow (_Symbol, PERIOD_CURRENT, 0, MINIBARS, low);
   ArraySetAsSeries(high, false);
   ArraySetAsSeries(low,  false);
   ExtAFBuffer[0]  = SARStep;
   ExtAFBuffer[1]  = SARStep;
   ExtSARBuffer[0] = high[0];
   ExtSARBuffer[1] = GetHigh(pos,ExtLastRevPos,high);
   ExtEPBuffer[0]  = low[pos];
   ExtEPBuffer[1]  = low[pos];

   //--- Main cycle
   for(i=pos; i<MINIBARS-1 && !IsStopped(); i++)
     {
      //--- check for reverse
      if(ExtDirectionLong)
        {
         if(ExtSARBuffer[i]>low[i])
           {
            //--- switch to SHORT
            ExtDirectionLong=false;
            ExtSARBuffer[i]=GetHigh(i,ExtLastRevPos,high);
            ExtEPBuffer[i]=low[i];
            ExtLastRevPos=i;
            ExtAFBuffer[i]=SARStep;
           }
        }
      else
        {
         if(ExtSARBuffer[i]<high[i])
           {
            //--- switch to LONG
            ExtDirectionLong=true;
            ExtSARBuffer[i]=GetLow(i,ExtLastRevPos,low);
            ExtEPBuffer[i]=high[i];
            ExtLastRevPos=i;
            ExtAFBuffer[i]=SARStep;
           }
        }
      //--- continue calculations
      if(ExtDirectionLong)
        {
         //--- check for new High
         if(high[i]>ExtEPBuffer[i-1] && i!=ExtLastRevPos)
           {
            ExtEPBuffer[i]=high[i];
            ExtAFBuffer[i]=ExtAFBuffer[i-1]+SARStep;
            if(ExtAFBuffer[i]>SARMaximum)
               ExtAFBuffer[i]=SARMaximum;
           }
         else
           {
            //--- when we haven't reversed
            if(i!=ExtLastRevPos)
              {
               ExtAFBuffer[i]=ExtAFBuffer[i-1];
               ExtEPBuffer[i]=ExtEPBuffer[i-1];
              }
           }
         //--- calculate SAR for tomorrow
         ExtSARBuffer[i+1]=ExtSARBuffer[i]+ExtAFBuffer[i]*(ExtEPBuffer[i]-ExtSARBuffer[i]);
         //--- check for SAR
         if(ExtSARBuffer[i+1]>low[i] || ExtSARBuffer[i+1]>low[i-1])
            ExtSARBuffer[i+1]=MathMin(low[i],low[i-1]);
        }
      else
        {
         //--- check for new Low
         if(low[i]<ExtEPBuffer[i-1] && i!=ExtLastRevPos)
           {
            ExtEPBuffer[i]=low[i];
            ExtAFBuffer[i]=ExtAFBuffer[i-1]+SARStep;
            if(ExtAFBuffer[i]>SARMaximum)
               ExtAFBuffer[i]=SARMaximum;
           }
         else
           {
            //--- when we haven't reversed
            if(i!=ExtLastRevPos)
              {
               ExtAFBuffer[i]=ExtAFBuffer[i-1];
               ExtEPBuffer[i]=ExtEPBuffer[i-1];
              }
           }
         //--- calculate SAR for tomorrow
         ExtSARBuffer[i+1]=ExtSARBuffer[i]+ExtAFBuffer[i]*(ExtEPBuffer[i]-ExtSARBuffer[i]);
         //--- check for SAR
         if(ExtSARBuffer[i+1]<high[i] || ExtSARBuffer[i+1]<high[i-1])
            ExtSARBuffer[i+1]=MathMax(high[i],high[i-1]);
        }
     }

   //--- Succeeded result
   return(ExtSARBuffer[MINIBARS-1-SARShift]);
  }

//+------------------------------------------------------------------+
//| PSAR - Find highest price from start to current position         |
//+------------------------------------------------------------------+
double GetHigh(int curr_pos,int start,const double& high[])
  {
   double result=high[start];
//---
   for(int i=start+1; i<=curr_pos; i++)
      if(result<high[i])
         result=high[i];
//---
   return(result);
  }
//+------------------------------------------------------------------+
//| PSAR - Find lowest price from start to current position          |
//+------------------------------------------------------------------+
double GetLow(int curr_pos,int start,const double& low[])
  {
   double result=low[start];
//---
   for(int i=start+1; i<=curr_pos; i++)
      if(result>low[i])
         result=low[i];
//---
   return(result);
  }
//+--------------------------------------------------------------------------------------------------------------------+
//| Moving Average function                                                                                            |
//+--------------------------------------------------------------------------------------------------------------------+
double MovingAverage(int MAPeriod, ENUM_MA_METHOD MAMethod, int MAShift)
  {
   //--- Local variables
   double ExtMABuffer[MINIBARS], price[];
   int    i,start;

   //--- Parameter validation
   MAPeriod = MathMin(MathMax(MAPeriod, 2), MINIBARS / 2);

   //--- Initializes / Defines variables
   ArrayInitialize(ExtMABuffer, 0);
   CopyClose(_Symbol, PERIOD_CURRENT, 0, MINIBARS, price);
   ArraySetAsSeries(price, false);

   //--- calculation
   if(MAMethod == MODE_EMA)
     {
      double SmoothFactor=2.0/(1.0+MAPeriod);

      //--- initializes variables
      start=MAPeriod;
      ExtMABuffer[0]=price[0];
      for(i=1; i<start; i++)
         ExtMABuffer[i]=price[i]*SmoothFactor+ExtMABuffer[i-1]*(1.0-SmoothFactor);

      //--- main loop
      for(i=start; i<MINIBARS && !IsStopped(); i++)
         ExtMABuffer[i]=price[i]*SmoothFactor+ExtMABuffer[i-1]*(1.0-SmoothFactor);
     }
   else if(MAMethod == MODE_LWMA)
     {
      int    l,weight=0;
      double sum=0.0,lsum=0.0;

      //--- initializes variables
      start=MAPeriod;
      //--- set empty value for first start bars
      for(i=0; i<start; i++)
         ExtMABuffer[i]=0.0;
   
      for(i=start-MAPeriod,l=1; i<start; i++,l++)
        {
         sum   +=price[i]*l;
         lsum  +=price[i];
         weight+=l;
        }
      ExtMABuffer[start-1]=sum/weight;

      //--- main loop
      for(i=start; i<MINIBARS && !IsStopped(); i++)
        {
         sum             =sum-lsum+price[i]*MAPeriod;
         lsum            =lsum-price[i-MAPeriod]+price[i];
         ExtMABuffer[i]=sum/weight;
        }
     }
   else if(MAMethod == MODE_SMMA)
     {
      //--- initializes variables
      start=MAPeriod;
      //--- set empty value for first start bars
      for(i=0; i<start-1; i++)
         ExtMABuffer[i]=0.0;
      //--- calculate first visible value
      double first_value=0;
      for(i=0; i<start; i++)
         first_value+=price[i];
      first_value/=MAPeriod;
      ExtMABuffer[start-1]=first_value;

      //--- main loop
      for(i=start; i<MINIBARS && !IsStopped(); i++)
         ExtMABuffer[i]=(ExtMABuffer[i-1]*(MAPeriod-1)+price[i])/MAPeriod;
     }
   else  //--- MODE_SMA
     {
      //--- initializes variables
      start=MAPeriod;
      //--- set empty value for first start bars
      for(i=0; i<start-1; i++)
         ExtMABuffer[i]=0.0;
      //--- calculate first visible value
      double first_value=0;
      for(i=0; i<start; i++)
         first_value+=price[i];
      first_value/=MAPeriod;
      ExtMABuffer[start-1]=first_value;

      //--- main loop
      for(i=start; i<MINIBARS && !IsStopped(); i++)
         ExtMABuffer[i]=ExtMABuffer[i-1]+(price[i]-price[i-MAPeriod])/MAPeriod;
     }

   //--- Succeeded result
   return(ExtMABuffer[MINIBARS-1-MAShift]);
  }
//+------------------------------------------------------------------+
 
Vinicius de Oliveira:

Boa tarde Gustavo!


Resolvi o meu problema transcrevendo o código dos indicadores pro EA mesmo (com pequenas adaptações), como eu tinha cogitado. Praticamente o EA não perdeu velocidade de execução. Estou anexando abaixo uma versão das funções que retorna os valores dos indicadores para o índice de barra (shift) passado como parâmetro. Outra versão (que é a que eu uso) seria declarar as funções do tipo void, declarar as variáveis ExtSARBuffer[] e ExtMABuffer[] como globais, e o EA lê os valores que for utilizar dessas variáveis. A vantagem da segunda versão em relação à primeira é, claro, menos execuções das funções.


Que bom que está funcionando é uma solução que resolveu seu problema!   Mas veja só, na solução o SAR e a MA estão fazendo os cálculos sobre 1000 barras, já nos indicadores builtin do  MT5 os cálculos são feitos sobre todas as  barras do gráfico. 

Uma questão que não entendi sobre seu problema é quantas vezes você precisa construir o HANDLE dos indicadores na sua estratégia e se eles são reutilizados ou podem ser liberados?

 
Rogerio Giannetti Torres:


Que bom que está funcionando é uma solução que resolveu seu problema!   Mas veja só, na solução o SAR e a MA estão fazendo os cálculos sobre 1000 barras, já nos indicadores builtin do  MT5 os cálculos são feitos sobre todas as  barras do gráfico. 

Uma questão que não entendi sobre seu problema é quantas vezes você precisa construir o HANDLE dos indicadores na sua estratégia e se eles são reutilizados ou podem ser liberados?

Outra questão pertinente também é que indicadores rodam em threads separadas, logo a carga computacional em cima do EA é menor!

 
Rogerio Giannetti Torres:


Que bom que está funcionando é uma solução que resolveu seu problema!   Mas veja só, na solução o SAR e a MA estão fazendo os cálculos sobre 1000 barras, já nos indicadores builtin do  MT5 os cálculos são feitos sobre todas as  barras do gráfico. 

Uma questão que não entendi sobre seu problema é quantas vezes você precisa construir o HANDLE dos indicadores na sua estratégia e se eles são reutilizados ou podem ser liberados?

Olá Rogerio, boa noite!

 

Eu preciso atualizar os parâmetros diariamente. Então, no OnTick(), eu tentei construir e desconstruir [IndicatorRelease()] os handles somente a cada nova barra D1 (eu negocio em H1), mas mesmo assim diminuiu enormemente a velocidade de execução do EA em backtests. Ficava inviável pra mim. Acho que, como você bem disse, são muitas dezenas de milhares de barras pra calcular, e o processo fica lento mesmo.

 
Vinicius de Oliveira:

Olá Rogerio, boa noite!

 

Eu preciso atualizar os parâmetros diariamente. Então, no OnTick(), eu tentei construir e desconstruir [IndicatorRelease()] os handles somente a cada nova barra D1 (eu negocio em H1), mas mesmo assim diminuiu enormemente a velocidade de execução do EA em backtests. Ficava inviável pra mim. Acho que, como você bem disse, são muitas dezenas de milhares de barras pra calcular, e o processo fica lento mesmo.

---     Então, no OnTick(), eu tentei construir e desconstruir [IndicatorRelease()] os handles somente a cada nova barra D1 (eu negocio em H1)

Não entendi ? Qual o motivo de construir um novo Handle para os mesmos parâmetros de  SYMBOL, TIME FRAME,  PERÍODO , MÉTODO , SÉRIES PREÇOS , se nenhum parâmetro do handle alterou, pra que liberar e construir novamente a mesma coisa.

 
Rogerio Giannetti Torres:

---     Então, no OnTick(), eu tentei construir e desconstruir [IndicatorRelease()] os handles somente a cada nova barra D1 (eu negocio em H1)

Não entendi ? Qual o motivo de construir um novo Handle para os mesmos parâmetros de  SYMBOL, TIME FRAME,  PERÍODO E SÉRIES PREÇOS o que muda de um dia para outro?

Esclarecer antes que não é algo que já está vigente não. Eu estava buscando essa solução pra poder testar algumas ideias.


Eu negocio Forex e quero que o EA busque negócios durante 24h. Acredito que algumas configurações de indicadores podem funcionar bem durante as sessões de Sydney e Tóquio; quando abre Londres podem ser melhores outras configurações; e quando abre NY talvez também sejam mais interessantes outras configurações. A questão da verificação e, se necessária, atualização diária pode ser em relação, por exemplo, à volatilidade (ADR) ...

Razão: