[SERVICE DESK] Error in getting the time of the senior TF in the timer! - page 6

 
I would be very interested to hear what the developers think about this.
 
 ResetLastError();
      if(iBarShift(Symbol(),PERIOD_M15,TimeCurrent(),true)==-1)
        {
         Print(__FILE__+": Данные истории по последнему часу отсутствуют! Ошибка #",GetLastError());
         return( false );
        }
      //---
      if(GetLastError()==ERR_NO_ERROR)
        {
         ResetLastError();
         //--- Запоминаем время открытия бара
         _m15OpenTime=iTime(NULL,PERIOD_M15,0);
         //---
         Print(__FILE__,": Актуальное время открытия бара М15 = "+TimeToString(_m15OpenTime)+". Ошибка #",GetLastError());
         //--- Возвращаем истину
         return( true );
        }
 
Alexey Kozitsyn:

It seems that the most reliable solution is really to wait for call of OnCalculate() with obligatory check of connection to trade server. If we do not check for connection (IsConnected()), then even in OnCalculate() we will get it at terminal loading:

However, it does not remove all questions:

1. Why doesn't it written in documentation to IsConnected() that it must be necessarily called before receiving data (at least) from the senior TF in OnCalculate()?

2. Why IsConnected() in OnTimer() actually does not work? Isn't the fact of establishing connection with a trade server supposed to tell us that data can be obtained?

3. Once we have established a connection with the trade server and are trying to receive data in OnTimer(), shouldn't functions iTime(), iBarShift(), SeriesInfoInteger() and functions similar to them return errors if data from this particular trade server, from which they take information, are not yet synchronized? Otherwise it turns out some nonsense, like we return error 4066 to you once and then you can use the data you have.

I have talked to the developers and one of my friends there and I am telling them the following: 1 What do I do?

1 Nonsense, you can call it whenever and from anywhere.

2 IsConnected can be called from anywhere in the code and it works, but it is a function that does not write anything on the error stack it returns true/false and that's it. Considering that the connection procedure is quite (minimum 1 sec) long and IsConnected is triggered at login time, it is necessary to check the connection status and wait for the start of quotes flow when starting the terminal.

3 These functions don't write anything to the error stack, they return the result themselves.

Why did we get 4066? That error was caused by the TimeCurrent function. Terminal logged in and requested time from the server depending on the connection quality it also takes some time, so we have a quick timer. And then we got 4066 on our request from TimeCurrent. And then we got the time and our functions started working normally and they themselves return an error as a result of their work bypassing the error stack.

As a recommendation in such situation, quick timer and terminal start, be sure to check that we started getting data from the server. My version is a bit crutchy, it would be correct to get a signal from OnCalculate to start receiving data.

 
It's simpler than that.
 
Alexey Kozitsyn:

What do you suggest to solve the problem (is there, in your opinion)? Wait until OnCalculate() is called 1-2 times?

Yes, exactly. In OnInit() just call the required TFs without checking the result (you cannot rely on it there), and in OnCalculate call the function IsTFDataReady(). As soon as true is returned for all requested TFs, you can start to execute the indicator's algorithm.

 
Alexey Kozitsyn:

1. Why doesn't the documentation for IsConnected() say that it must always be called before receiving data (at least) from the senior TF in OnCalculate()?

IsConnected() is quite a tricky function. It returns state of only one connection to server. But the terminal uses more than one connection. There are 8 trade threads by itself. So even if IsConnected() returns true, it is not quite clear what it means. At least, we cannot expect that timeseries will be requested and built. But if IsConnected() returns false, then we can be sure that the terminal is still offline.

What is the task, for which the presence of the terminal connection is so crucial? As far as I understand, the indicator is a tool for visualizing data. The data that is available. When new data arrives, it will update the visualization. It should not be required to check whether the data is up to date. That is the task of the terminal.

 
Igor Makanu:

I guess we are talking about MQL5, OHLC preparation is not the same as in MT4

I'm talking about MT4. About 2-3 years ago I was catching a bug with Time[0]. The developers seem to have fixed it, but then, over time, it showed up again. The problem is that it's impossible to unambiguously reproduce this bug.

 
Ihor Herasko:

IsConnected() is a rather tricky function. It only returns the status of one of the connections to the server. But the terminal uses more than one connection. There are 8 trade threads alone. So even if IsConnected() returns true, it is not quite clear what it means. At least, we cannot expect that timeseries will be requested and built. But if IsConnected() returns false, then we can be sure that the terminal is still offline.

What is the task, for which the presence of the terminal connection is so crucial? As far as I understand, the indicator is a tool for visualizing data. The data that is available. When new data arrives, it will update the visualization. It should not be required to check the relevance of data. This is the task of the terminal.

For indicators I don't remember the necessity to check the connection with the server, what we have in the history is drawn, when the history is loaded it means that all indicator buffers are recalculated

I have developed and use the following function in my EA. It is generally satisfying and it checks the connection with the server correctly:

bool ServerDisable(int count=10){
   if(IsTesting()||IsOptimization())return(false);
   for(int i=0;i<count;i++){
      if(IsConnected())
         if(IsTradeAllowed())
            if(!IsTradeContextBusy()){RefreshRates(); return(false);}
      Sleep(157);
   }
   Print(__FUNCTION__," Торговый сервер не отвечает");
return(true);}

I specifically use Sleep() in it to transmit control to the terminal and then check connection to the server and possibility to trade

 
Ihor Herasko:

I'm talking about MT4. About 2-3 years ago I was catching a bug with Time[0]. The developers seemed to have fixed it, but then, over time, it showed up again. The problem is that it's impossible to unambiguously reproduce this bug.

If it's not too much trouble, here's the topic of the topic - correct downloading of history from the major TF, here's the indicator: "I need to draw the MA" from the major TF on the bars of the minor TF, I made it within 5 minutes, it will work for 98% correctly, where in this code 2% "pitfalls" that will cause bugs?

I am interested in correct code for MT4

#property copyright "IgorM"
#property link      "https://www.mql5.com/ru/users/igorm"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot line1
#property indicator_label1  "line1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input ENUM_TIMEFRAMES   TimeFrame   =  PERIOD_H4;
input int               MAPeriod    =  25;
//--- indicator buffers
double         BufMA[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   double cl[];
//--- indicator buffers mapping
   SetIndexBuffer(0,BufMA);
   IndicatorDigits(Digits);
// запускаем подгрузку истории и выходим, даже не проверяя подгружена она или нет, история тут еще не нужна
   CopyClose(_Symbol,TimeFrame,0,iBars(_Symbol,TimeFrame),cl);
//---
   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[])
  {
//---
   int i,limit,resultcopy;
   double closetf[];
   if(prev_calculated==0)
     {
      resultcopy=CopyClose(_Symbol,TimeFrame,0,iBars(_Symbol,TimeFrame),closetf);
      if(resultcopy<0)
        {
         Print("Подгрузка истории....");
         return(0);
        }
      if(resultcopy<MAPeriod)
        {
         Comment("Большой период МА!!!, в истории доступно ", resultcopy," баров");
         return(resultcopy);
        }
      limit=resultcopy-1;
        }else{
      resultcopy=CopyClose(_Symbol,TimeFrame,0,iBars(_Symbol,TimeFrame),closetf);
      if(resultcopy<0)
        {
         Print("Подгрузка истории....");
         return(0);
        }
      if(resultcopy<MAPeriod)
        {
         Comment("Большой период МА!!!, в истории доступно ", resultcopy," баров");
         return(resultcopy);
        }
      limit=resultcopy-prev_calculated+1;
     }
   limit = fmin(rates_total-1,limit);
// основной цикл расчета индикатора
   for(i=limit; i>=0 && !IsStopped(); i--)
     {
      BufMA[i]=iMA(_Symbol,TimeFrame,MAPeriod,0,MODE_SMA,PRICE_CLOSE,i);
     }
//---
   return(resultcopy);

  }
 
Vitaly Gorbunov:

I talked to the developers and a friend I know there, and I'll tell you one thing at a time.

1 Nonsense, you can call it whenever and from any place.

2 IsConnected can be called from anywhere in the code and it works, but it is a function that does not put anything on the error stack, it returns true/false and that's it. Considering that the connection procedure is quite (minimum 1 sec) long and IsConnected is triggered at login time, it is necessary to check the connection status and wait for the start of quotes flow when starting the terminal.

3 These functions don't write anything to the error stack, they return the result themselves.

Why did we get 4066? That error was caused by the TimeCurrent function. Terminal logged in and requested time from the server depending on the connection quality it also takes some time, so we have a quick timer. And then we got 4066 on our request from TimeCurrent. And then we got the time and our functions started working normally and they themselves return an error as a result of their work bypassing the error stack.

As a recommendation in such situation, quick timer and terminal start, be sure to check that we started getting data from the server. My variant is a bit crutchy, it would be correct to get a signal from OnCalculate to start receiving data.

1. Read carefully what I write. It's not the first time I told you so! I didn't say anything about not calling somewhere!

Are you saying that all functions iBarShift(), iTime(), SeriesInfo...() request TimeCurrent()?