How to wait for all bars to be loaded before taking a screenshot?

 

Hello,

I have a profile with 40 charts and when I use it there is an indicator in each chart which makes a screenshot. The problem here is that there are sometimes two screenshots of one chart. These screenshots are a bit different. The second screenshot contains more current data. I think that the first screenshot is taken before all current chart data is loaded and the second when the loading-process is done. I thought this might only happen to the chart symbols I don't watch very often (in other profiles) and so their history is not updated. But today I noticed that it also happens to EURUSD which is always open in every profile and the data are loaded.

Does someone have an idea how to check if all data are loaded before taking a screenshot? 

 

How to help you without code?

Use the SRC-button please

 

There is no special code for that. I only use a very simple indicator, which makes a screenshot.

#property strict
#property indicator_chart_window

string strTF;
string TimeToStringNS(datetime when){
  string withSep = TimeToStr(when, TIME_DATE|TIME_SECONDS), // "yyyy.mm.dd hh:mm:ss"
         withOut = StringSubstr(withSep,  0, 4)  // yyyy
                 + StringSubstr(withSep,  5, 2)  // mm
                 + StringSubstr(withSep,  8, 2)  // dd
                 + StringSubstr(withSep, 11, 2)  // hh
                 + StringSubstr(withSep, 14, 2)  // mm
                 + StringSubstr(withSep, 17, 2); // ss
  return(withOut);                               // "yyyymmddhhmmss"
}
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   switch(Period()) {
      case PERIOD_MN1: strTF = "MN1";  break;
      case PERIOD_W1 : strTF = "W1";   break;
      case PERIOD_D1 : strTF = "D1";   break;
      case PERIOD_H4 : strTF = "H4";   break;
      case PERIOD_H1 : strTF = "H1";   break;
      case PERIOD_M30: strTF = "M30";  break;
      case PERIOD_M15: strTF = "M15";  break;
      case PERIOD_M5 : strTF = "M5";   break;
      case PERIOD_M1 : strTF = "M1";   break;
   }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   
   static datetime Time0;
   if (Time0 == Time[0]) return(0);
   Time0 = Time[0];
   string Now = TimeToStringNS(TimeCurrent());
   ChartScreenShot(0, Symbol()+"_"+strTF+"_"+Now+".gif", 1280, 720);
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

Here is an example. I switched the timeframes of all charts simultaneously with a script to M15 and then a screenshot was made. The second screenshot of the EURJPY is made two seconds later and it shows the current price data which the first one doesn't show. I am sure that the screenshot is taken before the current data could be loaded. But I don't know how to avoid that.

 

 

 

hmm - please post the file names (with TimeCurrent()).

 
The first screenshot is named EURJPY_M15_20150204114048.gif and the second is EURJPY_M15_20150204114050.gif
 
Check out (Print()) the time of Time[0] may be you can wait until Time[0] > TimeCurrent()-PeriodSeconds() ??
 

gooly, that was a great idea! I added this line

Comment("Time[0] > TimeCurrent()-PeriodSeconds()  =  ", Time[0] > TimeCurrent()-PeriodSeconds());

before the screenshot and if there are two charts of one symbol, the first charts comment is false and the second chart with the current data shows true.

Now I changed the code to this:

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[])
  {
//---
   
   static datetime Time0;
   if (Time0 == Time[0]) return(0);
   Time0 = Time[0];
   string Now = TimeToStringNS(TimeCurrent());
   while (Time[0] < TimeCurrent()-PeriodSeconds()) {};
   ChartScreenShot(0, Symbol()+"_"+strTF+"_"+Now+".gif", 1280, 720);
//--- return value of prev_calculated for next call
   return(rates_total);
  }

 And the while-loop works great here. No additional screenshots anymore. I don't know if all data are loaded now because of the tests I made. Therefore I try this indicator in 1-2 hours when I am back from the gym.

The only thing I don't like about that solution is that this could under some circumstances result in an endless loop. 

 

To save the earth by power saving you might add a little sleep?

while (Time[0] < TimeCurrent()-PeriodSeconds()) Sleep(500);
 
gooly:

To save the earth by power saving you might add a little sleep?

Not in an indicator, it will be ignored.
 
You can use OnTimer() to build in a delay
 
GumRai:
Not in an indicator, it will be ignored.

ok - you're right, I forgot.

Reason: