Errors, bugs, questions - page 3027

 
Сергей Таболин:

Indicators are my MOST weak point ))))

But!

Either I don't understand anything at all, or you're a little wrong.

As far as I know, prev_calculated is a counter of uncalculated data. And once the incoming data is counted, that counter is reset... Like, that's it, guy, no more new data to calculate.... )))

And for what reason the indicator should completely recalculate in such a case - I don't know!

---------------

Lied a little ))))

It's not the indicators that are re-calculated, but the "indices" are recalculated to make them "look nice" on the history ;)

the counter is reset for reasons beyond the programmer's control, as if the indicator had been started for the first time!

I would not like my message to be lost in the middle of incomprehensible explanations, but it finally reached the developers.



We need to note the connection between the value returned by OnCalculate() and the second input parameter prev_calculated. When calling the function, the prev_calculated parameter contains a value returned by OnCalculate() on previous call. This allows for economical algorithms for calculating the custom indicator in order to avoid repeated calculations for those bars that haven't changed since the previous call of this function.

-this is from the documentation. A calc that doesn't work properly breaks the whole concept of economical calculations.
 
Andrey Dik:
The counter is reset for reasons beyond the programmer's control, as if the indicator was running for the first time!

I didn't want my message to get lost in the incomprehensible applause, but it did reach the esteemed developers.

Is it like this on every new bar? They're being reassured, aren't they?

If not every bar, there are different reasons for resetting the pre_calc.

 

Forum on trading, automated trading systems and trading strategy testing

Bugs, bugs, questions

Andrey Dik, 2021.05.27 13:53

i.e., the pre_calculated counter is zeroed as soon as the new timeframe bar appears. it means that the indicator is recalculated again as if it was launched the first time.

is such a construction familiar to you?

if (rates_total == prev_calculated) return rates_total;
  
int startInd = rates_total - prev_calculated;

for (int i = startInd; i >= 0; i--)
{
  //тут считаем индикатор, который обращается к другому индикатору на старшем ТФ
}

the problem is not in the EA logic (redrawing, not redrawing, underdrawing or whatever) but in the fact that prev_calculated is reset while nobody asked it to do that!

I think the problem is:

if (rates_total == prev_calculated) return rates_total;

You don't let the called indicator on another TF calculate every tick, and then you call it and the history is synchronised and the calculation from zero of that indicator


i have created a test. the called indicator counts everything and does not reset to prev_calculated == 0

I drew close in the indicator and unwind the event with a new bar and prev_calculated == 0 :

// tst.mq5

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 start;
   static datetime t = 0;
   if(t != time[rates_total-1])
   {
      t = time[rates_total-1];
      Print(MQLInfoString(MQL_PROGRAM_NAME), " New bar ", t);
   }
   
   if(prev_calculated == 0)
   {
      start = 0;
      ArrayInitialize(Buffer, EMPTY_VALUE);
      Print(MQLInfoString(MQL_PROGRAM_NAME), " prev_calculated == 0");
   }
   else start = prev_calculated - 1;


   for(int i = start; i < rates_total; i++)
   {
      Buffer[i] = close[i];
   }
//--- return value of prev_calculated for next call
   return(rates_total);
}

call this indicator (get the last 2 values of the buffer) and also draw close on your TF:

input ENUM_TIMEFRAMES TF = PERIOD_M5;
int OnInit()
{
//--- indicator buffers mapping
   SetIndexBuffer(0, Buffer, INDICATOR_DATA);
   ind_handle = iCustom(NULL, TF, "NewFolder\\tst");
//---
   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 start;
   static datetime t = 0;
   if(t != time[rates_total-1])
   {
      t = time[rates_total-1];
      Print(MQLInfoString(MQL_PROGRAM_NAME), " New bar ", t);
   }

   if(prev_calculated == 0)
   {
      start = 0;
      ArrayInitialize(Buffer, EMPTY_VALUE);
      Print(MQLInfoString(MQL_PROGRAM_NAME), " prev_calculated == 0");
   }
   else start = prev_calculated - 1;


   for(int i = start; i < rates_total; i++)
   {
      Buffer[i] = close[i];
   }
   double buf[];
   if(CopyBuffer(ind_handle, 0, 0, 2, buf) < 0) Print("Error CopyBuffer # ",GetLastError());
//--- return value of prev_calculated for next call
   return(rates_total);
}


ran the last indicator on M1 , log:

2021.05.27 21:48:34.196 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:48:00

2021.05.27 21:48:34.197 tst_tf (EURUSD,M1) tst_tf prev_calculated == 0

2021.05.27 21:48:34.197 tst_tf (EURUSD,M1) Error CopyBuffer # 4806

2021.05.27 21:48:34.197 tst (EURUSD,M5) tst New bar 2021.05.27 21:45:00

2021.05.27 21:48:34.197 tst (EURUSD,M5) tst prev_calculated == 0

2021.05.27 21:49:01.636 tst_tf (EURUSD,M1) tst_tf new bar 2021.05.27 21:49:00

2021.05.27 21:50:00.149 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:50:00

2021.05.27 21:50:00.149 tst_tf (EURUSD,M5) tst New bar 2021.05.27 21:50:00

2021.05.27 21:51:01.789 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:51:00

2021.05.27 21:52:02.832 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:52:00

2021.05.27 21:53:00.920 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:53:00

2021.05.27 21:54:02.778 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:54:00

2021.05.27 21:55:00.308 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:55:00

2021.05.27 21:55:00.308 tst_tf (EURUSD,M5) tst New bar 2021.05.27 21:55:00

2021.05.27 21:56:00.118 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:56:00

2021.05.27 21:57:00.419 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:57:00

 
Andrey Khatimlianskii:

Is it like this at every new bar? Are they over-insuring or something...

If not on every bar, there are different reasons for resetting pre_calc.

exactly on every new bar of the major TF.

For example, if the indicator works on M1 and accesses the indicator on M5, then every 5 minutes the indicator will be completely re-calculated.

 
Igor Makanu:

I think the problem is:

You don't let the called indicator on another TF calculate every tick and then you call it and there is a history sync and calculation from zero of that indicator


i have created a test. the called indicator counts everything and does not reset to prev_calculated == 0

I drew close in the indicator and undid the event of a new bar and prev_calculated == 0 :

call this indicator (get the last 2 values of the buffer) and also draw close on your TF:

I check synchronization of data on the requested higher TF (M5) and readiness of the indicator on it, if it's not ready, then exit.

As a result, the indicator works only once at M1 bar open, and not at every tick:


//проверка готовности данных и индикатора на другом TF
if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))
{
  if (iBars (Symbol (), tf) != BarsCalculated (handleFr)) return 0;
}
else return 0;

//проверка на наличие нового бара
if (rates_total == prev_calculated) return rates_total;

I hope the developers will listen to my pleas.

 
Andrey Dik:

I check the data synchronisation on the requested higher TF (M5) and the readiness of the indicator on it, if it is not ready, then exit.

As a result, the indicator works only once at the opening of M1 bar, and not at every tick:


I hope the developers will listen to my pleas.

this should not work correctly in indicators:

if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))

if i am not mistaken, in the help there is a walkthrough of the script for paging data for all TFs and there should be a warning that historical data cannot be requested from the indicator due to the fact that the indicator works asynchronously

and it is recommended to use BarsCalculated() once after you bind the handle


UPD: script for history paging and explanation why it doesn't work in indicators:https://www.mql5.com/ru/docs/series/timeseries_access

 
Andrey Dik:

I check the data synchronisation on the requested higher TF (M5) and the readiness of the indicator on it, if it is not ready, then exit.

As a result, the indicator works only once at the opening of M1 bar, and not at every tick:


Do I really have to use my custom pre-calc? I hope the developers will listen to my pleas.

What for is such a check?

//проверка готовности данных и индикатора на другом TF
if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))
{
  if (iBars (Symbol (), tf) != BarsCalculated (handleFr)) return 0;
}
else return 0;

It would be much simpler to write return 0; without condition and that's it.

At each new bar, the condition will be fulfilled and all the bars will be recalculated regardless of synchronization. You have written an ill-considered code and pretend that it is a terminal bug...

 
A compilation error:
union X1 { //(1) нормально
        char x11[INT_MAX/2+1];
};
union X2 { //(2) Error: 'X2' - struct is too large
        char x21[INT_MAX/2+1];
        char x22[INT_MAX/2+1];
};
What is the fundamental difference between (1) and (2) ?
 
Union with a single field is a strange thing.
 
Alexey Viktorov:

What's the point of such a check?

It would be easier to write return 0; without condition and that's it...

The condition will be fulfilled at every new bar and all the bars will be recalculated regardless of synchronization. You have written a rash code and passed it off as a terminal bug...

think again.

Reason: