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

 
Vitaly Gorbunov:
The iBarShift method allows you to find holes in the history, but you have to check the history at intervals. I have written a procedure for myself that does this, and after that I have forgotten about the gaps in the MtF programs.
It was not a question of detecting "holes". The person wanted to get the last bar in the history. And this is not necessarily the current bar in time.
 
Vitaly Gorbunov:
The data is loaded with the 4066 error, and then it is the fault of the methaquotovs, most likely the received data is processed for this situation, the error was not invented. And up to that point, everything makes sense.

If an error is "not invented", it does not mean that it does not exist.

 
Alexey Navoykov:
This was not a question of detecting "holes". The person wanted to get the last bar in the history. And this is not necessarily the current time bar.

It's not about iBarShift(). It sends the same errors as iTime() and SeriesInfoInteger(). The crutch here is in comparing the time obtained during initialization and then comparing it with the time from the timer. That's what allowed to get correct actual data when loading terminal, not IBarShift().

Yes, and if the time is 15:00:45 (for example), and there is no tick on the 15:00 bar yet and if the time of the last hour bar opening is 14:00 - everything is correct, I think. And if the system returns 13:00 - that's a problem.

 
Alexey Kozitsyn:

1. Igor, have you looked at the code? Where do I get something in OnInit()?

In your case one or several OnTimer calls are executed right after OnInit(). There is no OnCalculate() event yet.

2. What checks? Where is it written that the indicator must use OnCalculate() at least once to work correctly?

Here we need to understand the logic of the terminal. OnInit() is called immediately when connecting the indicator to the chart. When starting the terminal, the connection of the indicator to the chart is performed right after the chart window is created. At this moment, the terminal hasn't even sent the request to the server.

The first OnCalculate() is called after the locally available quotes have been read. In some rare cases it happens that there is nothing locally. In this case, when addressing to Time[0], the indicators get out of the array. Therefore, it is better to use iTime function or similar.

The second and next OnCalculate() occur at history loading or at real ticks arrival.

 
Ihor Herasko:

The first OnCalculate() is called after reading the locally available quotes. In some rare cases it happens that there is nothing locally. In this case, when referring to Time[0], the indicators get out of the array. Therefore, you'd better use iTime function or similar.

I guess we are speaking about MQL5, OHLC preparation is different there than in MT4

I have been writing indicators based on a template for a long time:

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;
   if(prev_calculated==0)
     {
      limit=rates_total-1;    //--- Первый вызов индикатора или смена таймфрейма или подгрузка данных из истории
     }
   else limit=rates_total-prev_calculated+1;
   for(i=limit;i>=0;i--)      //---- Основной цикл расчета
     {                        
     }
   return(rates_total);
  }

i have never had an "indicator crash" on OHLC arrays in MT4, i think that MT4 will not run OnCalculate() until a chart is prepared for the first time, and if the history is loaded, i have not checked it, but prev_calculated==0 , in MT5 it will be like you wrote - you need additional checks to see if the OHLC data is already prepared

 
Ihor Herasko:

In your case one or more OnTimer calls will be executed right after OnInit(). There is no OnCalculate() event yet.

Here you need to understand the logic of the terminal. OnInit() is called immediately when connecting the indicator to the chart. When starting the terminal, connection of the indicator to the chart is performed right after the chart window is created. At this moment, the terminal hasn't even sent the request to the server.

The first OnCalculate() is called after the available quotes have been read locally. In some rare cases it happens that there is nothing locally. In this case, when addressing to Time[0], the indicators get out of the array. Therefore, it is better to use iTime function or similar.

The second and next OnCalculate() occur at history loading or at real ticks arrival.

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

 
Alexey Kozitsyn:

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

You may try tocopyprev_calculated==0 valueto a variable on the global scope and see in OnTimer() if the indicator has been calculated.OnCalculate() - it will be calculated in any case, I suspect that if the TF data was not ready, thenreturn(rates_total) will return 0, which will be in the next call ofOnCalculate() indicatingprev_calculated==0, approximately:

void OnTimer(){
   if(Global_prev_calculated==0)return;
}
 
Igor Makanu:

you may try tocopyprev_calculated==0 valueto a variable on the global scope and see in OnTimer() if the indicator was calculated; I wrote above that I never saw any bugs with incorrect calculation in MT4OnCalculate() - it will be calculated in any case, I suspect that if the TF data was not ready, thenreturn(rates_total) will return 0, which will be in the next call ofOnCalculate() a signprev_calculated==0

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

2018.09.21 23:45:27.128 test_isNewDayInOnCalculate_iBarShift() EURGBP.e,M1: test_isNewDayInOnCalculate_iBarShift().mq4: Актуальное время открытия бара М15 = 2018.09.21 21:30. Ошибка #0
2018.09.21 23:45:25.990 test_isNewDayInOnCalculate_iBarShift() EURGBP.e,M1: initialized
2018.09.21 23:45:25.975 Custom indicator test_isNewDayInOnCalculate_iBarShift() EURGBP.e,M1: loaded successfully

However, it does not remove all questions:

1. Why doesn't it say in the 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 looks nonsense, like we return error 4066 once and then use the present data in any way you want.

 
Alexey Kozitsyn:

However, this does not remove all questions:

1. Why doesn't the documentation for IsConnected() say that it must necessarily be 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 looks nonsense, like we return a 4066 error once and then deal with the existing data the way you want.

1. Well, no one cancelled the case of indicator call on historical data, if you need to work online, then check the connection, if not, or rather not important, then my version of the template works. The IsConnected() function group is actually a bit tricky, they cross IsTradeContextBusy() and IsConnected() itself sometimes and IsTradeAllowed()... I think they mess up on the server side and disconnect terminals at the time of news or any other manipulations

2,3. works, but you forget that GetLastError() will reset its state after a call and perhaps to update the state GetLastError() needs to transfer control to the terminal, maybe the terminal did not have time to re-set the state IsConnected() in GetLastError() before your call from the timer.... I think the OnTimer() function is not intended for receiving data: "MQL4 Reference / Status Check - OnTimer() will be called, but the variables of the terminal environment are not updated, andonCalculate() it's guaranteed to prepare all data by the terminal when the tick comes

 
Igor Makanu:

1. well, no one has cancelled the case of calling the indicator on historical data...

2,3. it works, but you forget that GetLastError() will reset its state after the call, and perhaps to update the state GetLastError() needs to pass control to the terminal, perhaps the terminal does not have time to re-set the state IsConnected() in GetLastError() before your call from timer.... I think the OnTimer() function is not intended for receiving data: "The MQL4 Reference / Status Check - OnTimer() will be called, but the variables of the terminal environment are not updated, and it's guaranteed that the terminal will prepare all the data when the tick comes-OnCalculate().

1. Do you think that if bar number 0 has incorrect time, the rest of the history will have a correct time?)

2,3. If data access functions don't have enough time to set some meaningful error - let it report it somehow, but certainly not by returning error code = 0 (no error). The rest of the "maybe" is just guesswork. And without proof there is nothing to talk about.

The OnTimer() function is not intended to fetch data...

No comment.

OnTimer() will be called but terminal environment variables are not necessarily updated

What do we need the 4066 error for?