Features of the mql5 language, subtleties and tricks - page 31

 
Artyom Trishkin:

Did you even look at the code I showed you? Did you run it?

I was not asking how to fill the indicator buffer, but why empty values are returned if I take values from AO not from the current bar.
I figured it out - there is no history, it is being loaded, and while it is being loaded AO from a non-native price returns an error "no data".

The question is how to know if the history is fully loaded in the necessary timeframe without entering the indicator cycle?

If you use the CopyBuffer in the indicator to receive data from another indicator, you need:

  1. Flip your indicator buffer so that the rightmost bar in the chart corresponds to index "0" in the indicator buffer.
  2. Thus, the "current bar" in the indicator "iMTF_AO.mq5" will be the RIGHT BAR in the chart, and it will correspond to index "0" in the indicator buffer "Buffer[]"
  3. And to get the "current bar" from the indicator (CopyBuffer(handle,0,shift,1,array)) "shift" parameter must be equal to "0".

If you don't want to flip the indicator buffer, do this (temporarily): AO(0) - to understand how to get from an INDICATOR the values of another INDICATOR. Maybe one or two times an error will pop up - but that's until the time series is built, and then the values will be given steadily.

 
Artyom Trishkin:
Did you see my answer? Have you tried it?
 
Vladimir Karputov:

If you use CopyBuffer in an indicator to get data from another indicator, you need:

  1. Reverse your indicator buffer so that the rightmost bar in the chart corresponds to index "0" in the indicator buffer.
  2. Thus, the "current bar" in the indicator "iMTF_AO.mq5" will be the RIGHT BAR in the chart, and it will correspond to index "0" in the indicator buffer "Buffer[]"
  3. And to get the "current bar" from the indicator (CopyBuffer(handle,0,shift,1,array)) "shift" parameter must be equal to "0".

If you don't want to flip the indicator buffer, do this (temporarily): AO(0) - to understand how to get from an INDICATOR THE VALUES OF OTHER INDICATORS. Maybe an error will pop up once or twice, but that's until the time series is built, and then the values will come out steadily.

1. My code has it, and it was there right away:

   ArraySetAsSeries(Buffer,true);
   int bars=Bars(NULL,PeriodForWork);
   datetime time_limit=GetTime(Symbol(),PeriodForWork,bars-1);
   int limit_p=GetBarShift(Symbol(),Period(),time_limit);
   if(rates_total<1) return(0);

2. this is how it is.

3. shift equals loop index i. And the loop goes from the beginning of historical data (rates_total-1) to the end (to the current data)

Another question is that it is necessary to calculate this data with respect to a non-native TF in order not to get data from missing bars. And it is necessary to determine before the cycle that the history from the desired TF is completely synchronized.

 
Artyom Trishkin:

1. My code has it, and it was there right away:

2. it is.

3. shift equals cycle index i. And the loop goes from the beginning of the historical data (rates_total-1) to the end (to the current data)

Another issue is that it is necessary to calculate this data in relation to a non-native timeframe in order not to get data from missing bars. And we should determine before the cycle that the history of the needed timeframe is completely synchronized.


Rework the loop of reference to the AO: put from "0" to some value (now from some value to zero). When the errors occur - compare at once: the number of calculated bars ("limit_p") and rates_total of the current indicator.


Added: and these lines erase all the efforts of the calculated "limit" (if we address a non-native timeframe):

   if(limit>1) 
     {
      limit=rates_total-1;
     }

Roughly speaking, at first (when referring to a non-native timeframe) "limit" was equal to 156, and below BACK! and "limit" became "154566666666".



 
Alexey Kozitsyn:
Have you tried synchronization? Also, the developers advise to keep the data of required TFs/symbols up to date through the timer.

No, I haven't tried it yet. About support of data relevance I saw, I remember - I know.

But initially it's necessary to exit from OnCalculate() if data on specified and current timeframe are not synchronized yet.

About current it is clear:

if(rates_total<1) return(0);

About given - it's necessary to check its Bars() - their number instead of rates_total.

I don't know about the limit - it can be checked on the current timeframe (as an example from another indicator):

   int limit=rates_total-prev_calculated;
   if(limit>1) {
      limit=rates_total-4;
      ArrayInitialize(BufferAoDN,EMPTY_VALUE);
      ArrayInitialize(BufferAoUP,EMPTY_VALUE);
      ArrayInitialize(BufferMacdDN,EMPTY_VALUE);
      ArrayInitialize(BufferMacdUP,EMPTY_VALUE);
      ArrayInitialize(BufferRsiDN,EMPTY_VALUE);
      ArrayInitialize(BufferRsiUP,EMPTY_VALUE);
      ArrayInitialize(BufferStochDN,EMPTY_VALUE);
      ArrayInitialize(BufferStochUP,EMPTY_VALUE);
      }

In this test indicator, we get data both from the current timeframe (it shows the calculations in OnCalculate()) and from the specified one - to get AO data from the specified timeframe.

I have not yet understood how to nicely calculate all required data by the number of bars - because the loop should begin with the bar corresponding to the time of the bar history with the very first existing data of either the current or specifiedfrom which bar it is less - that bar is used for starting the loop. In this case the limit should also be correctly calculated to detect the appearance of a new bar, which should lead to a complete recalculation or to the recalculation of the current bar only (depending on what happened - the opening of a new bar or history loading).

Maybe, I usually try to think everything at once, and I think a lot of unnecessary things...

 
Vladimir Karputov:


