where am I wrong, so that I don't crash my pc? - page 2

 

I solved at least one problem!

The indicator CaVol 'starts' with this way:

...
extern string   _1 = "modif. calculation"; // => 20
extern int      Percent = 50;              // => 1
extern double   Coeff   = 1.3;             // => should stay 1.3
extern double ...
...
int ActTF;
int OnInit() {
   ActTF = _Period;  // hi, whroeder :)
   Print(__LINE__," ",WindowExpertName());
   ...
}
int OnCalculate(...) {
   if ( ActTF != _Period  ) { 
      Print(__LINE__," ",WindowExpertName(),"  ",ActTF," != ",_Period); // never was touched!!
      OnInit(); 
      ReInit = true;
      return(0);         
   }
   ...

The problem with the recursive initialization of a new instance of the indicator CaVol happens if CallingCaVol calls CaVol that way:

int OnCalculate(...) {

   int idx = MathRand()%10; // => 0..9
   
   double val1 = iCustom(_Symbol,_Period, "CaVol", 20, 1.0,   idx + 0, 0 ),   // buffer  0.. 9
          val2 = iCustom(_Symbol,_Period, "CaVol", 20, 1.0,   idx + 10, 0 ),  // buffer 10..19
          val3 = iCustom(_Symbol,_Period, "CaVol", 20, 1.0,   idx + 20, 0 );  // buffer 20..29
   ...
}

I forgot the informative 'first parameter' and I could not imagine that this leads to that infinite loop of initializations :(

As soon as I call CaVol That way:

int OnCalculate(...) {

   int idx = MathRand()%10; // => 0..9
   
   double val1 = iCustom(_Symbol,_Period, "CaVol", "", 20, 1.0,   idx + 0, 0 ),   // buffer  0.. 9
          val2 = iCustom(_Symbol,_Period, "CaVol", "", 20, 1.0,   idx + 10, 0 ),  // buffer 10..19
          val3 = iCustom(_Symbol,_Period, "CaVol", "", 20, 1.0,   idx + 20, 0 );  // buffer 20..29
   ...
}

everything is fine - the calculation is correct as the values are the same as if CaVol was started directly on the chart!. So far so good - if I were able to understand that!

CaVol("",20,1.0, /*now use defaults*/  idxBuffer, shift); is correct but

CaVol(20,1.0, /*now use defaults*/  idxBuffer, shift); fails in an totally surprising way - I would expect false values but not initialization until the pc crashes!!

The first string parameter becomes 20 - with no effect on any further calculation.

The second parameter becomes 1 which is within the working tolerance, even though it is not intended, that should lead to different values

The third parameter should be set to its default value like all the others!

So why the hell do I get that stupid loop until the pc dies?

Anyway it could be a nice and simple feature to tease users ;)


But I still don't understand the other problem why is printed in the expert log:

2017.06.09 12:39:27.357 CaVol EURUSD,H1: 228 CaVol

despite CaVol was called by CallingCaVol?

As the reference shows:

"The name of the executed Expert Advisor, script, custom indicator, or library, depending on the MQL4 program, from which this function has been called."

But this is definitely not the case!

 
Carl Schreiber:

CaVol(20,1.0, /*now use defaults*/  idxBuffer, shift); fails in an totally surprising way - I would expect false values but not initialization until the pc crashes!!

The first string parameter becomes 20 - with no effect on any further calculation.

The second parameter becomes 1 which is within the working tolerance, even though it is not intended, that should lead to different values

The third parameter should be set to its default value like all the others!

So why the hell do I get that stupid loop until the pc dies?

Anyway it could be a nice and simple feature to tease users ;)

Yeah it's why I wrote :

Right. Though I didn't check with 1090. But normal behavior  is to use default parameters when they are not set explicitly. You can provide 0, 1, or x parameters. Of course you can't "jump" a parameter.


But I still don't understand the other problem why is printed in the expert log:

despite CaVol was called by CallingCaVol?

so what ?

As the reference shows:

"The name of the executed Expert Advisor, script, custom indicator, or library, depending on the MQL4 program, from which this function has been called."

But this is definitely not the case!

Read it again. Of course it's the case, the function WindowExpertName() is called by CaVol, not by CallingCaVol.

CallingCaVol calling CaVol doesn't matter.

 

1) "Of course you can't "jump" a parameter."

Well if I miss to enter a parameter the next parameters are shifted 'upwards'. This jump of parameter simply does not take place, they are just shifted - no?

If the 'new' parameter are in an allowed range than only the values of the indicator should be different, but here it causes an infinite loop of creating new instances of this indicators each time iCustom calls CaVol and that is really a different quality - no?

2) "CallingCaVol calling CaVol doesn't matter."

Ah, I got it!

While coding Classes I wanted to know where I am and there __FILE__ doesn't make sense but WindowExpertName() does the trick - so I thought even in this case I can get the 'most outside' program. Even the name of WindowExpertName suggest this idea as CallingCaVol is running in the Chart-Window not CaVol!!

Ok, Alain, how can an indicator like CaVol know, whether it running directly on the chart (so it plays all its gimmicks) or it is called by another ea, indi, ... and it should provide only the values in the buffer?

 
Carl Schreiber:

1) "Of course you can't "jump" a parameter."

Well if I miss to enter a parameter the next parameters are shifted 'upwards'. This jump of parameter simply does not take place, they are just shifted - no?

If the 'new' parameter are in an allowed range than only the values of the indicator should be different, but here it causes an infinite loop of creating new instances of this indicators each time iCustom calls CaVol and that is really a different quality - no?

There is no infinite loop (at least not in the first sense of this term). Usually when you use iCustom() the indicator is called (OnInit(), OnCalculate()...) and it remains in memory, in the background. If you call the same indicator, with same parameters (same symbol,period), from elsewhere it will use this instance which is already in memory. It's recognized by it's signature (I don't have any details about how it's implemented).

If you missed a parameter like you did, certainly when it's a string, and your iCustom use an int or double, MT4 is not able to recognize the signature, so each time it call a new instance of the indicator, which of course soon or later will lead to memory issue.

2) "CallingCaVol calling CaVol doesn't matter."

Ah, I got it!

While coding Classes I wanted to know where I am and there __FILE__ doesn't make sense but WindowExpertName() does the trick - so I thought even in this case I can get the 'most outside' program.

Ok, Alain, how can an indicator like CaVol know, whether it running directly on the chart (so it plays all its gimmicks) or it is called by another ea, indi, ... and it should provide only the values in the buffer?

The simplest is just to use an input parameter. The last one after your significant parameters, set it to false by default. When you call your indicator from an external source, just set your last iCustom parameter to true.

 
Carl Schreiber:
int OnInit() {
   ActTF = _Period;  // hi, whroeder :)
}
int OnCalculate(...) {
   if ( ActTF != _Period  ) 


CaVol(20,1.0, /*now use defaults*/  idxBuffer, shift); fails in an totally surprising way - I would expect false values but not initialization until the pc crashes!!
  1. Your if statement will never be true. Change the TF, the deinit/init runs and sets them equal again.
  2. Agreed, it's unexpected. That's why I write them pedantically as in Detailed explanation of iCustom - MQL4 forum I'm thinking the int being interpreted as a string results in some random string that varies from call to call, thus opening a myriad of them.
 
Alain Verleyen:

The simplest is just to use an input parameter. The last one after your significant parameters, set it to false by default. When you call your indicator from an external source, just set your last iCustom parameter to true.

Hmm - this should be something an indicator have to find out itself! There are so many predefined variables and this must be done 'manually' :(

"...so each time it call a new instance of the indicator, which of course soon or later will lead to memory issue."

As I said a nice and simple feature to tease the user - and if you make that a bit in a sophisticated way, e.g. at random speed, you can drive them nuts until they found out why their pc crashes!

 
Carl Schreiber: Ok, Alain, how can an indicator like CaVol know, whether it running directly on the chart (so it plays all its gimmicks) or it is called by another ea, indi, ... and it should provide only the values in the buffer?
  1. It shouldn't care, just do what it is supposed to do.
  2. If you insist, it should be told via a parameter.
 
whroeder1:
  1. It shouldn't care, just do what it is supposed to do.
  2. If you insist, it should be told via a parameter.

It matters :(

The problem is that if CaVol is called by another indicator some of its graphical things are shown on the chart some don't :(

So e.g.the indicator window is not shown but OBJ_RECTANGLE_LABEL are shown and OBJPROP_TEXT aren't ... kind of a mess!

"If you insist, it should be told via a parameter." For what do I have a computer if I have to things 'manually' that could be done automatically!

 
Carl Schreiber:

Hmm - this should be something an indicator have to find out itself! There are so many predefined variables and this must be done 'manually' :(

You always have to code it anyway, your graphical objects will not decide alone to hide themselves ;-) Try this function :

//+--------------------------------------------------------------------------+
//| Detect if current indicator is running directly on a chart or by iCustom |
//+--------------------------------------------------------------------------+
bool IsIndicatorRunningFromICustom()
  {
//--- detect if running from an EA
   if(!EventChartCustom(0,USHORT_MAX,0,0,"AUTO_CHECK"))
     {
      //--- An indicator running in background can't use '0' (current chart) 
      //--- to send custom event, result is error 4051
      if(GetLastError()==ERR_INVALID_FUNCTION_PARAMVALUE)
         return(true);
     }
//---
   return(false);
  }

"...so each time it call a new instance of the indicator, which of course soon or later will lead to memory issue."

As I said a nice and simple feature to tease the user - and if you make that a bit in a sophisticated way, e.g. at random speed, you can drive them nuts until they found out why their pc crashes!

I doubt that will crash a PC. It will crash MT4, maybe...

Let's see I just started a test to verify :-D

 
Alain Verleyen:

I doubt that will crash a PC. It will crash MT4, maybe...

If the pc(!) is running out of memory you'll get a hint by the OS (in my case Win 7) not mt4 to restart the pc immediately - that's a crash for me!