prev_calculated not reset to 0 after timeframe change?

 
I'm having a heck of a time setting up my custom indicator to only update the most recent bar on new_bar event and update the entire array when the timeframe is changed. My indicator is linked to an EA that downloads a file, reads and records an array, prints the array to file, and then I want the indicator to read the file and plot the array as a histogram. I'm using a global variable to check if new data is available or not. The problem is, I can either get the indicator to update one bar at a time with each new bar or update the entire histogram array (thereby erasing the last element in the array with each new bar). 
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_buffers 1
#property indicator_plots   1
//--- plot btcvl
#property indicator_label1  "array"
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_style1  STYLE_SOLID
#property indicator_width1  3

string   Filename="file_data.bin";
//--- indicator buffers
double         array[];
double         arrayBuffer[];
double         old_data;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   old_data=-1;

   IndicatorSetString(INDICATOR_SHORTNAME,"FileData");
   ArraySetAsSeries(array,true);
   ArraySetAsSeries(arrayBuffer,true);

   PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrRoyalBlue);
//--- indicator buffers mapping
   SetIndexBuffer(0,array,INDICATOR_DATA);
//---
    
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double& price[])
  {
  
   while(GlobalVariableGet("new data")!=old_data && !IsStopped()){
         ArrayInitialize(array,0);
         ArrayRemove(arrayBuffer,0,WHOLE_ARRAY);
         ReadFile(Filename);
         ArrayCopy(array,arrayBuffer,1,0,
WHOLE_ARRAY );
         old_data=GlobalVariableGet("new data");
      }
   
   
   return(rates_total);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ReadFile(string file)
  {
   if(file==Filename)
     {
      int v_file=FileOpen(Filename,FILE_READ|FILE_BIN);
      if(v_file!=INVALID_HANDLE)
        {
         FileReadArray(v_file,arrayBuffer,0,WHOLE_ARRAY);
         FileClose(v_file);
        }
     }

  }

The code works unless I want to accumulate new bars. For example, the file data holds 50 bars of data, and with each new bar, the entire histogram plot is replaced with the new 50 bars of data, essentially shifting the data to the left to add a new bar. I don't want this. I want it to only update the entire array if the timeframe is changed. I've tried putting the condition of only updating the entire array if prev-calculated = 0 but that doesn't seem to reset to zero when the timeframe changes. I've tried to build it like a normal indicator, with arraysetasseries(false) and finding a starting point to fill the price[] using prev_calculated and rates_total and I can get both scenarios to work. The problem is when the timeframe changes, it breaks.

Any education would be appreciated. ps. Webrequest is so slow and this is not a very practical indicator for daytrading but it is a project I'm doing to challenge myself to better learn reading, cleaning, and transforming spreadsheets in code.

Step on New Rails: Custom Indicators in MQL5
Step on New Rails: Custom Indicators in MQL5
  • www.mql5.com
I will not list all of the new possibilities and features of the new terminal and language. They are numerous, and some novelties are worth the discussion in a separate article. Also there is no code here, written with object-oriented programming, it is a too serous topic to be simply mentioned in a context as additional advantages for developers. In this article we will consider the indicators, their structure, drawing, types and their programming details, as compared to MQL4. I hope that this article will be useful both for beginners and experienced developers, maybe some of them will find something new.
 

If you change the timeframe or the name of the chart symbol in MetaTrader, all indicators on the chart will be unloaded from the chart and will be loaded onto it again. Unlike MT4, in MT5 the sequence of load/unload is not defined due to its internal architecture.

This feature sometimes causes problems which are not immediately obvious. These problems are related to the fact that OnInit of the new loaded indicator instance can be executed before the OnDeinit of the instance being unloaded.

Situations in which this problem is detected, are most often connected with the desire to transmit (explicitly/implicitly) some information from OnDeinit of the older indicator instance to OnInit of the new one. In other words, the new indicator instance should know about the existence of the old one, and should not load until the old instance is unloaded.

https://www.mql5.com/en/code/18138

Init_Sync
Init_Sync
  • www.mql5.com
The library makes indicators' Init/Deinit synchronized
 

So OnDeinit() is called when the timeframe or symbol changes. I read that is the case but when I placed a Print("DeInit") in the OnDeInit function and changed timeframes, it does not print it at all. After including those libraries, it now does call the OnDeInit() and OnInit() functions in order. This should be the key to solving my problem. I'll work on it and post the solution when I'm finished. Thank you for your help! I never would have figured this out.

 

"prev_calculated not reset to 0 after timeframe change"

It's not true, is it?

Problem in OnInit()/OnDeinit() call sequence. The value of prev_calculated will be reset even if the sequence of calls is broken, right?

After all, the new copy of the indicator cannot know the value of prev_calculated for the old copy...

 
Vladislav Boyko #:

"prev_calculated not reset to 0 after timeframe change"

It's not true, is it?

Problem in OnInit()/OnDeinit() call sequence. The value of prev_calculated will be reset even if the sequence of calls is broken, right?

After all, the new copy of the indicator cannot know the value of prev_calculated for the old copy...

Right.

 
Vladislav Boyko #:

"prev_calculated not reset to 0 after timeframe change"

It's not true, is it?

Problem in OnInit()/OnDeinit() call sequence. The value of prev_calculated will be reset even if the sequence of calls is broken, right?

After all, the new copy of the indicator cannot know the value of prev_calculated for the old copy...

It's strange though because I had if(prev_calculated == 0 ) Print("prev_calculated = 0"); and it was only printing when I recompiled or first added it to the chart until I added those synch libraries. But I am skeptical now.

 
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double& price[])
  {
  
   while(GlobalVariableGet("new data")!=old_data && !IsStopped()){
         ArrayInitialize(array,0);
         ArrayRemove(arrayBuffer,0,WHOLE_ARRAY);
         ReadFile(Filename);
         ArrayCopy(array,arrayBuffer,1,0,
WHOLE_ARRAY );
         old_data=GlobalVariableGet("new data");
      }
   
   
   return(rates_total);
  }

Where do you check prev_calculated?

 
Keith Watford #:

Where do you check prev_calculated?

Why should I check though? I've just added a if(prev_calculated < rates_total) new_bar = true; But the WebRequest() takes about 2.7 seconds at its fastest to complete before the global variable is updated so I can't rely on tick data to know when to update the price array. Edit: I should mention, the data is never for the current bar, it only includes last completed bar.

 
skylarwalker #:

Why should I check though? I've just added a if(prev_calculated < rates_total) new_bar = true; But the WebRequest() takes about 2.7 seconds at its fasted to complete before the global variable is updated so I can't rely on tick data to know when to update the price array.

I am confused by your reply.

You say that prev_calculated is not reset to zero when the TF is changed.

How do you Know? You don't check it in your code!

 
Keith Watford #:

I am confused by your reply.

You say that prev_calculated is not reset to zero when the TF is changed.

How do you Know? You don't check it in your code!

Ah I see, sorry I removed the check from the code before I shared it. It was simply if(prev_calculated==0) Print("prev_calculated = 0"); And it wasn't printing when I changed timeframes but it is no matter, now it is working fine.

So I don't know why it wasn't printing, it must have been something wrong with my loop statement making it freeze or something.

 

Ok, here's my bitcoin aggregate volume indicator, not using an API but simply ( and slowly) downloading a csv file from bitcoinity.org. I am a beginner so if I did something that doesn't make sense, it's because I didn't know any better. But it works as I intend for the most part. Still needs a little cleaning up.


https://github.com/SkyWes/BtcAggregateVolume.git

GitHub - SkyWes/BtcAggregateVolume: A simple EA and Indicator pair that plots a histogram of aggregated bitcoin volume scraped from the web.
GitHub - SkyWes/BtcAggregateVolume: A simple EA and Indicator pair that plots a histogram of aggregated bitcoin volume scraped from the web.
  • SkyWes
  • github.com
A simple EA and Indicator pair that plots a histogram of aggregated bitcoin volume scraped from the web. Add the indicator to the chart first. Give it a few seconds to update, the web scrape takes a few seconds.