Download MetaTrader 5

Breakpoints in Tester: It's Possible!

15 August 2007, 16:00
Christo Tsvetanov
7
3 606

Introduction

The only thing I miss in MQL4 is a normal debugger for Expert Advisors. All human beings have human feelings, so we make mistakes. At normal programming, we set breakpoints, launch the program, and then, when execution reaches a breakpoint, it will be stopped. So we can have a look into the contents of variables exercising us.

Displaying of debugging data is now possible due to such functions as Print, Comment, etc. But we sometimes may want to stop the program temporarily in certain places at a certain moment in order to review the situation. There are some finer points here. The program is usually launched to trade on a demo account or on a real account. This means that we will only be able to see the results in several months… Thus, the debug mode is reasonable only in the test mode of Expert Advisors (in Tester).


How It Works

Since a "Visual Test Mode" appeared in the Tester, it has become possible to track our EA's responses during quick passing of the program in Tester. If we want to stop execution temporarily, we can press "Pause" on the keyboard or click with the mouse button on the button of the same name in Tester toolbar. The developers of the terminal provide a library named WinUser32.mqh that contains some very interesting functions. One of them is keybd_event. It allows us to press any keys we want.

The idea was tossed up then – we can write a function that would press pause programmatically and print the necessary debugging information. Since our Expert Advisor will use DLL, we should first enable it for the EA. Press Ctrl+O and select/deselect check boxes:

Then we have to declare the using of WinUser32 somewhere at the beginning of the code:

#include <WinUser32.mqh>

This action is followed by declaration of function BreakPoint itself. There are some finer points here, but the simplest realization assumes no passed/returned parameters:

void BreakPoint()

The function must trigger only in the visual testing mode, so we will insert a check: If the Tester is not in the visual testing mode, we leave it:

if (!IsVisualMode()) return(0);

Then we will visualize some data. To my opinion, the most descriptive would be to use Comment(). Suppose we need only Bid and Ask.

string Comm="";
Comm=Comm+"Bid="+Bid+"\n";
Comm=Comm+"Ask="+Ask+"\n";
   
Comment(Comm);

The “\n” here means that data following after will be shown in the next string. Finally, let's press Pause.

keybd_event(19,0,0,0);
Sleep(10);
keybd_event(19,0,2,0);

The first string presses the key whereas the last one releases it. The Sleep button is necessary, too, since a too quick pressing/release may remain unprocessed. 19 is a virtual code of pause, 2 in the last string shows that release must be emulated.

All we have to do now is to substitute the break point in the Expert Advisor's code, say immediately after the long position the example from article Expert Advisor Sample has been opened.

ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green);
BreakPoint();

Below is the entire code to be inserted:

//We will use a function, described in header file
#include 
 
//Breakpoint neither receive nor send back any parameters
void BreakPoint()
{
   //It is expecting, that this function should work
   //only in tester
   if (!IsVisualMode()) return(0);
   
   //Preparing a data for printing
   //Comment() function is used as 
   //it give quite clear visualisation
   string Comm="";
   Comm=Comm+"Bid="+Bid+"\n";
   Comm=Comm+"Ask="+Ask+"\n";
   
   Comment(Comm);
   
   //Press/release Pause button
   //19 is a Virtual Key code of "Pause" button
   //Sleep() is needed, because of the probability
   //to misprocess too quick pressing/releasing
   //of the button
   keybd_event(19,0,0,0);
   Sleep(10);
   keybd_event(19,0,2,0);
}


What Shall We Do to Watch Local Variables?

The problem is in "invisibility" of such variables outside their declarations. In this case, the data should be passed. Suppose we want to watch variable MacdCurrent from the same article. For this, we will modify the function as follows:

void BreakPoint(double MacdCurrent)
{
   if (!IsVisualMode()) return(0);
nbsp;  
   Comment("MacdCurrent = ",MacdCurrent);


Optional Break Points

We sometimes may wish that the program does not always stop when it reaches a specific string, but only when some additional requirements are met. This usually happens in loops. For example, we want to break execution when the counter has reached a certain predefined value. For this, we have to pass an additional requirement:

void BreakPoint(double MacdCurrent, bool Condition)
{
nbsp;  if (!IsVisualMode() || (!Condition)) return(0);
nbsp;  //Or - which is the same:
   //if (!(IsVisualMode()&&Condition)) return(0);
   
   Comment("MacdCurrent = ",MacdCurrent);

We will call it as follows:

for(cnt=0;cnt<total;cnt++)     
   {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      BreakPoint(MacdCurrent, cnt==1);


Conclusion

So, why don't we just create a library to connect to the program and then use? The matter is that there are many variations, for which it would be better to modify function BreakPoint. Indeed, all written above is just a general idea. It can be implemented in many different ways.

Concluding, I would like to acknowledge Klot who was the first to guess how to realize pause pressing programmatically.

Translated from Russian by MetaQuotes Software Corp.
Original article: https://www.mql5.com/ru/articles/1427

Last comments | Go to discussion (7)
MQL4 Comments
MQL4 Comments | 27 Aug 2009 at 09:07
Here is the Pausebreak.mg
MQL4 Comments
MQL4 Comments | 27 Oct 2009 at 17:44

Hey this worked great in correcting the speed problem of Visual Mode where the last speed 32 is way too fast and speed 31 is way too slow. But the only problem was that at speed 32 it's moving so fast that by the time the keyboard event pauses the test it may be 20 to 50 bars past the even you wanted to pause at. So I added some number crunching as a sleep, since the Sleep() function doesn't work in testing.


void pause() // pauses visual mode during testing needs #include <WinUser32.mqh>
{
if(IsVisualMode())
{
keybd_event(19,0,0,0);
keybd_event(19,0,2,0);
//----crunch some numbers as sleep
int a=199999999;
int b=1;
while(a>b)
b++;
}

}

MQL4 Comments
MQL4 Comments | 22 Apr 2012 at 12:54
mql5 has debugger, pity that the language is different
whroeder1
whroeder1 | 31 Jan 2013 at 18:41
#include <WinUser32.mqh>
#import "user32.dll"
  int    GetAncestor(int, int);
#import
void     PauseTest(){                                 #define GA_ROOT 2
   datetime now = TimeCurrent();    static datetime oncePerTick;
   if(oncePerTick != now) if(IsTesting()) if(IsVisualMode()) if(IsDllsAllowed()
   ){ oncePerTick = now;
      for(int i=0; i<200000; i++){     // Delay required for speed=32 (max)
         if(IsStopped())   break;         // http://forum.mql4.com/32837 WH-DL
         int      main = GetAncestor(WindowHandle(Symbol(), Period()), GA_ROOT);
         if(i==0) PostMessageA(main, WM_COMMAND, 0x57a, 0); // 1402. Pause
}  }  }
jordan.baucke
jordan.baucke | 3 Dec 2014 at 15:11

I am attempting to set some breakpoints in my MQL4 EA running in the tester

The breakpoints work, but I cannot restart the test? And any subsequent attempts at starting a test do not run (blank visual mode chart) - I have to restart the terminal.

Any thoughts on how to restart the test after a breakpoint? And why my terminal might be freezing-

Terminal is IronFx (Build 745), Windows 7

#include <WinUser32.mqh>
#import "user32.dll"
  int GetAncestor(int, int);
#import
void PauseTest(){   datetime now = TimeCurrent();   static datetime oncePerTick;
    if( oncePerTick != now  )if( IsTesting()
    )if( IsVisualMode()     )if( IsDllsAllowed()    ){  oncePerTick = now;
        for(int i=0; i<200000; i++){        // Delay required for speed=32 (max)
            if (IsStopped()) break;         // http://forum.mql4.com/32837 WH-DL
            int main = GetAncestor(WindowHandle(Symbol(), Period()), 2);//GA_ROOT
            if (i==0) PostMessageA(main, WM_COMMAND, 0x57a, 0); // 1402. Pause
    }   }
    // The PostMessage above sends the command to the main terminal. Thus it
    // only affects the active chart window. To maximize a window for example
    // must activate it first. http://forum.mql4.com/35336#538848
    // See also SetForgroundWindow(h) https://www.mql5.com/en/code/10146
}
//Breakpoint neither receive nor send back any parameters
void BreakPoint()
{
   //It is expecting, that this function should work
   //only in tester
   if (!IsVisualMode()) return(0);
   
   //Preparing a data for printing
   //Comment() function is used as 
   //it give quite clear visualisation
   string Comm="";
   Comm=Comm+"Bid="+Bid+"\n";
   Comm=Comm+"Ask="+Ask+"\n";
   
   Comment(Comm);
   
   //Press/release Pause button
   //19 is a Virtual Key code of "Pause" button
   //Sleep() is needed, because of the probability
   //to misprocess too quick pressing/releasing
   //of the button
   keybd_event(19,0,0,0);
   Sleep(10);
   keybd_event(19,0,2,0);
}
cross posted: https://www.mql5.com/en/forum/38092
Step on New Rails: Custom Indicators in MQL5 Step on New Rails: Custom Indicators in MQL5

I will not list all of the new possibilities and features of the new terminal and language. They are numerous, and some novelties are worth the discussion in a separate article. Also there is no code here, written with object-oriented programming, it is a too serous topic to be simply mentioned in a context as additional advantages for developers. In this article we will consider the indicators, their structure, drawing, types and their programming details, as compared to MQL4. I hope that this article will be useful both for beginners and experienced developers, maybe some of them will find something new.

Here Comes the New MetaTrader 5 and MQL5 Here Comes the New MetaTrader 5 and MQL5

This is just a brief review of MetaTrader 5. I can't describe all the system's new features for such a short time period - the testing started on 2009.09.09. This is a symbolical date, and I am sure it will be a lucky number. A few days have passed since I got the beta version of the MetaTrader 5 terminal and MQL5. I haven't managed to try all its features, but I am already impressed.

False trigger protection for Trading Robot False trigger protection for Trading Robot

Profitability of trading systems is defined not only by logic and precision of analyzing the financial instrument dynamics, but also by the quality of the performance algorithm of this logic. False trigger is typical for low quality performance of the main logic of a trading robot. Ways of solving the specified problem are considered in this article.

Using text files for storing input parameters of Expert Advisors, indicators and scripts Using text files for storing input parameters of Expert Advisors, indicators and scripts

The article describes the application of text files for storing dynamic objects, arrays and other variables used as properties of Expert Advisors, indicators and scripts. The files serve as a convenient addition to the functionality of standard tools offered by MQL languages.