Discussão do artigo "LifeHack para traders: preparemos "fast-food" de indicadores" - página 2

 
Renat Fatkhullin:

...

Além disso, a extração ineficiente de 1 valor do indicador.

...

Tudo isso está na teoria. Mas, na prática, 99% dos indicadores são calculados em buffers de anel FIFO: excluir o último elemento, adicionar um novo, recalcular o indicador. Ou seja, novamente na prática, a adição ao buffer de cálculo é feita por um elemento e 99% de todos os cálculos no indicador é a adição de um elemento. Portanto, a ideia de CopyBuffer, CopyRates, CopyXXX é bonita, mas não corresponde à área de estudo.

 
Renat Fatkhullin:

...

Um horror difícil com vazamentos de alça (por que fechar a alça do indicador?) e uma sobrecarga incrível (tentar recriar o indicador, caindo dentro do gerenciador de indicadores). E muitas pessoas o copiarão sem olhar e sem entender.

...

Não está claro o que você quis dizer. Pelo que entendi, as alças não são fechadas em lugar algum( não háchamadas de IndicatorRelease ). Há uma chamada constante para funções padrão de criação de hendle, como iMACD:

//+------------------------------------------------------------------+
//| Função iMACD em notação MQL4|
//| Os números do buffer são os seguintes: |
//| MQL4 0 - MODE_MAIN, 1 - MODE_SIGNAL|
//| MQL5 0 - MAIN_LINE, 1 - SIGNAL_LINE|
//+------------------------------------------------------------------+
double   iMACD(
               string                     symbol,              // nome do símbolo 
               ENUM_TIMEFRAMES            timeframe,           // período de tempo 
               int                        fast_ema_period,     // período para o cálculo da média rápida 
               int                        slow_ema_period,     // período para cálculo da média lenta 
               int                        signal_period,       // período para o cálculo da média das diferenças 
               ENUM_APPLIED_PRICE         applied_price,       // tipo de preço ou alça 
               int                        buffer,              // buffer 
               int                        shift                // deslocamento
               )
  {
   
   double result=NaN;
//---
   int handle=iMACD(symbol,timeframe,fast_ema_period,slow_ema_period,signal_period,applied_price);
   if(handle==INVALID_HANDLE)
     {
      Print(__FUNCTION__,": INVALID_HANDLE error=",GetLastError());
      return(result);
     }
   double val[1];
   int copied=CopyBuffer(handle,buffer,shift,1,val);
   if(copied>0)
      result=val[0];
   else
      Print(__FUNCTION__,": CopyBuffer error=",GetLastError());
   return(result);
  }

Obviamente, todo o jogo aqui se baseia no fato de que o iMACD e funções semelhantes armazenam em cache o identificador retornado anteriormente dentro deles mesmos, portanto, não deve haver recriação do indicador.

 
Vasiliy Sokolov:

Tudo isso está na teoria. Mas, na prática, 99% dos indicadores são cálculos em buffers de anel FIFO: excluir o último elemento, adicionar um novo, recalcular o indicador. Ou seja, novamente na prática, a adição ao buffer de cálculo é feita por um elemento e 99% de todos os cálculos no indicador são a adição de um elemento. Portanto, a ideia de CopyBuffer, CopyRates, CopyXXX é bonita, mas não corresponde à área de estudo.

Isso se você escrever os manipuladores de last look mais simples e primitivos. Mas assim que você der um passo para o lado e começar a verificar dois ou mais pontos, verá imediatamente a diferença e o efeito.

Em geral, é claro, é estranho ouvir que as funções CopyXXX supostamente não estão na área de estudo.

Você deve se esforçar muito para dizer essas coisas sobre as funções básicas de acesso ao ambiente de mercado.


E também - não é à toa que os indicadores recebem 100% de todo o histórico para cálculos:

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
Isso é para provar que não há "99% no buffer do anel". O acesso em massa ao histórico, e não aos últimos valores individuais, é muito necessário.
 
Vasiliy Sokolov:

Não está claro o que você quer dizer com o que falou. Pelo que entendi, os hendles não são fechados em lugar algum( não háchamadas para IndicatorRelease ). Há uma chamada constante para as funções padrão de criação de hendles, como o iMACD:

Obviamente, todo o jogo se baseia no fato de que o iMACD e funções semelhantes armazenam em cache o identificador retornado anteriormente dentro deles mesmos, portanto, não deve haver recriação do indicador.

Todo o jogo é construído com base no hack e na total desconsideração pelo controle das alças.

Outro operador pega esse código, não presta atenção à alocação de identificadores, começa a fazer chamadas com parâmetros diferentes, multiplica indicadores, perde todos os identificadores e depois se surpreende com os freios e o consumo de memória.

Sabe-se quem é o culpado.

 
fxsaber:

O artigo é um pequeno trecho de outro.

Não vi nenhuma analogia.

fxsaber:

Nada foi feito para que ele funcione de forma eficiente. Não há armazenamento em cache de indicadores e séries temporais.

Realmente há espaço para otimização aqui. Introduzir o armazenamento em cache seria uma ótima ideia.

fxsaber:

High[i], Low[i], etc. estão faltando.

Eles deveriam estar presentes? Acho que o título do artigo (ou melhor, sua descrição) diz claramente apenas sobre indicadores?

fxsaber:

Não há iCustom.

Infelizmente, o MQL não oferece suporte a funções com um número arbitrário de parâmetros, portanto, não é possível implementar o iCustom "exatamente como no MT4"

fxsaber:

Esperava-se ver algo completamente diferente. Além disso, qual é o objetivo do fast food nos EAs, se ele nem sequer tem cheiro nos códigos-fonte?

Não acho que seja possível escrever um mecanismo completo que emule totalmente o estilo do MT4 em um único artigo. O tópico foi claramente definido: trabalhar com indicadores no estilo MQL4 (é uma pena que o título do artigo não reflita o tópico, o que é confuso).

 
Renat Fatkhullin:

...

Isso serve para provar que não há "99% no buffer de anel". São os acessos em massa ao histórico, e não os últimos valores individuais, que são muito necessários.

Eles existem e são usados com um pouco mais de frequência do que constantemente. Simplesmente não há meios especiais e os desenvolvedores precisam criar loops aninhados. Abra qualquer indicador com for's duplos aninhados: parabéns, o buffer de anel foi encontrado. Aqui está um exemplo de seu cálculo supereficiente do indicador MFI:

//+------------------------------------------------------------------+
//| Calcular MFI por volume a partir do argumento
//+------------------------------------------------------------------+
void CalculateMFI(const int nPosition,
                  const int nRatesCount,
                  const double &HiBuffer[],
                  const double &LoBuffer[],
                  const double &ClBuffer[],
                  const long &VolBuffer[],
                  const datetime &time[])
  {
   for(int i=nPosition;i<nRatesCount && !IsStopped();i++)
     {
      double dPositiveMF=0.0;
      double dNegativeMF=0.0;
      double dCurrentTP=TypicalPrice(HiBuffer[i],LoBuffer[i],ClBuffer[i]);
      if(time[i] == D'2016.05.23')
         int dbg = 4;
      for(int j=1;j<=ExtMFIPeriod;j++)
        {
         int    index=i-j;
         double dPreviousTP=TypicalPrice(HiBuffer[index],LoBuffer[index],ClBuffer[index]);
         if(dCurrentTP>dPreviousTP)
            dPositiveMF+=VolBuffer[index+1]*dCurrentTP;
         if(dCurrentTP<dPreviousTP)
            dNegativeMF+=VolBuffer[index+1]*dCurrentTP;
         dCurrentTP = dPreviousTP;
        }
      if(dNegativeMF!=0.0) ExtMFIBuffer[i]=100.0-100.0/(1+dPositiveMF/dNegativeMF);
      else                 ExtMFIBuffer[i]=100.0;
     }
  }

Bem, é óbvio que a velocidade de cálculo desse indicador depende do período de cálculo da média, e não deveria ser assim. E há muitos exemplos desse tipo, alguns dos quais escritos pelo próprio MQ, e você diz que não há buffers em anel.

 
Vasiliy Sokolov:

Existem e são usados com um pouco mais de frequência do que o tempo todo. O problema é que não há ferramentas especiais e os desenvolvedores precisam criar loops aninhados. Abra qualquer indicador com for's duplamente aninhados: parabéns, o buffer de anel foi encontrado. Aqui está um exemplo de seu cálculo supereficiente do indicador MFI:

Bem, é óbvio que a velocidade de cálculo desse indicador depende do período de cálculo da média, e não deveria ser assim. E há muitos desses exemplos, alguns dos quais escritos pelo próprio MQ, e você diz que não há buffers em anel.

Eles estão ausentes em 99% dos casos. E em 90% dos casos não há buffers em anel e em 50% dos casos não há buffers em anel. Mas há um volume de 100% de dados iniciais (para toda a profundidade do histórico) nos parâmetros OnCalculate.

E não se trata nem mesmo de calcular indicadores, mas de usar tanto os resultados dos indicadores quanto o acesso aos dados de origem. O acesso é necessário em uma escala maciça, não em uma única.

Você está tentando apresentar a situação de tal forma que "todo o mercado de análise é representado pelo último valor do indicador" e "CopyXXXX não corresponde à área temática".

Você está se esforçando muito para fazer um esboço.

 
Renat Fatkhullin:

...

E não se trata nem mesmo de calcular indicadores, mas de usar tanto os resultados dos indicadores quanto o acesso aos dados originais. O acesso é necessário em uma escala maciça, não em uma única.

...

Por favor, preste atenção à solicitação #1923700. Há alguns problemas com o acesso frequente a grandes quantidades de dados.

Já faz muito tempo que não há comentários e perguntas para fornecer informações adicionais que ajudem a descobrir o motivo desse resultado.

 
Renat Fatkhullin:

Outro operador pega esse código, não presta atenção à alocação de manipuladores, começa a fazer chamadas com parâmetros diferentes, multiplica indicadores, perde todos os manipuladores e fica surpreso com os freios e o consumo de memória.

Da mesma forma, esse outro operador pode começar a fazer chamadas para iHandles padrão com parâmetros diferentes. Se os parâmetros forem diferentes, serão criados indicadores diferentes, independentemente de você trabalhar com o manipulador diretamente ou usar o MQL4-Style.

 
Renat Fatkhullin:

Você está se esforçando muito para fazer um esboço.

E isso é uma pena.

E não se trata nem mesmo de calcular indicadores, mas de usá-los como resultados de indicadores.

Sim.

Renat Fatkhullin:

...

De qualquer forma, não vou discutir, pois é inútil. Seria interessante coletar estatísticas sobre o uso das funções Copy***. Quantos itens os usuários copiam, em média, mostraria muito.