Discussion of article "Using Assertions in MQL5 Programs" - page 3

 
Explanation. At the moment of writing this article in MQL5 there was no mechanism for the program to perform an emergency stop. As an alternative, the runtime error was triggered, which guaranteed the program to crash.
That's not true. An EA can be stopped by ExpertRemove(), an indicator by ChartIndicatorDelete(), an it's trivial for a script.
 
Alain Verleyen:
That's not true. An EA can be stopped by ExpertRemove(), an indicator by ChartIndicatorDelete(), an it's trivial for a script.

Please, show to me an example, how to exit with ExpertRemove() in a cicle.

For example, we have this code:

#property version   "1.00"
#property strict

int OnInit()
  {
   for(int i = 0; i < 100; i++)
   {
      if(i == 2)
      {
         ExpertRemove();
      }
      Print(i);
   }
      
//---
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {

      
  }

void OnTick()
  {
//---
   
  }

We need exit if i == 2, and all other steps not must running. In journal we must see only "0" and "1". How we can do it with this function?

Right now ExpertRemove() not stop EA at needed moment, all steps will be running, and after this EA will be stopped. But this is wrong for Assertion mechanism, we must stop EA momentally. And yes, we cannot use just "break", because we need universal macro or function for any part of any EA's.


About indicators - please show to me universal mechanism to definition ShortName of indicators. Because without this mechanism we cannot use this function for Assertions. Yes, we can define ShortName in our concrete indictor (for example with global variable, like a lot people do it, even if it is bad practice), but we no have for example universal function "GetShortName()". So we cannot make universal mechanism (I mean some macro or function for absolutly any indicators, where we can add just one line "assert(...)") with ChartIndicatorDelete().


And please show to me "trivial" variant for Sripts for any parts of code. It must be one (!) function or macro for any part of Script:

1) For cicles
2) For functions with any return type
3) For functions without return type (void).

So we must just add one line "assert(...)" in any part of Sript, like this:

#property version   "1.00"
#property strict

void OnStart()
  {
   assert(...);

  }

double SomeDouble()
  {
   assert(...);
   return 0.0;
  }

color SomeColor()
  {
   assert(...);
   return clrNONE;
  }

string SomeString()
  {
   assert(...);
   return "";
  }

void SomeVoid()
  {
   assert(...);
   return;
  }

void SomeCicle()
  {
   while(!IsStopped())
     {
      assert(...);
     }
  }

P.S. sorry for my bad English.

 

Or other example of EA with ExpertRemove(), not with cicle :)

For example, we must stop app if volume is bigger than we need (it just example, in real situation we should handle this situation differently):

#property version   "1.00"
#property strict

int OnInit()
  {
   OpenTrade();
//---
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {

      
  }

void OnTick()
  {
//---
   
  }
bool OpenTrade()
{
   double volume = GetVolume();
   
   if(volume > 1)
   {
      Print("Volume > 1, stop EA!");
      ExpertRemove();
   }
   
   Print("Opening position ...");
   
   return true;
}

double GetVolume()
{
   return 999.0;
}

We must stop EA momentally at needed place of code (in this is sense of assertions). But ExpertRemove() in this case not correct variant, we have:

2015.12.06 10:53:22.253    Test EURUSD,H1: Volume > 1, stop EA!
2015.12.06 10:53:22.253    Test EURUSD,H1: ExpertRemove function called
2015.12.06 10:53:22.253    Test EURUSD,H1: Opening position ...


So, please show to me how to use ExpertRemove() function (without return, break etc, it must be universally for any part of code) for this ceil.

 
Sergey Eremin:

Please, show to me an example, how to exit with ExpertRemove() in a cicle.

For example, we have this code:

We need exit if i == 2, and all other steps not must running. In journal we must see only "0" and "1". How we can do it with this function?

Right now ExpertRemove() not stop EA at needed moment, all steps will be running, and after this EA will be stopped. But this is wrong for Assertion mechanism, we must stop EA momentally. And yes, we cannot use just "break", because we need universal macro or function for any part of any EA's.

You don't have to use ExpertRemove() in OnInit(), just use return(INIT_FAILED);

int OnInit()
  {
//---
    ...

         if(somethign wrong)
           {
            //ExpertRemove();         
            return(INIT_FAILED);    //--- No need to use ExpertRemove() in OnInit()
           }
    ...
  }

in other part of the code, just return :

            ExpertRemove();
            return;           //--- Just return to finish the current event handler

or

            ExpertRemove();
            return(x);        //--- Just return to finish the current event handler

About indicators - please show to me universal mechanism to definition ShortName of indicators. Because without this mechanism we cannot use this function for Assertions. Yes, we can define ShortName in our concrete indictor (for example with global variable, like a lot people do it, even if it is bad practice), but we no have for example universal function "GetShortName()". So we cannot make universal mechanism (I mean some macro or function for absolutly any indicators, where we can add just one line "assert(...)") with ChartIndicatorDelete().

What's the problem ? You are working on your indicator, it's your code, so you know the short name.

My post was to say you are not right saying there is no way to terminate a program immediately. It's to you to find solution for your Assertion project.

This is absolutely not a bad practice to use global variable in an indicator. Of course if you want to create your self new limitation with such assertion "it is bad practice", you will find a lot of impossible things.

And please show to me "trivial" variant for Sripts for any parts of code. It must be one (!) function or macro for any part of Script:

1) For cicles
2) For functions with any return type
3) For functions without return type (void).

So we must just add one line "assert(...)" in any part of Sript, like this:

Same as for EA.

Files:
 
Alain Verleyen:

My post was to say you are not right saying there is no way to terminate a program immediately. It's to you to find solution for your Assertion project. 

This is absolutely not a bad practice to use global variable in an indicator. Of course if you want to create your self new limitation with such assertion "it is bad practice", you will find a lot of impossible things.

Ok, I understood you. Thanks, you're right.

 

But in my article I mean solutions for Assertions: universally mechamism of stopping MQL4/5 apps in any place of code (include OnInit and cicles). Just add one line in any part and done. Like it works in any Assertions mechanism in many pragramming languages ;)

Yes, your variants correct. But not for my vision of Assertions, because it's not universal solution for any part of any code. 

 

Thank you for your example of EA. 

 
Sergey Eremin:

Ok, I understood you. Thanks, you're right.

 

But in my article I mean solutions for Assertions: universally mechamism of stopping MQL4/5 apps in any place of code (include OnInit and cicles). Just add one line in any part and done. Like it works in any Assertions mechanism in many pragramming languages ;)

Yes, your variants correct. But not for my vision of Assertions, because it's not universal solution for any part of any code. 

 

Thank you for your example of EA. 

I know what you want to do, and it's perfectly doable, you just have to generalize to code I provided.

By analysing the calling context in your macro(s), detecting if it's an EA or an indicator, and parsing __FUNCSIG__.

It's up to you to make it an universal mechanism.

 
Alain Verleyen:

I know what you want to do, and it's perfectly doable, you just have to generalize to code I provided.

By analysing the calling context in your macro(s), detecting if it's an EA or an indicator, and parsing __FUNCSIG__.

It's up to you to make it an universal mechanism.

Yes, firstly I thought about such things, but eventually I made it as we see in article :)

Thank you for your comments! 

 

If someone is going to use this code, keep in mind this point: the following script

   if(true)
      assert(1==1, "")
   else
      Print("Never executed");

leads to the "Never executed" message from the else branch.

To be able to use assert correctly, you should correct it, for example, in this form:

#define  assert(condition, message) \
       do if(!(condition)) \
        { \
         string fullMessage= \
                            #condition+", " \
                            +__FILE__+", " \
                            +__FUNCSIG__+", " \
                            +"line: "+(string)__LINE__ \
                            +(message=="" ? "" : ", "+message); \
         \
         Alert("Assertion failed! "+fullMessage); \
         double x[]; \
         ArrayResize(x, 0); \
         x[1] = 0.0; \
        } while(false)
#else
#define  assert(condition, message) 
#endif

(the macro in the #else branch is also corrected : it returns an empty string (instead of ";").

In this variant, you should put ";" after assert(...)