Отладка в 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