Rework loop calling to AO: put from "0" and to some value (now from some value to zero). When errors occur - compare at once: the number of calculated bars ("limit_p") and rates_total of the current indicator.


Added: and these lines erase all the efforts of the calculated "limit" (if we refer to a non-native timeframe):

Roughly speaking, at first (when referring to a non-native timeframe) "limit" was 156, and below BATCH! and "limit" has already become "154566666666"

Yes, I wrote about it at once that I messed up here in a hurry.

But I'm not going to change the loop - there is a quite complicated indicator in which everything is built on the calculation of the history from the beginning to the end - it's easier to recalculate the limits and to obtain the normal data than to rewrite the entire indicator - all of its logic.

 
Artyom Trishkin:

No, I haven't tried it yet. About support of data relevance I saw, I remember - I know.

But initially it's necessary to exit from OnCalculate() if data on specified and current timeframe are not synchronized yet.

About current one I understand:

It's not quite like that. At the initial loading of the terminal with the indicator you may receive not what you expect. During the day and if there are interruptions in connection, there may be errors too.

About the exit from OnCalculate(): The first request Bars() should be done at the initialization stage, then in OnCalculate() synchronization of the current and necessary TFs should be checked. If there is no synchronization, you get out.

 
Artyom Trishkin:

Yes, that's what I wrote right away that I messed up here in a hurry.

I will not change the loop, there is a quite complicated indicator, which is based on the calculation of history from the beginning to the end - it's easier to recalculate the limits and to get the normal data than to rewrite the whole indicator - all its logic.

Artem, what do you mean "from the beginning to the end"?

Do you think flipping all the arrays is the best way out?

Why

ArraySetAsSeries(Buffer,true);

if you're only copying one value?

When copying the TF other than the current one, it is better to pass the time of the needed bar to the CopyBuffer() function. Otherwise, it won't copy the bar you want.

 
Alexey Viktorov:

1. Artem, what do you mean by "from the beginning to the end"?

2. Do you think flipping all the arrays is the best way out?

3. Why

4. If you copy only 1 value?

In the CopyBuffer() function when copying is not the current timeframe, it is better to pass the time of the required bar. Otherwise, it won't copy the bar you want.

1. The beginning of the historical data is the very first bar in the history that has the shortest opening time, the end of the historical data is the current bar.

2. I copy from 4 to 5.

Well, because in Buffer[] data is written in loop from rates_total-1 to 0. If you don't do it as a timeseries, then the display will be on the chart backwards and forwards.

4. I copy one value at one moment of time, that corresponds to the data of bar i of a specified timeframe.

Look how laconic and easy it is to get the data of not the current timeframe in mql4, and it works successfully and everything works as planned. And how strange it is to receive indicator data in mql5, and they cannot be received in any way - there is always error 4806 if I pass the timeframe that does not correspond to the timeframe of the chart where the indicator works.

//+------------------------------------------------------------------+
double GetDataAO(string sy, int timeframe, int shift) {
   double array[1];
   ZeroMemory(array);
#ifdef __MQL4__
   array[0]=iAO(sy,timeframe,shift);
#else 
   ResetLastError();
   if(CopyBuffer(handle_ao,0,shift,1,array)==WRONG_VALUE) {
      Print(__FUNCTION__," > Error: ",GetLastError());
      return(0);
      }
#endif 
   return(array[0]);
}
//+------------------------------------------------------------------+

At the same time, the indicator handle is created in OnInit(), it corresponds to the current timeframe, from which the data is obtained:

handle_ao=iAO(symbol,periodForWork);

I.e., at any time no matter how we switch thef, the handle is created with the necessary (selected in settings)f. But the AO data can be obtained only if the selectedfunction in the settings coincides with the currentfunction. If they do not coincide, then it always returns zero from the function.

The question is: WHY?

 
Artyom Trishkin:

1. The beginning of historical data - the very first bar in the history, which has the shortest opening time, the end of historical data - the current bar.

2. I rewrite from four to five.

Well, because in Buffer[] data is written in loop from rates_total-1 to 0. If you don't do it as a timeseries, then the display will be on the chart backwards and forwards.

4. I copy one value at a time that corresponds to the data on bar i of a given timeframe.

Look how laconic and easy it is to obtain the data of the currentfactor in mql4; they are obtained successfully and everything works as planned. And how strange it is to receive indicator data in mql5, and they cannot be received in any way - there is always error 4806 if I pass the timeframe that does not correspond to the timeframe of the chart where the indicator is running in the function of receiving AO data.

At the same time, the indicator handle is created in OnInit(), it corresponds to the current timeframe, from which the data is obtained:

I.e., at any time no matter how we switch thef, the handle is created with the necessary (selected in settings)f. But the AO data can be obtained only if the selectedfunction in the settings coincides with the currentfunction. If they do not coincide, it always returns zero from the function.

The question is, WHY?

1. Just to clarify. Now I understand that we are talking about the same thing.

I understand it, but I don't agree that it is necessary to reverse arrays for this. Is it necessary to have one indicator for two terminals? It's almost like making a 2in1 scythe and an axe.

3. as I understand Buffer[] is used by the receiver in the CopyBuffer() function to get only 1 indicator value.

4. You have not paid attention to the main thing. The start of copying of indicator values should not be determined by the bar index, but by the time of the i-th bar.

int  CopyBuffer( 
   int       indicator_handle,     // handle индикатора 
   int       buffer_num,           // номер буфера индикатора 
   datetime  start_time,           // с какой даты 
   int       count,                // сколько копируем 
   double    buffer[]              // массив, куда будут скопированы данные 
   );
Reason: