Array Buffer Values get mixed?!?! - page 2

 
Fernando Carreiro #:

I have already provided you with an example in my previous post ... #9

As for you not being able to use a loop to update previous values, without an actual detailed explanation of what you are doing, I cannot just "guess" at what should be done for your case specifically.

can I just remove the for-loop from your example and just use the buffer[0] =  .... ?

Like this:

#property strict

#property indicator_separate_window

#property indicator_buffers   2

#property indicator_label1    "Bar Up"
#property indicator_color1    clrLimeGreen
#property indicator_width1    2
#property indicator_style1    STYLE_SOLID
#property indicator_type1     DRAW_HISTOGRAM

#property indicator_label2    "Bar Down"
#property indicator_color2    clrFireBrick
#property indicator_width2    2
#property indicator_style2    STYLE_SOLID
#property indicator_type2     DRAW_HISTOGRAM

double g_dbBufferBarUp[], g_dbBufferBarDown[];

int OnInit( void )
{
   IndicatorSetInteger( INDICATOR_DIGITS, _Digits );
   SetIndexBuffer( 0, g_dbBufferBarUp,   INDICATOR_DATA );
   SetIndexBuffer( 1, g_dbBufferBarDown, INDICATOR_DATA );
   return( INIT_SUCCEEDED );
};

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[]
   )
{
      double dbCloseOpen     = close[0] - open[0];
      g_dbBufferBarUp[0] = dbCloseOpen > 0.0 ?  dbCloseOpen : 0.0;
      g_dbBufferBarDown[0] = dbCloseOpen < 0.0 ? -dbCloseOpen : 0.0;


   return( rates_total ); // Return value of prev_calculated for next call
};


Would it be correct?

 
Dmitry Zhakov #: can I just remove the for-loop from your example and just use the buffer[0] =  .... ? Like this: Would it be correct?

As per your original post (and code where you DIDN'T use a loop), you stated that ... "Everything works correctly. But after some time the buffer values get either corrupted or mixed."

So, how are you going to resolve that, when for example there is a history update or bars are missed or recalculations are needed?

How are you going to detect which buffer data is valid and which is corrupted?

Unless you give a more clear understanding of what you are doing, we are unable to give you a proper answer.

EDIT: You will probably, need to build a separate internal (or external) database of the data you are collecting and then use that to keep the buffers synchronised properly. However, I don't know what you are doing, so I am only guessing here.

 
Fernando Carreiro #:

As per your original post (and code where you DIDN'T use a loop), you stated that ... "Everything works correctly. But after some time the buffer values get either corrupted or mixed."

So, how are you going to resolve that, when for example there is a history update or bars are missed or recalculations are needed?

How are you going to detect which buffer data is valid and which is corrupted?

Unless you give a more clear understanding of what you are doing, we are unable to give you a proper answer.

EDIT: You will probably, need to build a separate internal (or external) database of the data you are collecting and then use that to keep the buffers synchronised properly. However, I don't know what you are doing, so I am only guessing here.


My question is why the old buffer data is overwritten by MetaTrader? 

I see that I had missing "INDICATOR_DATA" in SetIndexBuffer. I had it just SetIndexBuffer (0, g_dbBufferBarUp); I do not know it that could be the reason... 

SetIndexBuffer( 0, g_dbBufferBarUp,   INDICATOR_DATA );
 
Dmitry Zhakov #My question is why the old buffer data is overwritten by MetaTrader? 

I'm not sure. The are several possible factors, but since we don't have access to your whole code, we can only guess.

Dmitry Zhakov #: I see that I had missing "INDICATOR_DATA" in SetIndexBuffer. I had it just SetIndexBuffer (0, g_dbBufferBarUp); I do not know it that could be the reason... 

No, that part will not affect it, because "INDICATOR_DATA" is the default anyway.

 


Here I have done the test with the attached indicator. And as you see the histogram values are corrupted!!!  It happens after many hours of running. It was fully correct at beginning. And only after about 10 hours of running the old bars become wrong values. Every bullish candle should have green histogram bar and every bearish candle should have red histrogram bar. After x hours of running the values get mixed! While the "fresh" historgram bars are showing correct. Only old "histogram" bars become chaotic values. 

Old bars with chaotic values:



Fresh (new) bars with correct values:




Here is the indicator code:

#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_minimum    0
#property indicator_maximum    1


double barup[];
double bardn[];


int OnInit()
  {
   
   IndicatorSetInteger( INDICATOR_DIGITS, _Digits );   
   IndicatorBuffers(2);
   SetIndexBuffer(0,barup, INDICATOR_DATA );   
   SetIndexBuffer(1,bardn, INDICATOR_DATA );   
   SetIndexStyle (0, DRAW_HISTOGRAM, STYLE_SOLID, 2, clrLimeGreen);   
   SetIndexStyle (1, DRAW_HISTOGRAM, STYLE_SOLID, 2, clrRed);   
   SetIndexEmptyValue(0, 0.0);
   SetIndexEmptyValue(1, 0.0);  
     
      
//---
   return(INIT_SUCCEEDED);
  }
  
void OnDeinit(const int reason)
  {

  }  
  


//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+

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[]
   )
   {
//---
     
   if (Open[0] >= Close[0]) {
      bardn[0] = 1;
      barup[0] = 0; 
   }
   else if (Open[0] < Close[0]) {
      barup[0] = 1;
      bardn[0] = 0;
   }


   
//--- return value of prev_calculated for next call
   return( rates_total ); // Return value of prev_calculated for next call
 };
//+------------------------------------------------------------------+


PLEASE HELP ME TO SORT OUT THIS ISSUE. SEEMS THAT METATRADER HAS A CRITICAL BUG!

Files:
 
Dmitry Zhakov #: Here I have done the test with the attached indicator. And as you see the histogram values are corrupted!!!  It happens after many hours of running. It was fully correct at beginning. And only after about 10 hours of running the old bars become wrong values. Every bullish candle should have green histogram bar and every bearish candle should have red histrogram bar. After x hours of running the values get mixed! While the "fresh" historgram bars are showing correct. Only old "histogram" bars become chaotic values. Old bars with chaotic values: Fresh (new) bars with correct values: Here is the indicator code: PLEASE HELP ME TO SORT OUT THIS ISSUE. SEEMS THAT METATRADER HAS A CRITICAL BUG!

THERE IS NO BUG. I've already explained that the buffers sometimes need to be refreshed. This happens when the old bar data is removed or added from the chart or its maximum number bars changes.

Given, that you are only updating the current bar, this can and will happen, that the buffers becomes unsynchronised and need to be refreshed.

So, you have to create a mechanism to cache the external data in an internal or external database, to use as a source to refresh the buffers properly in a loop.

You could for example cache the data in an Offline Chart for example or some other data file of your own format.

 

Here is a simplistic example of when old data is removed from a chart:

Lets us say that you set your chart's maximum bars to 24 and you are displaying a H1 chart. As each new H1 bar comes in the old H1 bars 24 hours ago are removed so that you always only have 24 bars on your chart.

MetaTrader goes further by keeping a cache of the bars, so that this does not happen on every new bar, but eventually it will need to re-adjust the number of bars on the chart, and call for the buffers to be refresh/recalculated.

So, as you can see, it is not a bug, it is just as how it works, and why the "rates_total" and "prev_calculated" from OnCalculate() work as they do and you have to use a loop.

 
Dmitry Zhakov #:

can I just remove the for-loop from your example and just use the buffer[0] =  .... ?

Like this:


Would it be correct?

i'm more curious if any reason you don't want to use for-loop.

Reason: