Разрабатываем мультивалютный советник (Часть 31): Секреты шага создания проекта оптимизации (I)
Введение
В прошлой статье мы сделали обзор полного цикла использования разработанной системы создания мультивалютных советников, построенных на основе идеи объединения многих одиночных экземпляров простых торговых стратегий. Статья получилась большая, но иначе невозможно было дать общий взгляд на использование созданного инструментария. Однако всё равно многие нюансы пока остались за кадром, а с ними с высокой вероятностью придется столкнуться при использовании библиотеки Adwizard. Мы и сами в процессе написания прошлой статьи столкнулись с некоторыми непонятными вещами, оставив разбор их причин на потом. Не будем откладывать это надолго.
Приступим к более детальному погружению в тонкости и исследование подводных камней предложенного подхода. В рамках данной статьи мы подробнее посмотрим на шаг создания проектов оптимизации, который в прошлой части был шагом 2. Часть необходимых действий на этом шаге тогда уже была выполнена заранее, и мы только воспользовались полученными результатами для выполнения данного шага. Теперь обратим внимание на то, как нужно подбирать параметры оптимизации советников до создания проекта.
Намечаем путь
Начнём с анализа того, почему у нас не создалась база данных итогового советника первого этапа. Напомним, что дело было так: мы создали три разных проекта оптимизации и запустили их выполнение на конвейере автоматической оптимизации. В результате мы ожидали получить три базы данных для итоговых советников, но получили только две. Для первого проекта база данных не была создана. Есть подозрение, что наиболее вероятная причина этого может быть не связана с какими-то ошибками в программном коде. Но эта причина может оказаться не единственной.
Далее рассмотрим, какая подготовительная работа должна предшествовать шагу создания проекта. Ведь в прошлой статье мы воспользовались почти всем готовым — и торговой стратегией и определёнными диапазонами оптимизируемых параметров и выбором времени оптимизации и прочими вещами. А за каждой такой вещью стоит тот или иной объем действий по получению нужных значений и обоснованию допустимости и эффективности их выбора.
Представим, что мы только что реализовали новую торговую стратегию и хотим использовать её для автоматической оптимизации. То есть шаг 1 по разработке торговой стратегии будем считать выполненным, а вот к исследованию поведения этой стратегии при разных значениях входных параметров мы ещё не приступили. Без такого, хотя бы беглого исследования, выполнить второй шаг не получится. Поэтому займемся предварительными запусками оптимизации советника первого этапа оптимизации вне конвейера автоматической оптимизации.
Что не так с первым проектом
После завершения работы конвейера автоматической оптимизации, на котором были выполнены три проекта, мы получили следующие файлы в общей папке данных терминала:

Для этого рисунка мы специально почистили общую папку от других файлов, которые не имели отношения к рассматриваемому нами процессу. Если у вас в этой папке будут присутствовать ещё и другие файлы, то это нормально.
Откроем базу данных оптимизации article.19684.db.sqlite в SQLiteStudio. Создание базы данных итогового советника должно было выполниться на третьем этапе. Поэтому нам нужно найти запись в таблице задач (tasks), которая соответствует работе (job), выполняемой на третьем этапе (stage). Открываем содержимое таблицы этапов (stages) и находим в ней запись для первого проекта (id_project = 1) с третьим этапом (expert = Stage3.ex5 или name = "Save to library"):

Запоминаем идентификатор строки третьего этапа (id_stage = 4), переходим к таблице работ (jobs) и там находим строку работы, соответствующей этом этапу:

Из этой строки берём идентификатор работы (id_job = 20), переходим к таблице задач (tasks) и находим в ней строку для задачи, связанной с этой работой. На третьем этапе у нас в состав работы входит единственная задача:

Посмотрим на дату начала и окончания выполнения этой задачи: разница между ними составляет всего одну секунду. Это значит, что тестер не выполнил проход для советника третьего этапа, так как на его выполнение потребовалось бы гораздо больше времени. Можно убедиться в этом, поискав в таблице проходов (passes) запись, соответствующую идентификатору этой задачи (id_task = 65). Такой записи нет.
Посмотрим теперь аналогичным образом на работы и задачи второго этапа (id_stage = 3). Сначала определим идентификаторы работ для второго этапа:

Затем по ним выберем задачи, относящиеся к этим работам. На втором этапе мы тоже использовали только одну задачу для одной работы:

Как видно, у этих задач время выполнения составляло менее 10 секунд (finish_date - start_date), что заметно меньше выделенных 300 секунд (max_duration) на данном этапе. Если посмотреть таблицу проходов (passes), то в ней нет проходов для данных задач.
Поднимемся ещё выше по порядку выполнения этапов и посмотрим на первый этап конвейера автоматической оптимизации. На нём для одной работы выполняется шесть задач оптимизации, поэтому их будет уже больше. Дойдя аналогично третьему и второму этапу до таблицы задач, мы увидим следующее:

Тут разность между временем начала и окончания задачи соответствует установленной максимальной продолжительности (max_duration = 120). Поэтому на этом этапе, похоже, всё было в порядке. Вернёмся ко второму этапу.
Попробуем перезапустить его. Для этого в базе данных нам надо изменить статус второго этапа с Done (Выполнен) на Queued (Поставлен в очередь):

Благодаря написанным в части 20 триггерам, такое изменение статуса этапа автоматически приведет к изменению статуса всех входящих в него работ и задач. Они так же перейдут в состояние Queued (Поставлен в очередь). После этого запускаем в терминале советник автоматической оптимизации:

Оптимизация успешно стартовала, мы видим, что общее количество поставленных в очередь задач оптимизации равно 9 (Total tasks in queue: 9). При заданном ограничении времени 5 минут на задачу для завершения их выполнения понадобится примерно 45 минут. Если переключиться на вкладку результатов текущей оптимизации, то видно довольно большое количество успешно выполненных проходов с довольно хорошим показателем среднегодовой прибыли (от $2000 до $8000 для начального депозита $10000):

Так что подождём завершения этого повторного запуска. В итоге запуск завершился успешно, все задачи оптимизации были выполнены. Теперь можно перезапустить третий этап конвейера автоматической оптимизации.
Поменяем статус у третьего этапа первого проекта в таблице stages так же, как мы чуть ранее сделали это со статусом второго этапа. Если мы не удалили с графика терминала советник автоматической оптимизации, то он сразу приступит к выполнению поставленной задачи. Если успели его удалить, то понадобится снова его прикрепить к графику. При этом советник сам найдет задачу, поставленную в очередь, и начнёт её выполнять:

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

Что ж, нам не удалось достоверно установить причину возникшей ранее ошибки, но зато мы продемонстрировали, какие шаги могут привести к устранению её последствий. Пока что перезапуск этапов проектов выполнять весьма неудобно. Если нам понадобится чаще прибегать к этой операции, то, наверное, имеет смысл подумать над реализацией какого-то более удобного интерфейса. Но пока не будем забегать вперёд.
Возможно, что в тот раз оптимизация на втором этапе не смогла выполниться из-за невозможности подгрузить историю котировок с серверов MetaQuotes. Сообщения о таких ошибках появлялись в то время на форуме MQL5. Или сыграла роль ещё какая-то ошибка в последней бета-версии на тот момент, уже исправленная в текущей бета-версии, которая использовалась сейчас. В тот период как раз шла очень интенсивная работа по внедрению нововведений в терминал, и новые бета-версии выходили почти каждый день.
Также пару раз встречалась такая ситуация, что советник оптимизации пытался прервать текущий процесс оптимизации по завершении отведённого времени, но терминал впадал в состояние невозможности остановить оптимизацию. Кнопка "Стоп" благополучно превращалась в кнопку "Старт", но оптимизация при этом продолжалась. Попытки советника начать новую оптимизацию заканчивались неудачей. После принудительного перезапуска агентов тестирования проблема не повторялась, поэтому не ясно, как можно её предотвратить в дальнейшем. Вполне возможно, что в новых билдах она вообще не повторится.
Так или иначе, мы всегда можем перезапустить нужный этап автоматической оптимизации проекта. Однако, как выяснилось, мы не можем таким образом перезапустить выполнение одной фиксированной задачи, поменяв её статус на Queued. Дело в том, что когда мы разрабатывали триггеры для автоматического изменения статусов дочерних объектов при смене статуса родительских, такой сценарий не был предусмотрен. Поэтому необходимый для такой работы триггер пока не реализован. Мы добавим его в дальнейшем или реализуем нужную смену статусов с помощью внешних по отношению к базе данных средств.
Тестирование итогового советника
Посмотрим, какие результаты покажет итоговый советник для первого проекта. Для этого нам потребуется выполнить следующие действия:
- Посмотреть, какое имя имеет итоговый советник для первого проекта и какой магический номер установлен в его параметрах по умолчанию. Мы назвали его SimpleCandles-MQ-100K-10.mq5, а магический номер в нём поставлен 1968401.
- Переименовать или скопировать базу данных итогового советника в файл с именем, составленным по такому шаблону: <имя_советника_без_расширения>-<магический_номер>.test.sqlite, то есть
- SimpleCandles-MQ-100K-10-1968401.test.db.sqlite
- Скомпилировать итоговый советник, если это ещё не было сделано раньше.
- Запустить тестирование для оценки результатов.
В первом проекте мы поставили максимальную расчётную просадку равную 10% и использование для торговли всех доступных на торговом счёте средств. При этом включены риск-менеджер и менеджер закрытия, но их параметры поставлены со значительным запасом. Например, максимальный дневной убыток равен 20%. Это значение не должно достигаться, если рыночная ситуация будет продолжать оставаться похожей на ту, которая наблюдалась на интервале оптимизации. Для менеджера закрытия мы поставили значение общей прибыли, при которой происходит закрытие всех позиций и продолжение торговли с чистого листа, равным 200%.
Результаты тестирования на периоде 2025.01.01 — 2025.10.01 с настройками по умолчанию получились вот такие:


Как видно, просадка составила более 40% вместо ожидаемых 10%. Это влияние менеджера закрытия и риск-менеджера. Риск-менеджер закрыл все позиции 2025.04.09, так как была достигнута прибыль 200% от начального баланса $100000. Данный момент времени начала торговли оказался неудачным, что привело к нескольким срабатываниям риск-менеджера, закрывшим позиции по достижении просадки более 20% до начала следующего дня. Такое поведение будет предметом дальнейших исследований, так как ранее мы использовали риск-менеджер в ситуациях, когда рост депозита составлял единицы процентов, а не сотни. Возможно, что потребуется вносить корректировки в его работу.
При отключении риск-менеджера и менеджера закрытия, или только последнего, результаты выглядят более ожидаемо:


Тут превышение просадки совсем небольшое: 11% вместо 10%. Такое различие связано, скорее всего, с тем, что при нормировке на третьем этапе использовался режим работы с постоянным лотом (точнее, с постоянным размером депозита, выделенного для расчёта размеров лотов), а сейчас мы тестировали в режиме с переменным лотом (весь растущий баланс счёта был доступен советнику для расчёта размеров позиций).
Запуск итогового советника
Для запуска итогового советника на торговом счёте нам потребуется выполнить похожие действия:
- Переименовать или скопировать базу данных итогового советника в файл с именем <имя_советника_без_расширения>-<магический_номер>.sqlite, то есть SimpleCandles-MQ-100K-10-1968401.db.sqlite
- Скомпилировать итоговый советник, если это ещё не было сделано раньше.
- Скопировать скомпилированный советник в папку Experts того терминала, на котором ему предстоит работать. Этот шаг не нужен в том случае, если компиляция выполнялась уже в той установке терминала, в которой планируется работа советника.
- Запустить его на графике терминала на любом символе и таймфрейме с параметрами по умолчанию.
Отметим ещё раз, что при желании изменить параметры итогового советника, рекомендуется делать это не в диалоге установки параметров, а в исходном коде советника. Это более надёжный способ, и он всегда доступен, так как исходный код итогового советника полностью в нашем распоряжении.

Для дальнейшего наблюдения за несколькими терминалами с запущенными итоговыми советниками можно использовать веб-интерфейс проекта MT5 Manager, доступный в хранилище MQL5 Algo Forge. На данном этапе мы сможем увидеть примерно такую картину для трёх запущенных терминалов:

Перейдём теперь ко второй намеченной части — рассмотрению предварительной работы для шага создания проекта оптимизации.
Торговая стратегия
Прежде всего, давайте напомним суть используемой модельной торговой стратегии. Более подробно про неё можно прочитать в части 24, а кратко её можно изложить так:
Советник запускается на определенном символе и периоде (таймфрейме)
Задаем входные параметры:
- Символ
- Таймфрейм для подсчёта однонаправленных свечей
- Количество однонаправленных свечей (signalSeqLen)
- Период ATR (periodATR)
- Stop Loss (в пунктах или % ATR) (stopLevel)
- Take Profit (в пунктах или % ATR) (takeLevel)
- Максимальное количество одновременно отрытых позиций (maxCountOfOrders)
- Размер позиций
При наступлении нового бара, проверяем направления последних закрытых signalSeqLen свечей.
Если направления одинаковые, и количество открытых позиций меньше maxCountOfOrders, то:
- Вычисляем StopLoss и TakeProfit. Если periodATR = 0, то просто отступаем от текущей цены на количество пунктов, взятых из параметров stopLevel и takeLevel. Если periodATR > 0, то рассчитываем величину ATR, используя параметр periodATR для дневного таймфрейма. От текущей цены отступаем на величины ATR * stopLevel и ATR * takeLevel.
- Открываем позицию SELL, если направления свечей были вверх и позицию BUY, если направления свечей были вниз. При открытии устанавливаем рассчитанные ранее уровни StopLoss и TakeProfit.
Эта стратегия реализована и подключена в советнике первого этапа конвейера автоматической оптимизации в проектном репозитории SimpleCandles в файле Optimization/Stage1.mqh. Из этого файла нас интересует сейчас только блок задания входных параметров стратегии:
//+------------------------------------------------------------------+ //| 4. Входные параметры для стратегии | //+------------------------------------------------------------------+ sinput string symbol_ = ""; // Символ sinput ENUM_TIMEFRAMES period_ = PERIOD_CURRENT; // Таймфрейм для свечей input group "=== Параметры сигнала к открытию" input int signalSeqLen_ = 6; // Количество однонаправленных свечей input int periodATR_ = 0; // Период ATR (если 0, то TP/SL в пунктах) input group "=== Параметры отложенных ордеров" input double stopLevel_ = 25000; // Stop Loss (в доле ATR или пунктах) input double takeLevel_ = 3630; // Take Profit (в доле ATR или пунктах) input group "=== Параметры управление капиталом" input int maxCountOfOrders_ = 9; // Макс. количество одновременно отрытых ордеров input int maxSpread_ = 100; // Макс. допустимый спред (в пунктах)
Для создания проекта оптимизации нам нужно выбрать какие-то разумные значения или диапазоны значений для каждого параметра. Давайте пройдемся по ним и проанализируем каждый.
- symbol_ — символ. Этот параметр не меняется в процессе одной оптимизации, так как для каждого символа мы будем запускать отдельный процесс оптимизации. Поэтому для него нам нужно выбрать те символы, которые мы планируем включить в итоговый советник. Например, для первого проекта мы выбрали три символа: GBPUSD, EURUSD, EURGBP. Посмотрим сначала на первый из них — GBPUSD.
- period_ — таймфрейм для свечей. Этот параметр тоже не меняется в процессе одной оптимизации, поэтому для него нам также нужно заранее выбрать какие-то значения. Исходя из основной идеи торговой стратегии, возьмём, например, несколько не очень больших таймфреймов, чтобы сделать более частыми появление сигналов на открытие позиций. Конечно, заранее мы не можем точно знать, какие таймфреймы окажутся более выгодными. Но для этого и нужен такой предварительный анализ результатов оптимизации, которую мы выполним до создания проекта автоматической оптимизации. Посмотрим на работу советника на таймфрейме M5.
- signalSeqLen_ — количество однонаправленных свечей. Для этого параметра уже логично использовать перебор нескольких значений при оптимизации. Для определения разумного диапазона мы можем, например, собрать статистику по количеству серий однонаправленных свечей разной длины. Для этого мы даже делали вспомогательный инструмент в части 26. Из его результатов видно, что большинство серий на разных таймфреймах имеют длину от 2 до 8. Поэтому возьмем именно такой диапазон для этого параметра с шагом 1.
- periodATR_ — период ATR (если 0, то TP/SL в пунктах). Здесь мы должны чётко определиться, будем ли мы использовать ATR или нет, так как от этого будут зависеть допустимые диапазоны двух следующих параметров для SL и TP. Исходя из того, что в пунктах движение цены для различных символов может иметь разные абсолютные значения, то кажется более удобным использовать оценку размаха движения данного символа в виде ATR, и указывать размеры SL и TP относительно этой оценки. В исходном коде стратегии для расчёта ATR используется таймфрейм D1, поэтому возьмем для начала широкий диапазон от 28 до 210 дней с шагом 2, чтобы сгладить кратковременные всплески ATR.
- stopLevel_ — Stop Loss (в доле ATR или пунктах). Тут у нас нет особо предположений, какие значения будут давать хорошие результаты. Поэтому начнём с очень малой доли от ATR и дойдём до заведомо большой доли, которая будет давать очень редкие срабатывания SL. Например, от 0.01 до 20 с шагом 0.01.
- takeLevel_ — Take Profit (в доле ATR или пунктах). Аналогично предыдущему параметру, возьмем широкий диапазон значений с маленьким шагом. Например, от 0.01 до 10 с шагом 0.01. Максимальное значение взяли поменьше, чтобы в среднем в комбинациях параметров чаще встречался TP, который меньше SL, но и обратная ситуация тоже могла встретиться.
- maxCountOfOrders_ — максимальное количество одновременно открытых ордеров. С этим параметром тоже изначально нет ясности, поэтому поставим наугад диапазон значений от 1 до 10 с шагом 1.
- maxSpread_ — максимально допустимый спред (в пунктах). Этот параметр мы вводили уже после реализации торговой стратегии для демонстрации того, как можно добавить новый параметр. Поэтому он не будет оказывать какое-то существенное влияние на оптимизацию. Поставим ему достаточно большое значение, чтобы спред всё время считался допустимым, например, 100 пунктов.
Сделав такой выбор начальных диапазонов входных параметров стратегии для оптимизации, приступим к проверке, насколько этот выбор является приемлемым.
Предварительное тестирование
Откроем тестер стратегий, выберем в нём генетическую оптимизацию советника первого этапа на временном интервале от 2025.01.01 до 2025.10.01 (9 месяцев) и внесём в параметры выбранные выше значения:


Помимо рассмотренных параметров торговой стратегии, мы видим вверху ещё два параметра, которые были добавлены в советнике первого этапа: идентификатор задачи оптимизации и файл с базой данных оптимизации. Они понадобятся только при запуске конвейера автоматической оптимизации, а сейчас мы можем их просто игнорировать.
Запустим оптимизацию и понаблюдаем некоторое время за её результатами. Долго ждать не пришлось, и менее чем за 5 минут оптимизация завершилась. Посмотрим сначала на визуализацию результатов:

Напомним, что критерием оптимизации был пользовательский критерий, в качестве которого мы использовали нормированную прибыль, получаемую при 10% просадке от депозита $10000 за год работы. Если период оптимизации меньше года, то значение критерия всё равно аппроксимируется на год.
На рисунке видно, что этот показатель принимал значения в диапазоне от -$1000 до $13000. Значения, близкие к наибольшим, начали появляться после совершения примерно одной трети от всех проходов. Это даёт основания полагать, что можно ограничить время оптимизации при сохранении качества получаемых результатов.
Мы видим много темно-зеленых точек, то есть таких, которые обозначают проход с достаточно большим количеством сделок. Но встречаются и высоко расположенные красные точки, означающие проход, в котором, несмотря на хороший результат, было совершено мало сделок и поэтому есть сомнения в том, что это достижение именно торговой стратегии, а не удачи.
Посмотрим теперь на численные характеристики наилучших проходов.

По этим результатам тоже можно сделать некоторые дополнительные выводы:
- Значения параметра maxCountOfOrders_ в основном ближе к верхней границе его диапазона (к 10). Один из проходов, где этот параметр равен 1, показан красным, так как совершил всего 12 сделок. Коэффициент Шарпа для него заметно меньше, чем у соседних проходов, поэтому мы, наверное, можем зафиксировать значение этого параметра равным 10, исключив из оптимизации.
- Проходы с сильно отличающимися значениями параметра periodATR_ могут давать примерно одинаковые по характеристикам результаты. Поэтому этот параметр — тоже кандидат на удаление из списка оптимизируемых. Попробуем поставить ему значение 28 на следующей итерации.
- Можно заметить, что у лучших проходов величина takeLevel_ немного больше stopLevel_. Также не видно хороших результатов, где эти величины меньше 1.0. Поэтому можно скорректировать диапазоны для этих параметров, например, на промежуток от 1.0 до 5.0 тем же шагом 0.01.
- Параметр signalSeqLen_ для лучших проходов принимал в основном только два значения 4 и 5. Так что можем ограничить диапазон значений для этого параметра только этими двумя.
Однако перед тем, как применить эти изменения для диапазонов, запустим тестирование ещё для другого символа: EURUSD. Для него результаты получились немного другие:

Здесь в лучшие проходы попали другие значения для параметров takeLevel_, stopLevel_ и signalSeqLen_. Поэтому лучше, наверное, их не ограничивать так, как мы собирались сделать только на основе анализа результатов оптимизации по GBPUSD. Также видно, что количество сделок на проходах маловато. Это связано с большими значениями SL и TP для открываемых позиций. Поэтому нельзя будет задать в параметрах отбора проходов на второй этап оптимизации слишком большое значение для минимального количества сделок. Иначе на него не пройдут почти все проходы для EURUSD. Пока что желательно установить его равным не более чем 20.
Для оптимизации на EURGBP результаты получились ещё менее красивыми:

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

В итоге у нас осталось только три оптимизируемых параметра.
Посмотрим, как выглядят результаты пробной оптимизации на трёх выбранных символах при таких настройках.
GBPUSD:

EURUSD:

EURGBP:

В целом, довольно неплохо. Количество сделок, где их было мало, увеличилось. Коэффициент Шарпа достигает приятных значений. Если нас устраивает такое разнообразие хороших результатов проходов, то можно переходить к переносу этих параметров оптимизации в проект. Если пока нет, то можно продолжить изменять диапазоны и оценивать новые получаемые результаты, пока не достигнем желаемого.
Будем считать, что такие параметры оптимизации нас устроили.
Перенос параметров оптимизации в проект
Давайте сначала скопируем параметры оптимизации из тестера стратегий. Для этого достаточно кликнуть и перейти в тестере стратегий на вкладку входных параметров (Inputs) и нажать комбинацию клавиш Ctrl + C (скопировать в буфер). Там окажется такой текст:
idTask_=0 fileName_=database.sqlite symbol_=EURUSD period_=5 ; === Параметры сигнала к открытию signalSeqLen_=6||4||1||8||Y periodATR_=28||28||2||210||N ; === Параметры отложенных ордеров stopLevel_=25000.0||1||0.01||5||Y takeLevel_=3630.0||1||0.01||5||Y ; === Параметры управление капиталом maxCountOfOrders_=10||1||1||10||N maxSpread_=100||10||1||100||N
Как можно догадаться, в каждой строке у нас находится информация об одном параметре или комментарий, если строка начинается с символа ";". Параметры, которые могут участвовать в оптимизации, имеют в своей строке несколько значений, разделённых комбинацией "||". Первое значение — это значение параметра по умолчанию, затем идут: минимальное значение, шаг, максимальное значение и буква Y или N, обозначающая участие этого параметра в оптимизации (Y — участвует, N — не участвует).
Первые две строки нам нужно отбросить, так как эти параметры будут устанавливаться автоматически:
symbol_=EURUSD period_=5 ; === Параметры сигнала к открытию signalSeqLen_=6||4||1||8||Y periodATR_=28||28||2||210||N ; === Параметры отложенных ордеров stopLevel_=25000.0||1||0.01||5||Y takeLevel_=3630.0||1||0.01||5||Y ; === Параметры управление капиталом maxCountOfOrders_=10||1||1||10||N maxSpread_=100||10||1||100||N
В оставшейся части у нас остаются два места, в которые при запуске конвейера автоматической оптимизации должны будут подставляться разные значения:
symbol_=EURUSD period_=5 ; === Параметры сигнала к открытию signalSeqLen_=6||4||1||8||Y periodATR_=28||28||2||210||N ; === Параметры отложенных ордеров stopLevel_=25000.0||1||0.01||5||Y takeLevel_=3630.0||1||0.01||5||Y ; === Параметры управление капиталом maxCountOfOrders_=10||1||1||10||N maxSpread_=100||10||1||100||N
Такую заготовку нужно перенести в файл создания проекта оптимизации Optimization/CreateProject.1968401.mq5 в функцию paramsTemplate1(), и оформить её в виде строковой константы, в которую будут подставляться строковое значение с названием символа и число, обозначающее таймфрейм:
// Шаблон параметров оптимизации на первом этапе string paramsTemplate1(COptimizationProject *p) { string params = StringFormat( "symbol_=%s\n" "period_=%d\n" "; === Параметры сигнала к открытию\n" "signalSeqLen_=6||4||1||8||Y\n" "periodATR_=28||28||2||210||N\n" "; === Параметры отложенных ордеров\n" "stopLevel_=25000.0||1||0.01||5||Y\n" "takeLevel_=3630.0||1||0.01||5||Y\n" "; === Параметры управление капиталом\n" "maxCountOfOrders_=10||1||1||10||N\n" "maxSpread_=100||10||1||100||N\n", p.m_symbol, p.StringToTimeframe(p.m_timeframe)); return params; }
Напомним, что файл создания проекта можно назвать произвольно, мы просто воспользовались уже существующим в репозитории файлом.
Сделанные изменения касаются задания параметров отдельных запусков оптимизации советника первого этапа в тестере стратегий. Теперь необходимо ещё указать параметры, которые относятся к первому этапу в целом.
Настройка общих параметров первого этапа
Эти параметры задаются в том же файле создания проекта оптимизации (Optimization/CreateProject.1968401.mq5). Вот как они выглядят в исходном коде:
sinput group "::: Этап 1. Поиск" sinput string stage1ExpertName_ = "Stage1.ex5"; // - Советник этапа sinput string stage1Criterions_ = "6,6,6,6,6,6"; // - Критерии оптимизации для задач sinput long stage1MaxDuration_ = 120; // - Макс. продолж. задач (с)
Посмотрим на каждый параметр:
- stage1ExpertName_ — советник этапа. Название скомпилированного файла советника первого этапа. Мы использовали имя Stage1.mq5 в проектном репозитории для этого советника, поэтому после компиляции получим имя Stage1.ex5. В принципе, нет особых причин менять его от проекта к проекту. Поэтому этот параметр можно не трогать.
- stage1Criterions_— критерии оптимизации для задач. Этот параметр должен содержать одну или несколько цифр в диапазоне от 0 до 7, разделённых запятыми. Он выполняет сразу две задачи.
Во-первых, количество цифр определяет, сколько раз будет запускаться процесс оптимизации для одного набора входных параметров. В данном примере у нас есть шесть значений через запятую. Значит, при запуске первого этапа каждая его работа (job), то есть группа задач, относящаяся к одной возможной комбинации символ/таймфрейм, будет состоять из шести задач (task).
Во-вторых, цифры задают используемый критерий оптимизации для каждой задачи оптимизации. Сейчас они все одинаковы и равны 6, что означает использование пользовательского критерия (Custom max). Остальные значения приведены в таблице:
В начале развития проекта мы использовали разные критерии в пределах одной работы. Это повышало разнообразие получаемых комбинаций параметров, подбираемых в разных процессах оптимизации. Но после разработки критерия нормированной среднегодовой прибыли, постепенно перешли к использованию только этого критерия. С ним тоже получается достаточное разнообразие.Значение Критерий 0 Balance max 1 Profit Factor max 2 Expected Payoff max 3 Drawdown min 4 Recover Factor max 5 Sharpe Ratio max 6 Custom max 7 Complex Criterion max - stage1MaxDuration_ — максимальная продолжительность задач в секундах. При пробных запусках на имеющихся мощностях агентов тестирования мы получаем возможность оценить время, затрачиваемое на один процесс оптимизации (или задачу оптимизации). Наблюдая за процессом вживую, можно заметить, что достаточно хорошие результаты встречаются и гораздо раньше, чем тестер решит завершить оптимизацию. Поэтому мы можем сократить общее время первого этапа автоматической оптимизации, если ограничим время выполнения одной задачи. Сделать это можно, указав в этом параметре число, большее 0. Если будет указан 0, то это означает отсутствие ограничения по времени.
В результате пробных запусков мы решили ограничить время двумя минутами, то есть 120 секундами.
На этом предварительную работу по настройке параметров первого этапа проекта можно считать завершённой.
Напоследок давайте посмотрим, как выглядят графики нескольких случайных проходов из полученных ранее результатов оптимизации.
GBPUSD:

EURUSD:

EURGBP:

График GBPUSD выглядит лучше остальных. EURUSD и EURGBP имеют периоды падения и роста, но в целом растут. Причем периоды падения у них не всегда точно совпадают. Это как раз даёт возможность улучшить торговые результаты при объединении работы торговой стратегии на нескольких инструментах одновременно, повысив устойчивость.
Заключение
В рамках данной статьи мы углубились в два важных аспекта работы с библиотекой Adwizard, которые могут остаться за кадром. Во-первых, мы столкнулись с практической проблемой: отсутствием базы данных итогового советника для первого проекта после выполнения конвейера оптимизации. Анализ показал, что причина кроется в сбое на втором этапе — задачи оптимизации завершились почти мгновенно, не успев выполнить ни одного прохода в тестере стратегий. Хотя точную первопричину установить не удалось (возможны как временные проблемы с загрузкой истории котировок, так и особенности работы бета-версий терминала), мы продемонстрировали возможный способ восстановления.
Во-вторых, и что гораздо существеннее, мы подробно разобрали подготовительную работу, предшествующую созданию проекта оптимизации. Успешное применение конвейера автоматической оптимизации подразумевает проведение предварительного анализа, направленного на выявление нежелательных эффектов. Например, простое задание «широких» диапазонов параметров часто приводит к неэффективному использованию вычислительных ресурсов и попаданию в локальные максимумы, а разные торговые инструменты могут демонстрировать принципиально разное поведение при одних и тех же параметрах стратегии.
Предварительная оптимизация вручную позволяет выявить избыточные оптимизируемые параметры, сократив размерность задачи и повысив качество финальных результатов. Компромисс между разнообразием проходов и их статистической значимостью требует балансировки диапазонов параметров, чтобы достигнуть разумного минимума по количеству сделок.
Но мы ещё не закончили рассмотрение шага создания проекта. В состав проекта входит три этапа. В рамках данной статьи мы рассмотрели подготовку параметров только первого из них. В следующих частях мы перейдём к подготовке параметров для второго и третьего этапа.
Спасибо за внимание, и до новых встреч!
Важное предупреждение
Все результаты, изложенные в этой статье и всех предшествующих статьях цикла, основываются только на данных тестирования на истории и не являются гарантией получения хоть какой-то прибыли в будущем. Работа в рамках данного проекта носит исследовательский характер. Все опубликованные результаты могут быть использованы всеми желающими на свой страх и риск.
| # | Имя | Версия | Описание | Последние изменения |
|---|---|---|---|---|
| SimpleCandles | Рабочая папка проекта (внутри MQL5/Shared Projects) | |||
| 1 | SimpleCandles-MQ-100K-10.mq5 SimpleCandles-MQ-200K-07.mq5 SimpleCandles-MQ-300K-05.mq5 | 1.05 | Итоговые советники для параллельной работы нескольких групп модельных стратегий. Параметры будут браться из встроенной библиотеки групп. Их может быть больше, каждый из них может использоваться как шаблон | Часть 30 |
| └ Optimization | Папка советников оптимизации проекта | |||
| 2 | CreateProject.1968401.mq5 CreateProject.1968401.mq5 CreateProject.1968401.mq5 | 1.06 1.05 1.05 | Советник-скрипт создания проекта с этапами, работами и задачами оптимизации. | Часть 31 |
| 3 | Optimization.mq5 | 1.03 | Советник для автоматической оптимизации проектов | Часть 29 |
| 4 | Stage1.mq5 | 1.04 | Советник оптимизации одиночного экземпляра торговой стратегии (Этап 1) | Часть 30 |
| 5 | Stage2.mq5 | 1.04 | Советник оптимизации группы экземпляров торговых стратегий (Этап 2) | Часть 30 |
| 6 | Stage3.mq5 | 1.04 | Советник, сохраняющий сформированную нормированную группу стратегий в базу данных эксперта с заданным именем. | Часть 30 |
| └ Strategies | Папка стратегий проекта | Часть 25 | ||
| 7 | SimpleCandlesStrategy.mqh | 1.03 | Класс торговой стратегии SimpleCandles | Часть 30 |
| Adwizard | Папка библиотеки Adwizard (внутри MQL5/Shared Projects) | |||
| └ Base | Базовые классы, от которых наследуются другие классы проекта | |||
| 8 | Advisor.mqh | 1.04 | Базовый класс эксперта | Часть 10 |
| 9 | Factorable.mqh | 1.06 | Базовый класс объектов, создаваемых из строки | Часть 28 |
| 10 | FactorableCreator.mqh | 1.00 | Класс создателей, связывающих названия и статические конструкторы классов-наследников CFactorable | Часть 24 |
| 11 | Interface.mqh | 1.01 | Базовый класс визуализации различных объектов | Часть 4 |
| 12 | Receiver.mqh | 1.04 | Базовый класс перевода открытых объемов в рыночные позиции | Часть 12 |
| 13 | Strategy.mqh | 1.04 | Базовый класс торговой стратегии | Часть 10 |
| └ Database | Файлы для работы со всеми типами баз данных, используемых советниками проекта | |||
| 14 | Database.mqh | 1.13 | Класс для работы с базой данных | Часть 29 |
| 15 | db.adv.schema.sql | 1.00 | Схема базы данных итогового советника | Часть 22 |
| 16 | db.cut.schema.sql | 1.00 | Схема урезанной базы данных оптимизации | Часть 22 |
| 17 | db.opt.schema.sql | 1.06 | Схема базы данных оптимизации | Часть 29 |
| 18 | Storage.mqh | 1.01 | Класс работы с хранилищем Key-Value для итогового советника в базе данных эксперта | Часть 23 |
| └ Experts | Файлы с общими частями используемых советников разного типа | |||
| CreateProject.mqh | 1.07 | Библиотечный файл для советника-скрипта создания проекта с этапами, работами и задачами оптимизации | Часть 30 | |
| 19 | Expert.mqh | 1.24 | Библиотечный файл для итогового советника. Параметры групп могут браться базы данных эксперта | Часть 28 |
| 20 | Optimization.mqh | 1.06 | Библиотечный файл для советника, управляющего запуском задач оптимизации | Часть 29 |
| 21 | Stage1.mqh | 1.19 | Библиотечный файл для советника оптимизации одиночного экземпляра торговой стратегии (Этап 1) | Часть 23 |
| 22 | Stage2.mqh | 1.04 | Библиотечный файл для советника оптимизации группы экземпляров торговых стратегий (Этап 2) | Часть 23 |
| 23 | Stage3.mqh | 1.04 | Библиотечный файл для советника, сохраняющего сформированную нормированную группу стратегий в базу данных эксперта с заданным именем. | Часть 23 |
| └ Optimization | Классы, отвечающие за работу автоматической оптимизации | |||
| 24 | OptimizationJob.mqh | 1.00 | Класс для работы этапа проекта оптимизации | Часть 25 |
| 25 | OptimizationProject.mqh | 1.00 | Класс для проекта оптимизации | Часть 25 |
| 26 | OptimizationStage.mqh | 1.00 | Класс для этапа проекта оптимизации | Часть 25 |
| 27 | OptimizationTask.mqh | 1.01 | Класс для задачи оптимизации (для создания) | Часть 29 |
| 28 | Optimizer.mqh | 1.04 | Класс для менеджера автоматической оптимизации проектов | Часть 29 |
| 29 | OptimizerTask.mqh | 1.06 | Класс для задачи оптимизации (для конвейера) | Часть 29 |
| └ Strategies | Примеры торговых стратегий, используемые для демонстрации работы проекта | |||
| 24 | HistoryStrategy.mqh | 1.00 | Класс торговой стратегии воспроизведения истории сделок | Часть 16 |
| 25 | SimpleVolumesStrategy.mqh | 1.11 | Класс торговой стратегии с использованием тиковых объемов | Часть 22 |
| └ Utils | Вспомогательные утилиты, макросы для сокращения кода | |||
| 26 | ConsoleDialog.mqh | 1.01 | Класс для вывода текстовой информации на график | Часть 28 |
| 26 | ExpertHistory.mqh | 1.00 | Класс для экспорта истории сделок в файл | Часть 16 |
| 27 | Macros.mqh | 1.07 | Полезные макросы для операций с массивами | Часть 26 |
| 28 | MTTester.mqh | — | Файл для работы с тестером стратегий из библиотеки MultiTester | Часть 28 |
| 29 | NewBarEvent.mqh | 1.00 | Класс определения нового бара для конкретного символа | Часть 8 |
| 30 | SymbolsMonitor.mqh | 1.01 | Класс получения информации о торговых инструментах (символах) | Часть 28 |
| └ Virtual | Классы для создания различных объектов, объединённых использованием системы виртуальных торговых ордеров и позиций | |||
| 31 | Money.mqh | 1.01 | Базовый класс управления капиталом | Часть 12 |
| 32 | TesterHandler.mqh | 1.07 | Класс для обработки событий оптимизации | Часть 23 |
| 33 | VirtualAdvisor.mqh | 1.12 | Класс эксперта, работающего с виртуальными позициями (ордерами) | Часть 28 |
| 34 | VirtualChartOrder.mqh | 1.02 | Класс графической виртуальной позиции | Часть 28 |
| 35 | VirtualCloseManager.mqh | 1.00 | Класс менеджера закрытия | Часть 28 |
| 36 | VirtualHistoryAdvisor.mqh | 1.00 | Класс эксперта воспроизведения истории сделок | Часть 16 |
| 37 | VirtualInterface.mqh | 1.00 | Класс графического интерфейса советника | Часть 4 |
| 38 | VirtualOrder.mqh | 1.09 | Класс виртуальных ордеров и позиций | Часть 22 |
| 39 | VirtualReceiver.mqh | 1.04 | Класс перевода открытых объемов в рыночные позиции (получатель) | Часть 23 |
| 40 | VirtualRiskManager.mqh | 1.06 | Класс управления риском (риск-менеждер) | Часть 28 |
| 41 | VirtualStrategy.mqh | 1.09 | Класс торговой стратегии с виртуальными позициями | Часть 23 |
| 42 | VirtualStrategyGroup.mqh | 1.04 | Класс группы торговых стратегий или групп торговых стратегий | Часть 28 |
| 43 | VirtualSymbolReceiver.mqh | 1.00 | Класс символьного получателя | Часть 3 |
Также исходный код доступен в публичных репозиториях SimpleCandles и Adwizard
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Оптимизация Роем Жуков — Beetle Swarm Optimization (BSO)
Возможности Мастера MQL5, которые вам нужно знать (Часть 62): Использование паттернов ADX и CCI с обучением с подкреплением TRPO
Нейросети в трейдинге: Гибридные модели прогнозирования с управляемой смесью распределений (Основные компоненты)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования