Discussão do artigo "Receitas MQL5 - Criamos um buffer circular para calcular rapidamente indicadores numa janela deslizante" - página 4

 
Otto Pauser:

Um ótimo artigo, o homem sabe programar!

Se ao menos a tradução alemã não fosse tão horrível!!!!!

Olá,

Muito obrigado pela dica. A tradução foi corrigida.

Com os melhores cumprimentos

 

Bom dia, Vasiliy Sokolov!

Seus indicadores criados com a ajuda do buffer de anel mostram algo pouco claro, acho que o método ChangeValue não funciona ou talvez eu tenha entendido algo errado?

 
Savio Araujo:

Eu já vi isso. Como verifiquei os exemplos que você forneceu. Eles mostram o mesmo problema que eu tive ao lidar com a atualização dos valores enquanto o mercado está funcionando. Verifique o Stochastic que você forneceu. Adicionar um novo valor não é um problema, mas quando tentamos usar Stoch.ChangeLast() ou OnChangeValue() na classe CRiMaxMin, isso não funciona. Ele não altera o valor adequadamente. Se você puder verificar ou enviar um exemplo de um código funcional, seria muito bom.

Muito obrigado.

Excelente trabalho aqui, muito obrigado ao autor. Talvez o erro que você está vendo, Savio, esteja aqui:

int RingBuffer::iToRealInd(int iIndex)

{

   if(iIndex >= iNumElements() || iIndex < 0)

      return iBufferSize-1; //previous bug was caused by no -1 here

...

Eu adicionei o -1 na última linha citada; ele não estava lá antes e causaria o retorno de um índice inadequado. Observe que mudei os nomes das variáveis/métodos de acordo com meu estilo de programação, mas a ideia é a mesma.

 
Por que o CRiStoch não tem um método chamado ChangeValue?
 
brisully:

Excelente trabalho aqui, muito obrigado ao autor. Talvez o bug que você está vendo, Savio, esteja aqui:

int RingBuffer::iToRealInd(int iIndex)

{

   if(iIndex >= iNumElements() || iIndex < 0)

      return iBufferSize-1; //previous bug was caused by no -1 here

...

Eu adicionei o -1 na última linha citada; ele não estava lá antes e causaria o retorno de um índice inadequado. Observe que mudei os nomes das variáveis/métodos de acordo com meu estilo de programação, mas a ideia é a mesma

Tentei sua correção, mas a atualização ainda não está correta. Parece que está faltando alguma coisa e não consigo encontrar o problema ao tentar executar o buffer de anel na formação de uma nova barra. Quando o mercado está funcionando, as linhas Alto/Baixo ficam completamente misturadas. O código funciona muito bem e muito rápido ao processar dados antigos, mas com novos dados chegando durante a formação de uma nova barra, ele simplesmente não funciona para mim.

 
Vasily, obrigado pelo código! Ele ajuda muito.
Se eu puder fazer alguns comentários:

1. Na classe void CRiMaxMin::OnChangeValue(int index, double del_value, double new_value), no método " OnChangeValue" na linha
.
if(m_min_ind >= 0 && new_value >= GetValue(m_min_ind))
      m_min_ind = index;

Figura: erro de digitação?


typo - sinal "less than or equal to".

2.Ao pesquisar os elementos Min e Max de uma matriz, se usados exatamente como um buffer em anel (quando novos elementos começam a ser gravados no início da matriz), min e mah são definidos incorretamente. O mínimo é maior que o máximo. Em uma matriz. Tudo funciona usando os métodos padrão (ArrayMinimum e ArrayMaximum).
Picture: O mínimo é maior que o máximo

Em algum lugar, a indexação está se desviando. Não consigo consertar isso sozinho. Se alguém puder corrigi-lo, seria ótimo. Anexei um orientador de teste.

#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include  <RingBuffer\RiMaxMin.mqh>

input group "A verificação do buffer de anel é verdadeira."
input bool ringBuffer=true;


input group "Tamanho do buffer".
input int pTest=10;

double minValue,maxValue;
int minIndex,maxIndex,lastIndex,indArr;

double arr[];

CRiMaxMin minMaxTest;

int OnInit()
  { 
   if(ringBuffer)minMaxTest.SetMaxTotal(pTest);
   else  
      {
      indArr=-1;
      lastIndex=pTest-1;
      ArraySetAsSeries(arr,true);
      ArrayResize(arr,pTest);
      }
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   
   
  }

void OnTick()
  {
   if(ringBuffer)
      {
      minMaxTest.AddValue(rand());
      minIndex=minMaxTest.MinIndex();
      minValue=minMaxTest.GetValue(minIndex);
      //minValue=minMaxTest.MinValue();
      maxIndex=minMaxTest.MaxIndex();
      maxValue=minMaxTest.GetValue(maxIndex);
      //maxValue=minMaxTest.MaxValue();
      }
   else
      {
      //arr[0]=rand();
      //ArrayCopy(arr,arr,1,0,lastIndex);
      indArr++;
      if(indArr>lastIndex)indArr=0;
      arr[indArr]=rand();
      minIndex=ArrayMinimum(arr,0,pTest);
      minValue=arr[minIndex];
      //minValue=arr[ArrayMinimum(arr,0,pTest)];
      maxIndex=ArrayMaximum(arr,0,pTest);
      maxValue=arr[maxIndex]; 
      //maxValue=arr[ArrayMaximum(arr,0,pTest)];
      }  
   Alert("minValue ",DoubleToString(minValue)," --  maxValue ",DoubleToString(maxValue));
   if(minValue>maxValue)
      {
      Alert("Min > Max !!!");
      Print("Min > Max !!!");
      ExpertRemove();
      }
  }
Arquivos anexados:
 
Peço desculpas. O mínimo e o máximo estão corretos. Eu mesmo estava pensando demais.
 
Isso é exatamente o que eu preciso. Obrigado pelo código e pelo artigo tão detalhado. A ideia de otimizar a busca por extremos é ótima!
 

Você cometeu um erro em ToRealInd(int index).

Deveria ser:
if(index >= GetTotal() || index < 0 )
return m_max_total-1;