[Resolvido] Erro na lógica para plotar uma HLine

 

Boa noite.

Estou com dificuldades para entender onde pode estar o erro na lógica para plotar uma linha atráves de uma condição de um histograma.

Acontece o seguinte, quando atinge o valor e retorna abaixo desse valor especificado, ele move a linha, mas não devolve para a posição anterior, já que o valor não terminou dentro do pedido pela condição.

E outro erro, que acho ser só no testador de estatégia, ele plota a linha um candle a frente do que deveria, mas não percebi isso no gráfico normal.

Vou deixar o código e um print que sinalizei como acontece.


Edit: Uma coisa que esqueci de comentar, se removo o indicador e adiciono novamente, ele calcula certo as linhas.

Qual seria o comando para forçar recalcular?


#property indicator_separate_window
//+------------------------------------------------------------------+
//| PROPRIEDADES DO INDICADOR (DIRETIVAS)                            |
//+------------------------------------------------------------------+
#property indicator_buffers 3
#property indicator_plots 1 
//---
#property indicator_label1 "HistogramaBase" 
#property indicator_type1 DRAW_COLOR_HISTOGRAM 
#property indicator_style1 STYLE_SOLID 
#property indicator_color1 clrDodgerBlue,clrRed,clrWhite //Cores do histograma
#property indicator_width1 2 

//###############
double wBuffer[]; 
double wColor[]; 
double cl[];

sinput string largura = "Largura das linhas e estilo";
input int widthLineUp = 1;
input int widthLineDown = 1;

string name;

int OnInit()
  {
//--- Mapear os buffers do indicador
   SetIndexBuffer(0,wBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,wColor,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(2,cl,INDICATOR_DATA);
   
   IndicatorSetString( INDICATOR_SHORTNAME, "Wave Lines" );

   ChartSetInteger(0, CHART_SHOW_OBJECT_DESCR, true);
   
   name = "HighLineM1";
   ObjectCreate(0,name,OBJ_HLINE,0,0,0);  
   ObjectSetInteger(0,name,OBJPROP_COLOR,clrWhite);
   ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DASH);
   ObjectSetInteger(0,name,OBJPROP_WIDTH,widthLineUp);
   ObjectSetString(0,name,OBJPROP_TEXT,"  Line UP");
        
   //Low
   name = "LowLineM1";
   ObjectCreate(0,name,OBJ_HLINE,0,0,0);           
   ObjectSetInteger(0,name,OBJPROP_COLOR,clrWhite);
   ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DASH);
   ObjectSetString(0,name,OBJPROP_TEXT,"  Line DN");
   ObjectSetInteger(0,name,OBJPROP_WIDTH,widthLineDown);
   
   return(INIT_SUCCEEDED);
  }
  
  void OnDeinit(const int reason){
      ObjectDelete(0, "LowLineM1");
      ObjectDelete(0, "HighLineM1");
      ChartRedraw();
  }

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[])
  {

int i;
if(prev_calculated == 0) i = 2;
else i = prev_calculated-1;

while(i < rates_total){
   cl[i] = close[i];
   double vol = (double)volume[i];
   //***** Subindo 
   if (cl[i] >= cl[i-1]) { 
      if (cl[i-1] >= cl[i-2]) {
         wBuffer[i] = wBuffer[i-1] + vol;
         wColor[i] = 0;
      } 
      else{
         wBuffer[i] = vol;
         wColor[i] = 0;
      }
   } 
   // ***** Descendo   
   else{                          
      if (cl[i-1] < cl[i-2]) {
         wBuffer[i] = wBuffer[i-1] - vol;
         wColor[i] = 1;
      }
      else{
         wBuffer[i] = -vol;
         wColor[i] = 1;
      }
   }
        // Condição para plotar a linha horizontal
        if(Period() == PERIOD_M1){
            if(wBuffer[i] >= 91500){wColor[i] = 2; //Se o histograma atingir esse valor, pinta de branco e move a linha.
               ObjectMove(0,"HighLineM1",0,TimeCurrent(),high[i]);
            }
            if(wBuffer[i] <= -91500){wColor[i] = 2; 
               ObjectMove(0,"LowLineM1",0,TimeCurrent(),low[i]);
            }
        }
        // #####################################
     
   i++;
  }
   return(rates_total);
  }
//+------------------------------------------------------------------+
Arquivos anexados:
 
teste colocar sempre q vc move a linha ChartRedraw()
 
sandrolho:
teste colocar sempre q vc move a linha ChartRedraw()

Bom dia.

Não funciona também, move do mesmo jeito.

 
prsc:

Boa noite.

Estou com dificuldades para entender onde pode estar o erro na lógica para plotar uma linha atráves de uma condição de um histograma.

Acontece o seguinte, quando atinge o valor e retorna abaixo desse valor especificado, ele move a linha, mas não devolve para a posição anterior, já que o valor não terminou dentro do pedido pela condição.

E outro erro, que acho ser só no testador de estatégia, ele plota a linha um candle a frente do que deveria, mas não percebi isso no gráfico normal.

Vou deixar o código e um print que sinalizei como acontece.


Edit: Uma coisa que esqueci de comentar, se removo o indicador e adiciono novamente, ele calcula certo as linhas.

Qual seria o comando para forçar recalcular?


Me parece um indicador de "Tempo Real", já que apenas 2 linhas são usadas.

  1. Sugiro retirar a movimentação das linhas de dentro do WHILE. Apenas guarde a última referência válida para a pintura.
  2. Saindo do WHILE você terá a variável final que vc usará para mover as linhas.
  3. Use logo após ChartRedraw().

 
Flavio Jarabeck:

Me parece um indicador de "Tempo Real", já que apenas 2 linhas são usadas.

  1. Sugiro retirar a movimentação das linhas de dentro do WHILE. Apenas guarde a última referência válida para a pintura.
  2. Saindo do WHILE você terá a variável final que vc usará para mover as linhas.
  3. Use logo após ChartRedraw().

Eu fiz 2 testes, e não funcionou, e não sei se era o que vc sugeriu.

Pode ser um tipo de lógica simples, mas confesso que estou com uma tremenda dificuldade para aprender a elaborar esse tipo de lógica.

O primeiro teste, apenas criei uma variável para guardar a posição de [ i ], e tirei todo o conteúdo para fora do while.

// #########  Condição para plotar as linhas
        //if(Period() == PERIOD_M1){
        //    if(wBuffer[i] >= 91500){
        //      wColor[i] = 2; //Color White
        //      ObjectMove(0,"HighLineM1",0,TimeCurrent(),high[i]);
        //      }
        //    if(wBuffer[i] <= -91500){
        //       wColor[i] = 2; 
        //       ObjectMove(0,"LowLineM1",0,TimeCurrent(),low[i]);
        //       //ChartRedraw();
        //    }
        //}
        // #####################################
        pos = i;
   i++;
  }
  ChartRedraw();
        // #########  Não pinta de branco e não plota as linhas
        if(Period() == PERIOD_M1){
            if(wBuffer[pos] >= 91500){
              wColor[pos] = 2; //Color White
              ObjectMove(0,"HighLineM1",0,TimeCurrent(),high[pos]);
              }
            if(wBuffer[pos] <= -91500){
               wColor[pos] = 2; 
               ObjectMove(0,"LowLineM1",0,TimeCurrent(),low[pos]);
            }
        }
        // #####################################
   return(rates_total);
  }


No segundo teste, criei mais 2 variáveis do tipo int para guardar o evento caso se confirma-se.

        // #########  Condição para plotar as linhas
        if(Period() == PERIOD_M1){
            if(wBuffer[i] >= 91500){
               posU = 1; //Guardando o evento
              //wColor[i] = 2; //Color White
              //ObjectMove(0,"HighLineM1",0,TimeCurrent(),high[i]);
              }
            if(wBuffer[i] <= -91500){
               posD = -1;
               //wColor[i] = 2; 
               //ObjectMove(0,"LowLineM1",0,TimeCurrent(),low[i]);
               //ChartRedraw();
            }
        }
        // #####################################
        pos = i;
   i++;
  }
  ChartRedraw();
         // #########  Não pinta o histograma e plota as linhas uma sobre a outra.
            if(posU == 1){
              wColor[pos] = 2; //Color White
              ObjectMove(0,"HighLineM1",0,TimeCurrent(),high[pos]);
              }
            if(posD == -1){
               wColor[pos] = 2; 
               ObjectMove(0,"LowLineM1",0,TimeCurrent(),low[pos]);
            }
        // #####################################
   return(rates_total);
  }


No total declarei essas variáveis acima do while.

int posU = 0;
int posD = 0;
int pos;

Onde em tudo eu errei?

 
prsc:

