Download MetaTrader 5

Strange Behaviour of a working Indicator .. What to do? How to recognize?

To add comments, please log in or register
Carl Schreiber
7289
Carl Schreiber  

I created an OOP-base for Indicators and EA, so that I don't have to use iCustom!

What you see is a very simple Mom: Buff2[b+1] = close[b+1] - close[b+1+PER];

Buff1 receives the values that are calculated by the OOP-base.

As you can see, the OOP-calculated values are pretty much the same as the directly calculated values:


The solid rad line are the values of the OOP-base, the yellow dotted line the directly calculated values = perfect match as of the beginning of the chart.

NOW!

Now I dare to develop another indicator (Atr) the same way using the OOP-base, of course I don't use the one of Mom!

Well by what ever reason this indicator need 5 minutes for its installation - I haven't started to find out why, it should be a lot faster!!

Installation time here means the time for OnInit() and the first run through the bars from the oldest to the last bar in OnCalculate()

Anyway this causes the (untouched Mom) to appear like that:


The directly calculated values are the same, either newly calculated or just not changed,
BUT
all the values in the OOP-base buffer became zero. As soon as I open the setup-window and press OK I immediately get the first picture again.

Once again:

  1. I did not touch (modif, compile,..) the mom-indicator.
  2. If the installation time of the other indicator (atr) is faster it does not happen (acc to my experience).
  3. Both indicators use the same OOP-base, but of course each creates its own instance of it!

My questions are:

  1. Is there a way for the mom-indicator to recognize by a system variable or function that the previous values are corrupted (I would hate the idea to check on every tick each bar!!)
  2. Does anybody know, why this happens?
  3. .. and why the directly coded mom (Buff2) is ok, while the OOP-base values 'disappear'?

This is the code snippet of the Mom-indicator:

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[])
  {
//---
   TC = TimeCurrent();
   bool isNewbar = false;
   static datetime actOpn;
   int q,b,lim = getBars3(rates_total,prev_calculated,PER);
   if (actOpn != time[0]) { isNewbar=true; actOpn=time[0]; }
   static datetime begFlat=0,endFlat=0,frstBar=0;
   if (frstBar==0) frstBar=time[b];
   b = lim;

   while(b-->0) {
      CI_Mom.calc( time[b] );
      if ( isNewbar && prev_calculated > 20 ) {
         Buff1[b] = CI_Mom.getValA(1);
         Buff2[b+1] = close[b+1] - close[b+1+PER];
      } else {
         Buff1[b+1] = CI_Mom.getValA(1);
         Buff2[b+1] = close[b+1] - close[b+1+PER];
      }
   }
   b=0;
   CI_Mom.calc( TimeCurrent() );
   Buff1[0] = CI_Mom.getValA(0);
   Buff2[0] = close[0] - close[0+PER];
//--- return value of prev_calculated for next call
   return(rates_total);
}

And this is the Atr-Indicator:

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[])
  {
//---
   bool isNewbar = false;
   static datetime actOpn;
   int q,b,lim = getBars3(rates_total,prev_calculated,PER);
   if (actOpn != time[0]) { isNewbar=true; actOpn=time[0]; }
   static datetime begFlat=0,endFlat=0,frstBar=0;
   if (frstBar==0) frstBar=time[b];
   b = lim;
   if (T3==0) { T3 =  TimeCurrent(); Comment(EaName," Ini has started ",TimeToString(T1,TIME_SECONDS),"  and ended: ",TimeToString(T2,TIME_SECONDS),"  OnCalc started: ",TimeToString(T3,TIME_SECONDS)); }

   while(b-->0) {
         CI_Atr.calc( time[b] );
         if ( isNewbar && prev_calculated > 20 ) {
            BuffAtrRaw[b]  =  CI_Atr.getValAtrRaw(1);
            BuffATR[b]     =  CI_Atr.getValAtrEma(1); 
         } else {
            BuffAtrRaw[b+1] =  CI_Atr.getValAtrRaw(1);
            BuffATR[b+1]    =  CI_Atr.getValAtrEma(1);
         }
      }
   }
   b=0;
   CI_Atr.calc( TimeCurrent() );
   BuffAtrRaw[0] =  CI_Atr.getValAtrRaw(0);
   BuffATR[0]    =  CI_Atr.getValAtrEma(0); 

   if (T4==0) T4 =  TimeCurrent();

   Comment("actual:   ",TimeToString(TimeCurrent(),TIME_SECONDS),"  newBar: ",(string)isNewbar,"\nfirstBar: ",TimeToString(time[rates_total-1]),"  ",ArraySize(BuffAtrRaw),"  rates_total: ",rates_total,
           "\n OnInit Beg: ",TimeToString(T1,TIME_SECONDS),"   OnInit End: ",TimeToString(T2,TIME_SECONDS),"   OnCalc Beg: ",TimeToString(T3,TIME_SECONDS),"   OnCalc End: ",TimeToString(T4,TIME_SECONDS)
   );
//--- return value of prev_calculated for next call
   return(rates_total);
}

Thanks in advance,

Calli

whroeder1
15902
whroeder1  
Carl Schreiber: Well by what ever reason this indicator need 5 minutes for its installation - I haven't started to find out why, it should be a lot faster!!

Installation time here means the time for OnInit() and the first run through the bars from the oldest to the last bar in OnCalculate()

I'm seeing the same thing with some of my indicators (on build 1090.)

The symptom appears to be the last ones attached to the chart (6/7 & 7/7.) OnInit is called but neither OnCalculate nor OnTimer are being called. It's semi-random, on start up and on compilation. There is nothing in the journal (except indicator pair: initialized.)

Since the functions aren't being called, your code is irrelevant. Refresh doesn't change anything. Changing timeframe appears to fix the problem.

Alain Verleyen
Moderator
33290
Alain Verleyen  
Carl Schreiber:
...
A bug either in your code, or in mql4/MT4 (or both but it's unlikely). Impossible to say without the full source code. Need to be investigated.
Carl Schreiber
7289
Carl Schreiber  

I can constantly repeat this 'feature' if I just compile e.g. the mom-indicator: the red line (OOP) is flat (=0.0) the yellow line is correct.

If I open the setup-window just to press ok - the red line again matches the yellow one perfectly.

Can it be that the problem is caused by OOP as in DeInit() all objects and instances are deleted and due the slower process for OOP than what is 'accepted' for indicators - this is just bypassed or this part 'lose' in the thread race?

I tried to use a global bool var, which is set to false in OnInit - and failed (not working):

bool PrevCalc;
void OnInit() {
   PrevCalc = false;
   ...
}

int OnCalculate(..) {
   if ( !PrevCalc ) { PrevCalc = true; return(0); } // re-calc. all
   ...
}


I checked the pointer at the end of OnInit():

2017.08.03 15:08:05.308    Test_OOP_Mom EURUSD,H1: Test_OOP_Mom v. 2017.08.03 15:07:56 CI_Mom: POINTER_DYNAMIC

Alain Verleyen
Moderator
33290
Alain Verleyen  
Carl Schreiber:

I can constantly repeat this 'feature' if I just compile e.g. the mom-indicator: the red line (OOP) is flat (=0.0) the yellow line is correct.

If I open the setup-window just to press ok - the red line again matches the yellow one perfectly.

Can it be that the problem is caused by OOP as in DeInit() all objects and instances are deleted and due the slower process for OOP than what is 'accepted' for indicators - this is just bypassed or this part 'lose' in the thread race?

I tried to use a global bool var, which is set to false in OnInit - and failed (not working):


I checked the pointer at the end of OnInit():

2017.08.03 15:08:05.308    Test_OOP_Mom EURUSD,H1: Test_OOP_Mom v. 2017.08.03 15:07:56 CI_Mom: POINTER_DYNAMIC

If the problem appears only when DeInit() is called then you have a solid clue.
Carl Schreiber
7289
Carl Schreiber  

DeInit() is called automatically - no?

But at the end of the last OnInit() the (new) pointers are valid!!

Alain Verleyen
Moderator
33290
Alain Verleyen  
Carl Schreiber:

DeInit() is called automatically - no?

Yes of course.
Carl Schreiber
7289
Carl Schreiber  
Alain Verleyen:
Yes of course.
Ok, so the objects are (re-) created in (my) OnInit() - it should be enough.
whroeder1
15902
whroeder1  
My code doesn't use any pointers, I just don't see the print statement inside OnCalculate/OnTick.
Carl Schreiber
7289
Carl Schreiber  
I entered the Print() at the end of OnInit() after you said that only OnInit() is called in order to check whether the pointers are valid.
Carl Schreiber
7289
Carl Schreiber  

Things are getting even more mysterious!

While Mom and Atr seem to influence each other - one destroys the other - the sma indicator built the same way works perfect with CI_Mom:

// Sma
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[])
  {
//---
   bool isNewbar = false;
   static datetime actOpn;
   int q,b,lim = getBars3(rates_total,prev_calculated,PER);
   if (actOpn != time[0]) { isNewbar=true; actOpn=time[0]; }
   static datetime begFlat=0,endFlat=0,frstBar=0;
   if (frstBar==0) frstBar=time[b];
   b = lim;

   while(b-->0) {
      CI_Sma.calc( time[b] );
      if ( isNewbar && prev_calculated > 20 ) {
         Buff1[b] = CI_Sma.getValA(1);
      } else {
         Buff1[b+1] = CI_Sma.getValA(1);
      }
      Buff2[b] = iMA(_Symbol,_Period,PER,0,MODE_SMA,PRICE_CLOSE,b);
   }
   b=0;
   CI_Sma.calc( TimeCurrent() );
   Buff1[0] = CI_Sma.getValA(0);
   Buff2[0] = iMA(_Symbol,_Period,PER,0,MODE_SMA,PRICE_CLOSE,0);
//--- return value of prev_calculated for next call
   return(rates_total);
}

Both, Sma and Mom, show a perfect match of the OOP-values and the iMA()-values.

Meanwhile I added a buffer to Mom to show the memory used:

Buff3[0] = (double)TerminalInfoInteger(TERMINAL_MEMORY_USED);

It shows 959.0000 no matter whether either CI_Sma or CI_Atr is running beside CI_Mom.

May be you'll say: Ahhh, CI_Atr cause the problem. But all three CI_... are created the same way:

  1. Save a working indicator - like CI_Mom - under a new name: CI_Atr.
  2. Add some arrays if needed.
  3. Modify the relevant lines in the calc(..) method.
  4. Test it on the chart.

Now CI_Mom shows the same mem. use of 959 - for both CI_Sma and CI_Atr (I have 8GB Ram available, total use ~ 5.8GB).

12
To add comments, please log in or register