Скачать MetaTrader 5

Брейкпойнты в тестере – это возможно!

20 июля 2007, 10:03
Christo Tsvetanov
4
1 091


Введение

Если мне чего-то и не хватает в MQL4, то это наличия нормального отладчика (debugger) советников. Все мы люди, поэтому часто делаем ошибки. При обычном программировании мы расставляем точки останова (брейкпойнты), запускаем программу, и когда выполнение достигнет какой-нибудь из этих точек, то выполнение останавливается. При этом мы можем посмотреть на содержание переменных, которые нас интересуют.

Вывод отладочных данных возможен и сейчас благодаря функциям типа Print, Comment и так далее, но еще хочется в какой-то момент временно остановить программу в точно определенном месте, чтобы проанализировать ситуацию. Тут есть еще и дополнительный нюанс: обычно программа запускается для торговли либо в режиме Demo, либо в режиме Real. Это означает, что на результаты можно будет посмотреть только через несколько месяцев… Таким образом, отладочный режим имеет смысл только в режиме тестирования советников.


Принцип действия

С появлением в тестере "Визуального режима тестирования" стало возможно следить за реакциями нашего советника во время быстрого прогона программы. Если мы захотим временно остановить выполнение, то можем нажать на клавишу "Pause" или кликнуть мышкой по одноимённой кнопке на панели тестера. Разработчики терминала предоставили библиотеку WinUser32.mqh, содержащую некоторые любопытнейшие функции. Одна из них – keybd_event. Она позволяет осуществлять нажатие произвольной клавиши.

Тут и рождается идея – написать функцию, которая нажимала бы на паузу программным образом и печатала необходимую отладочную информацию. Так как наш советник будет использовать DLL, то сначала нужно это разрешить. Нажимаем Ctrl+O и ставим/снимаем галочки:

Потом, где-то в начале текста программы, нужно объявить об использовании библиотеки WinUser32:

#include <WinUser32.mqh>

Затем следует объявление самой функции BreakPoint. Тут есть нюансы, но простейшая реализация предполагает отсутствие передаваемых/возвращаемых параметров:

void BreakPoint()

Функция должна срабатывать только в режиме визуального тестирования, поэтому ставим проверку: если тестер не находится в режиме визуального тестирование, то уходим:

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

Потом нужно визуализировать кое-какие данные. По-моему, самый наглядный способ – это Comment(). Предположим, что пока нам нужны только Bid и Ask.

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

Тут “\n” означает, что идущие потом данные будут отображены на следующей строчке. Под конец нажимаем на клавишу Pause.

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

Первая строка нажимает на клавишу, последняя – отжимает её. Пауза (Sleep) нужна, так как слишком быстрое нажатие/отжатие может и не обработаться. 19 – это виртуальный код клавиши паузы, 2 в последней строке показывает, что нужно эмулировать отжатые.

Всё, что осталось, – подставить брейкпойнт в коде советника, например, сразу после момента открытия длинной позиции в примере из статьи "Пример создания эксперта".

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

Вот и весь вставляемый код:

//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);
}


Что делать, если нам нужно посмотреть на локальные переменные

Проблема заключается в "невидимости" таких переменных за пределами их объявления. В этом случае данные нужно передавать. Предположим, нам нужно посмотреть на переменную MacdCurrent из той же статьи. Для этого меняем функцию следующим образом:

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


Условные точки перерыва

Иногда хочется, чтобы программа останавливалась не всегда (по достижении конкретной строки), а только при выполнении каких-то дополнительных условий. Обычно такое бывает в циклах - например, нам нужен останов, когда счетчик достиг какого-то заранее известного значения. Для этого нужно передавать дополнительное условие:

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

Вызываем следующим образом:

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


Заключение

так, почему всё-таки не сделать библиотеку, которую можно подключить и потом использовать? Дело в том, что есть много вариантов, для которых лучше изменять содержимое функции BreakPoint. На самом деле все вышесказанное - только основная идея. Есть множество вариантов её использования.

И наконец, хочу поблагодарить Klot'а – он первым догадался о программной реализации нажатия клавиши паузы.

MQL4 Comments
MQL4 Comments | 9 ноя 2008 в 11:20

А что за тестер?

Где дают?

Опух я уже с этими принтами, мессбоксами и алертами.

Спасибо.

Денис Орлов
Денис Орлов | 11 сен 2009 в 15:42

Спасибо за статью.

А где можно подробнее ознакомится с функциями keybd_event, mouse_event и др.?

MQL4 Comments
MQL4 Comments | 14 июн 2010 в 08:25
vu ne podskajete skolko stoil ili mog stoit Maitnik (Swinger) v 2008 gody?
Vitalii Borynskyi
Vitalii Borynskyi | 22 окт 2012 в 10:30
Очень интересная статья. Не знаю, буду ли применять на практикте, но обязательно опробую. Ну и для общего развития. Класс!
Что такое Мартингейл и имеет ли смысл им пользоваться? Что такое Мартингейл и имеет ли смысл им пользоваться?

В статье содержится подробное описание системы мартингейл, а также точные математические вычисления необходимые для ответа на вопрос "Имеет ли смысл применять мартингейл?".

Тестер в терминале MetaTrader 4: Это необходимо знать Тестер в терминале MetaTrader 4: Это необходимо знать

Продуманный интерфейс терминала MetaTarder 4 является фасадом, но кроме того терминал имеет в своем составе также тщательно проработанный тестер стратегий. И если достоинства МТ4 как торгового терминала являются очевидными, то оценка возможностей тестера по качественному тестированию стратегий приходит только с опытом. Эта статья показывает достоинства и преимущества тестирования именно в MetaTrader 4.

Как реализовать свой критерий оптимизации Как реализовать свой критерий оптимизации

Для стандртного эксперта Moving Average реализован пример оптимизации по критерию прибыль/просадка с выводом результатов в файл

Язык MQL4 для "чайников". Технические индикаторы и встроенные функции Язык MQL4 для "чайников". Технические индикаторы и встроенные функции

Это третья статья из цикла "Язык MQL4 для 'чайников'". Сейчас мы будем разбираться, как использовать встроенные функции и функции для работы с техническими индикаторами. Последние будут жизненно необходимы при разработке в дальнейшем ваших советников и индикаторов. Кроме того, мы на простом примере посмотрим, как можно отслеживать торговые сигналы для входа в рынок, что бы вы поняли, как правильно использовать индикаторы. А в конце статьи вы узнаете кое-что новенькое и интересное про сам язык.