Отладка в mql. Улучшить дебаг с помощью mql_debug
1 марта 2021 г. 3:54
Зачастую при написании кода mql в среде разработки MetaEditor не хватает отладчика (дебаггера), который мог бы не только следить за переменными, но и вычислять выражения. К сожалению, в MetaEditor такого нет. Например, в коде:
int OnInit(){
double a = MathPow(2, 1) + MathAbs(-10)/2;
for (int i=0, len=OrdersTotal(); i < len; i++)
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) && OrderType() == OP_BUY)
OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 70);
}
поставив точку останова, например, на 2-ой, мы не можем посмотреть в дебаггере отдельно, чему равно MathPow(2, 1) или MathAbs(-10)/2. Только если мы пошагово перейдём на следующую строчку, мы сможем узнать в дебаггере, чему равно a. Такая же ситуация и со строчкой OrderClose - мы не сможем узнать в отладчике текущий результат выражения OrderTicket(), OrderLots() или MarketInfo(OrderSymbol(), MODE_BID).
Чтобы хоть как-то узнать, например, чему равно MathPow(2, 1), можно использовать команду Print и смотреть результат выражения в журнале терминала. Или выносить выражения в отдельную переменную и просматривать результат в дебаггере:
int OnInit(){
Print(MathPow(2, 1));
double my_debug = MathAbs(-10)/2;
double a = MathPow(2, 1) + MathAbs(-10)/2;
}
Недостаток такого подхода в том, что при использовании Print неудобно просматривать значение выражения: всё-таки хочется видеть в одном месте и код, и вычисленные значения. При создании дополнительных переменных, требуется писать много букв: объявлять тип данных и придумывать имя переменной - это долго.
Для облегчения работы с отладкой программного кода на mql я написал библиотеку mql_debug, который умеет записывать результат вычисления выражений в файл или журнал терминала. При этом показывается, в каком файле, в какой функции и на какой строчке кода был вызван дебаг выражения. Библиотека доступна на гитхабе:
https://github.com/vivazzi/mql_debug
Установка mql_debug
Скачайте библиотеку и скопируйте папку mql_debug/Include/debug в <TERMINAL DIR>/MQL(4/5)/Include.
Использование
Добавьте #include <debug/debug.mqh> и используйте функцию _d:
#include <debug/debug.mqh>
int OnInit(){
_d(MathPow(2, 1) + MathAbs(-10) / 2);
_d(StringFormat("Length of 1234567890 = %d", StringLen("1234567890")));
}
Скомпилируйте и запустите своего эксперта в терминале, прикрепив на какое-нибудь окно торговой пары. Результат дебага будет записан в файл <TERMINAL DIR>/Files/debug/<ACCOUNT NUMBER>/debug.txt:
MyExpert.mq4: int OnInit(), line 3:
MathPow(2,1)+MathAbs(-10)/2 :: 7
MyExpert.mq4: int OnInit(), line 4:
StringFormat(Length of 1234567890 = %d,StringLen(1234567890)) :: Length of 1234567890 = 10
Как видите, в лог файле отображается информация:
- Файл, функция и номер линии, на которой был вызван дебаг
_d, - Отслеживаемое выражение и его результат после знаков
::
Также вы можете использовать _d любой вложенности:
_d(_d(MathPow(2, 1)) + _d(MathAbs(-10) / 2));
Результат выполнения кода:
TestDebug.mq4: int OnInit(), line 3:
MathPow(2,1) :: 2
TestDebug.mq4: int OnInit(), line 3:
MathAbs(-10)/2 :: 5
TestDebug.mq4: int OnInit(), line 3:
MathPow(2,1)+MathAbs(-10)/2 :: 7
Результаты отображаются в порядке вложенности, где сначала показываются самые внутренние функции _d.
После выполнения нескольких функций _d можно поменять имя лог файла командой _d_set_log_path(). Таким образом будет несколько файлов с отслеживаемыми данными:
#include <debug/debug.mqh>
int OnInit(){
_d(MathPow(2, 1));
_d_set_log_path("example_debug.txt");
_d(MathAbs(-10));
}
В результате создадутся 2 дебаг файла:
1. <TERMINAL DIR>/Files/debug/<ACCOUNT NUMBER>/debug.txt:
TestDebug.mq4: int OnInit(), line 3:
MathPow(2,1) :: 2
2. <TERMINAL DIR>/Files/example_debug.txt:
TestDebug.mq4: int OnInit(), line 3:
MathAbs(-10) :: 10
Если во время выполнения кода нужно очистить файл, то используйте метод _d_clear():
#include <debug/debug.mqh>
int OnInit(){
_d(MathPow(2, 1));
_d_clear();
_d(MathAbs(-10));
}
При вызове _d и _dp вы используете объект Дебага по умолчанию. Для использования нескольких дебагов создайте свои объекты дебага и используйте соответствующие функции d и dp с указанием вашего объекта:
Debug d_1("debug_1.txt");
d(d_1, MathPow(4, 1));
dp(d_1, MathPow(4, 2));
Debug d_2("debug_2.txt");
d(d_2, MathPow(4, 1));
dp(d_2, MathPow(4, 2));
Для изменения лог файла используйте d_set_log_path(d_object, log_path), а для очищения файла используйте d_clear(d_object).
Сохранение дебага в журнал терминала
Для сохранения результатов дебага в журнал терминала, то используйте _dp():
#include <debug/debug.mqh>
int OnInit(){
_dp(MathPow(2, 3));
}
Выведет в журнал:
2021.02.28 13:50:25.956 MyExpert EURUSD,H1: MyExpert.mq4: int OnInit(), line 43: MathPow(2,3) :: 8
В README.md пакета на гитхабе вы можете найти более полную и актуальную документацию mql_debug:
https://github.com/vivazzi/mql_debug
Представляю вашему вниманию книгу, написанную моим близким другом Максимом Макуриным: Секреты эффективного управления ассортиментом.
Книга предназначается для широкого круга читателей и, по мнению автора, будет полезна специалистам отдела закупок и логистики, категорийным и финансовым менеджерам, менеджерам по продажам, аналитикам, руководителям и директорам, в компетенции которых принятие решений по управлению ассортиментом.
Комментарии: 0