Eu fiz 2 testes, e não funcionou, e não sei se era o que vc sugeriu.

Pode ser um tipo de lógica simples, mas confesso que estou com uma tremenda dificuldade para aprender a elaborar esse tipo de lógica.

O primeiro teste, apenas criei uma variável para guardar a posição de [ i ], e tirei todo o conteúdo para fora do while.


No segundo teste, criei mais 2 variáveis do tipo int para guardar o evento caso se confirma-se.


No total declarei essas variáveis acima do while.

int posU = 0;
int posD = 0;
int pos;

Onde em tudo eu errei?

ChartRedraw() vem DEPOIS de você mover os objetos!
 

E, tem que testar, não me lembro o comportamento, mas o ObjectMove() precisa receber o Time da barra e não simplesmente o TimeCurrent(), ou seja, em um timeframe de M5, seria 2020.01.24 16:05:00, e não 2020.01.24 16:05:17.  Estou desconfiado apenas, não tenho certeza... O MQL5 tem muitas dessas pegadinhas...


;)

 
Flavio Jarabeck:

E, tem que testar, não me lembro o comportamento, mas o ObjectMove() precisa receber o Time da barra e não simplesmente o TimeCurrent(), ou seja, em um timeframe de M5, seria 2020.01.24 16:05:00, e não 2020.01.24 16:05:17.  Estou desconfiado apenas, não tenho certeza... O MQL5 tem muitas dessas pegadinhas...


;)

Para pintar o histograma, a coloração precisa ficar dentro do while mesmo.

Criei uma variável do tipo MqlDateTime para puxar o minuto e também não funcionou.

Com esse código modificado abaixo, ficou como no print em anexo, as linhas sobrepostas.


        // #########  Condição para plotar as linhas
        if(Period() == PERIOD_M1){
            if(wBuffer[i] >= 91500){
               posU = 1;
              wColor[i] = 2; //Color White
              //ObjectMove(0,"HighLineM1",0,TimeCurrent(),high[i]);
              }
            if(wBuffer[i] <= -91500){
               posD = -1;
               wColor[i] = 2; 
               //ObjectMove(0,"LowLineM1",0,TimeCurrent(),low[i]);
            }
        }
        // #####################################
        pos = i;
   i++;
  }
  
         // #########  Movendo a coloração para dentro do while, voltou a pintar o candle, mas linhas sobrepostas
            if(posU == 1){
             // wColor[pos] = 2; //Color White
              ObjectMove(0,"HighLineM1",0,candle.min,high[pos]); //Criei uma variável candle / MqlDateTime candle; TimeCurrent(candle); /
              //ChartRedraw();
              }
            if(posD == -1){
               //wColor[pos] = 2; 
               ObjectMove(0,"LowLineM1",0,0,low[pos]);
              // ChartRedraw();
            }
            ChartRedraw();
        // #####################################
   return(rates_total);


E no código original com o erro de movimento, quando não ultrapassa o valor estipulado, plota no lugar correto e fica ali como no print.

Arquivos anexados:
 
prsc:

Para pintar o histograma, a coloração precisa ficar dentro do while mesmo.

Criei uma variável do tipo MqlDateTime para puxar o minuto e também não funcionou.

Com esse código modificado abaixo, ficou como no print em anexo, as linhas sobrepostas.



E no código original com o erro de movimento, quando não ultrapassa o valor estipulado, plota no lugar correto e fica ali como no print.

Não é só vc usar:

time[pos]


pra pegar o tempo?

 

E, leia a documentação do ChartRedraw().


Basta 1 unica vez depois de mover os elementos do gráfico...

 
Flavio Jarabeck:

E, leia a documentação do ChartRedraw().


Basta 1 unica vez depois de mover os elementos do gráfico...

Eu estava só testando individualmente o ChartRedraw(), não deixava todos habilitados.

Sobre a hora, não tem o que faça, sempre o resultado é o mesmo, time[pos] também não funcionou e outros que tentei.

No indicador de pintar candle que tenho, tem as condições para pintar, e o else no final caso termine sem validar as anteriores, vai para um valor padrão

Nesse aqui não sei fazer um else onde buscaria a posição anterior como o valor padrão.

Por data/time não está fazendo efeito nenhum.

Eu gostaria que funciona-se rápido o indicador, mas também não me queixo de um pouco de dificuldade, afinal estou aprendendo ainda, só tenha paciência com o novato :)

Razão: