Download MetaTrader 5

Discussion of article "Using Assertions in MQL5 Programs"

To add comments, please log in or register
MetaQuotes Software Corp.
Moderator
182445
MetaQuotes Software Corp. 2015.11.24 13:28 

New article Using Assertions in MQL5 Programs has been published:

This article covers the use of assertions in MQL5 language. It provides two examples of the assertion mechanism and some general guidance for implementing assertions.

Assertion is a special construction that enables checking arbitrary assumptions in the program's arbitrary places. They are typically embodied in the form of a code (mostly as a separate function or macro). This code checks a true value of a certain expression. If it appears to be false, then a relevant message is displayed, and the program is stopped, given the implementation provides for it. Accordingly, if the expression is true, it implies that everything operates as intended - the assumption is met. Otherwise, you can be certain, that the program has located errors and is clearly notifying about it.

For example, if it's expected that a certain value X within the program under no circumstance should be less than zero, then the following statement can be made: "I confirm that a value of X exceeds or equals zero". If X happens to be less than zero, then a relevant message will be displayed, and a programmer will be able to adjust the program.

Assertions are particularly useful in big projects, where their component parts may be reused or modified with time.

Assertions should cover only those situations that shouldn't occur during the program's regular operation. As a rule, assertions can be applied only at the program's development and debugging stages, i.e. they shouldn't be present in the final version. All assertions must be removed during the final version's compilation. This is usually achieved through conditional compilation.

Fig. 1. Example of an assertion

Fig. 1. Example of an assertion

Author: Sergey Eremin

Alain Verleyen
Moderator
31137
Alain Verleyen 2015.12.05 20:23  
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.
Sergey Eremin
4393
Sergey Eremin 2015.12.06 08:09  
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.

Sergey Eremin
4393
Sergey Eremin 2015.12.06 08:58  

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.

Alain Verleyen
Moderator
31137
Alain Verleyen 2015.12.06 11:34  
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:
Sergey Eremin
4393
Sergey Eremin 2015.12.06 12:30  
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. 

Alain Verleyen
Moderator
31137
Alain Verleyen 2015.12.06 13:20  
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.

Sergey Eremin
4393
Sergey Eremin 2015.12.06 13:36  
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! 

To add comments, please log in or register