Группа OnTester-событий для контроля оптимизации

Для управления ходом оптимизации и передачи с агентов на терминал произвольных прикладных результатов (помимо показателей торговли) в MQL5 существует 3 особых события: OnTesterInit, OnTesterDeinit, OnTesterPass. Описав для них обработчики в коде, программист получит возможность выполнять нужные ему действия перед запуском оптимизации, после завершения оптимизации и при завершении каждого из отдельных проходов оптимизации (если с агента поступили прикладные данные — об этом чуть ниже).

Все обработчики являются опциональными. Как мы видели, оптимизация работает и без них. Также следует понять, что все 3 события работают только в ходе оптимизации, но не одиночного теста.

Эксперт с данными обработчиками автоматически загружается на отдельном графике терминала с указанными в тестере символом и периодом. Эта копия эксперта не торгует, а выполняет исключительно сервисные действия. В ней не работают все прочие обработчики событий, в частности, OnInit, OnDeinit, OnTick.

Чтобы в коде эксперта отличить, выполняется ли он в штатном торговом режиме на агенте или в сервисном режиме в терминале, следует вызвать функцию MQLInfoInteger(MQL_FRAME_MODE) — получим true или false. Как можно понять, этот сервисный режим также называемся режимом "фреймов" — пакетов прикладных данных, которые могут отправляться в терминал из экземпляров эксперта на агентах. Как это делается, мы покажем чуть позже.

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

Событие OnTesterInit генерируется при запуске оптимизации в тестере стратегий перед самым первым проходом. Обработчик имеет 2 варианта: с возвращаемым типом int и void.

int OnTesterInit(void)

void OnTesterInit(void)

В варианте с возвратом int значение ноль (INIT_SUCCEEDED) означает успешную инициализацию эксперта, запущенного на графике в терминале, что разрешает начать оптимизацию. Любое другое значение означает код ошибки, и оптимизация не начнется.

Вторая версия функции всегда подразумевает успешную подготовку эксперта к оптимизации.

На выполнение OnTesterInit отводится ограниченное время, по превышении которого будет произведено принудительное завершение работы эксперта, а сама оптимизация будет отменена. При этом в журнал тестера будет выведено соответствующее сообщение.

В предыдущем разделе мы видели пример того, как обработчик OnTesterInit использовался для модификации параметров оптимизации с помощью функций ParameterGetRange/ParameterSetRange.

void OnTesterDeinit(void)

Функция OnTesterDeinit вызывается по окончании оптимизации эксперта.

Функция предназначена для финальной обработки прикладных результатов оптимизации. Например, если в OnTesterInit был открыт файл для записи содержимого фреймов, то в OnTesterDeinit его нужно закрыть.

void OnTesterPass(void)

Событие OnTesterPass автоматически генерируется при поступлении фрейма данных во время оптимизации. Функция позволяет обработать прикладные данные, получаемые от экземпляров эксперта, выполняющихся на агентах во время оптимизации. Отправку фрейма с агента тестирования необходимо выполнять из обработчика OnTester с помощью функции FrameAdd.

Диаграмма последовательности событий при оптимизации экспертов

Диаграмма последовательности событий при оптимизации экспертов

Стандартный набор финансовых показателей о каждом проходе теста отправляется из агентов в терминал автоматически. Эксперт не обязан что-либо отправлять с помощью FrameAdd, если ему это не требуется. Если фреймы не используются, обработчик OnTesterPass не будет вызываться.

С помощью OnTesterPass можно динамически обрабатывать результаты оптимизации "на лету", например, отображать на графике в терминале, или складывать в файл для последующей пакетной обработки.

Для демонстрации возможностей обработчиков OnTester-событий нам нужно сначала изучить функции для работы фреймами. Они представлены в следующих разделах.