Автоматизация запуска терминала для выполнения сервисных задач
Содержание
- Введение
- Запуск платформы из конфигурационного файла
- Программная обработка запуска из конфигурационного файла
- Периодический запуск терминала по расписанию
- Полный цикл автоматизации средствами Windows
- Заключение
Введение
Начиная с MetaTrader 5 build 4230 для пользователей платформы появилась интересная возможность:
- В терминале добавлена поддержка параметра ShutdownTerminal в секции [StartUp] пользовательских конфигурационных файлов. Параметр используется, чтобы запускать платформу для выполнения одноразовых задач при помощи скриптов. Например, у вас есть скрипт, который делает скриншот графика. Вы создаете конфигурационный файл, который запускает этот скрипт вместе с платформой. Если добавить в него ShutdownTerminal со значением «Yes», платформа будет автоматически выключаться сразу после завершения работы скрипта.
- В языке MQL5 добавлено свойство MQL_STARTED_FROM_CONFIG в перечисление ENUM_MQL_INFO_INTEGER. Возвращает true, если скрипт/эксперт запущен из секции StartUp конфигурационного файла. Это означает, что данный скрипт/эксперт был прописан в конфигурационном файле, с которым запущен терминал.
Что даёт нам запуск терминала с конфигурационным файлом? Такой запуск может выполняться, например, из командной строки, либо ярлыка программы или скрипта с заранее прописанными ключами запуска. Соответственно, мы можем не только вручную запустить платформу с определённым конфигурационным файлом, но и выполнить запуск из Планировщика заданий Windows. Для такого запуска нужно заранее определить конфигурационный файл и указать его для запуска клиентского терминала.
Представим такую ситуацию: у нас постоянно запущен простой торгующий эксперт и хотелось бы его время от времени переоптимизировать на ближайшей проторгованной истории. Значит, мы должны периодически, например, раз в неделю или месяц, запускать оптимизацию его параметров и смотреть по результатам новые оптимальные настройки его параметров. Можно автоматизировать этот процесс так, чтобы клиентский терминал сам запускался, например, в выходные в указанное время, запускал в оптимизаторе наш эксперт и по результатам создавал xml-файл, из которого мы можем выбрать нужные оптимальные значения параметров. По окончании оптимизации и создания файла отчёта терминал закроется сам, и нам останется только запустить файл отчёта из папки расположения данных терминала для его анализа.
Кроме того, если советник при его запуске из конфигурационного файла в тестере должен делать что-то дополнительное, но при этом не делать этих же действий в боевом режиме, то мы можем, анализируя флаг MQL_STARTED_FROM_CONFIG, сделать ветвление в программе для обработки такого запуска. Это может быть, например, анализ последней истории торговли, снятие скриншотов экрана со сделками, и тому подобное. Всё это мы легко можем сделать, используя новые возможности клиентского терминала.
Запуск платформы из конфигурационного файла
Торговая платформа может быть запущена с пользовательским набором параметров. Для этого на основе оригинального файла настроек common.ini нужно создать собственный файл. Для запуска платформы с этим файлом настроек нужно выполнить в командной строке команду:
путь_к_платформе\terminal64.exe /config:c:\myconfiguration.ini
где "c:\myconfiguration.ini" — это путь к собственному конфигурационному файлу.
Параметры конфигурационного файла поделены на несколько блоков и соответствуют настройкам на вкладках окна настройки платформы.
Наиболее важные параметры в конфигурационном файле можно посмотреть в справке по клиентскому терминалу.
Не обязательно прописывать в собственном конфигурационном файле все настройки и параметры. Достаточно указать только необходимые параметры для запуска нужного скрипта или советника в нужном режиме. Все недостающие параметры будут взяты из текущих настроек терминала и тестера.
Например, у нас терминал, предназначенный для запуска из командной строки, расположен по пути C:\Program Files\MetaTrader 5\terminal64.exe. Чтобы открыть каталог данных этого терминала, нужно нажать сочетание клавиш Shift+Ctrl+D. В каталоге данных в подпапке config\ находится оригинальный файл с настройками терминала common.ini. На основе этого файла нужно создать собственный, который будет указываться при запуске терминала из командной строки.
Рассмотрим различные аспекты запуска терминала из командной строки.
Программная обработка запуска из конфигурационного файла
Напишем такой скрипт в папке MQL5\Scripts\MT5 Automation\Test_STARTED_FROM_CONFIG.mq5:
//+------------------------------------------------------------------+ //| Test_STARTED_FROM_CONFIG.mq5 | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- string text=(MQLInfoInteger(MQL_STARTED_FROM_CONFIG) ? "Started from config" : "Started manually"); Alert(StringFormat("MT5 Automation Test Script: %s",text)); }
При обычном запуске скрипта в терминале будет выведен алерт с сообщением:
MT5 Automation Test Script: Started manually
Теперь подготовим данные для запуска терминала из командной строки.
Откроем файл MQL5\config\common.ini и создадим на его основе конфигурационный файл:
[Common] Login=98271878 Server=MetaQuotes-Demo [Charts] ProfileLast=default MaxBars=50000 TradeHistory=1 TradeLevels=1 [StartUp] Script=MT5 Automation\Test_STARTED_FROM_CONFIG Symbol=EURUSD Period=H1 Template=default.tpl
Здесь в секции [Common] указаны
- логин (номер счёта),
- сервер, на котором зарегистрирован этот счёт.
В секции [StartUp] указаны
- путь к файлу тестового скрипта относительно подпапки MQL5\Scripts\ в каталоге данных терминала,
- символ, на котором будет запущен скрипт: EURUSD,
- период графика: H1,
- шаблон, применяемый к этому графику: определённый по умолчанию для новых графиков (default.tpl).
Нужно указывать любой из своих доступных счётов, чтобы терминал мог свободно к ним подключиться во время автоматического запуска.
Сохраним файл в папке, например, C:\MetaQuotes\Scripts\TestConfig.ini. Такой путь выбран просто для краткости и удобства — в этот каталог будем сохранять все тестовые файлы и скрипты, создаваемые в рамках данного обсуждения — чтобы всё находилось в одном месте, путь был коротким, понятным и не требовал длинного ввода ключей запуска скриптов.
Исходя из расположения исполняемого файла терминала в папке C:\Program Files\MetaTrader 5\terminal64.exe и конфигурационного файла в папке C:\MetaQuotes\Scripts\TestConfig.ini команда для автозапуска будет такой:
C:\Program Files\MetaTrader 5\terminal64.exe /config:C:\MetaQuotes\Scripts\TestConfig.ini
Теперь можно ввести команду:
terminal64.exe /config:C:\MetaQuotes\Scripts\TestConfig.ini
в командной строке Windows, предварительно перейдя в каталог терминала командами cd.
Либо, что удобнее, выбрать из контекстного меню кнопки "Пуск" команду "Выполнить" и запустить терминал командой
C:\Program Files\MetaTrader 5\terminal64.exe /config:C:\MetaQuotes\Scripts\TestConfig.ini


Терминал будет запущен вместе с тестовым скриптом, который выведет такой алерт:
MT5 Automation Test Script: Started from config
Здесь скрипт определил, что запущен из конфигурационного файла, и вывел алерт с соответствующим сообщением.
Таким образом, проверяя значение, возвращаемое при запросе свойства программы MQL_STARTED_FROM_CONFIG, мы можем сделать любую нужную нам обработку при запуске программы из командной строки с пользовательским конфигурационным файлом. А значит, советник может спокойно торговать в боевом режиме при обычном его запуске на графике, но делать совсем иные вещи (аналитика, скриншоты, тестирование, оптимизация и т.п.) при его запуске из командной строки.
Кроме того, мы можем в скрипте в секции обработки запуска из конфигурационного файла, по окончании заложенной в эту секцию логики, принудительно закрыть терминал:
if(MQLInfoInteger(MQL_STARTED_FROM_CONFIG)) { // ... some code of yours TerminalClose(return_code); }
И более того, код завершения терминала мы можем прочитать в скрипте, из которого была выполнена команда на открытие терминала с конфигурационным файлом. Таким образом, возвращая нужные коды завершения работы терминала, мы можем снаружи обрабатывать эти коды для организации логики ветвления в скрипте, из которого был открыт терминал.
Напишем такой тестовый скрипт с именем Test_STARTED_FROM_CONFIG_2.mq5:
//+------------------------------------------------------------------+ //| Test_STARTED_FROM_CONFIG_2.mq5 | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #define SYMBOL "AUDUSD" #define PERIOD PERIOD_H1 #define COUNT 10000 #define ATTEMPTS 3 #define WAIT 1000 //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- Объявим переменные и распечатаем в журнал способ запуска терминала int err_code=0, received=0; bool config_start=(bool)MQLInfoInteger(MQL_STARTED_FROM_CONFIG); string text=(config_start ? "Started from config" : "Started manually"); Alert(StringFormat("MT5 Automation Test Script: %s",text)); //--- Если запуск из командной строки с конфигурационным файлом if(config_start) { //--- В цикле по количеству ATTEMPTS попыток for(int i=0;i<ATTEMPTS;i++) { //--- распечатаем в журнале номер попытки PrintFormat("Receiving %s data. Attempt %d",SYMBOL,i+1); //--- Получаем данные символа SYMBOL в количестве COUNT и сохраняем код возврата //--- Если всё успешно - прерываем цикл, иначе - ждём WAIT секунд и повторяем err_code=GetSymbolData(received); //--- Распечатаем количество полученных данных PrintFormat("Received: %d",received); if(err_code==0) break; Print("..."); Sleep(WAIT); } Print("All attempts completed"); //--- По завершении всех попыток получения данных символа //--- закрываем терминал с указанием кода возврата err_code TerminalClose(err_code); } } //+------------------------------------------------------------------+ //| Получает данные по символу SYMBOL в количестве COUNT | //+------------------------------------------------------------------+ int GetSymbolData(int &data_received) { int err=0, copied=0; double array[]; //--- Запрашиваем данные символа SYMBOL в количестве COUNT ResetLastError(); copied=CopyClose(SYMBOL,PERIOD,0,COUNT,array); err=GetLastError(); //--- Если количество скопированных данных не равно запрошенному if(copied!=COUNT) { //--- Если нет ошибки, значит ещё не все данные получены. //--- Укажем код ошибки ERR_HISTORY_NOT_FOUND if(err==0) err=ERR_HISTORY_NOT_FOUND; PrintFormat("%s: CopyClose(%s, H1, 0 - %d) failed. Error %d",__FUNCTION__,SYMBOL,COUNT,err); } data_received=copied; return err; } //+------------------------------------------------------------------+
Скрипт запрашивает некоторое количество баров истории по указанному в макроподстановках символе. Дано три попытки получения данных и скрипт завершает свою работу закрытием терминала. Кодом завершения работы терминала будет код ошибки, полученной при запросе исторических данных. И этот код мы можем прочитать средствами Windows после окончания работы терминала.
Этот скрипт пропишем в конфигурационном файле TestConfig.ini:
[Common] Login=98271878 Server=MetaQuotes-Demo [Charts] ProfileLast=default MaxBars=50000 TradeHistory=1 TradeLevels=1 [StartUp] Script=MT5 Automation\Test_STARTED_FROM_CONFIG_2 Symbol=EURUSD Period=H1 Template=default.tpl
Теперь из командной строки будет открываться терминал с конфигурационным файлом, в котором прописан новый скрипт с именем Test_STARTED_FROM_CONFIG_2.mq5.
В каталоге C:\MetaQuotes\Scripts\ создадим новый текстовый файл и сохраним его под именем RunTest_STARTED_FROM_CONFIG_2.cmd.
Это будет тестовый скрипт, в котором пропишем запуск терминала с конфигурационным файлом и простая логика обработки кода возврата, получаемого при закрытии терминала:
@echo off CHCP 1251 > nul ECHO Запускаем терминал с файлом конфигурации TestConfig.ini... "C:\Program Files\MetaTrader 5\terminal64.exe" /config:C:\MetaQuotes\Scripts\TestConfig.ini REM Сразу же после завершения процесса terminal64.exe проверяем ERRORLEVEL IF %ERRORLEVEL% EQU 0 ( ECHO ================================================== ECHO Терминал завершил работу без ошибок. Код возврата: %ERRORLEVEL% ECHO ================================================== ) ELSE ( ECHO ================================================== ECHO Терминал завершил работу с ошибкой. Код возврата: %ERRORLEVEL% ECHO ================================================== ) PAUSE
Теперь, если запустить этот скрипт на выполнение двойным щелчком, то откроется терминал, выполнит прописанный в конфигурационном файле скрипт и закроется. Сразу же после закрытия терминала в консоль будет выведена запись о результате работы терминала и запущенного в нём скрипта.
Таким образом можно писать сложную логику работы терминала в зависимости от кодов возврата, возвращаемых терминалом при его закрытии.
А эти коды мы сами можем устанавливать в зависимости от того, как отработал запущенный в терминале скрипт.
Это даёт нам гибкие возможности по созданию различных сценариев автозапуска терминала с различными конфигурационными файлами.
Периодический запуск терминала по расписанию
Запуск простого абстрактного скрипта для тестов даст мало конкретики. Давайте рассмотрим всё на примере реального советника из CodeBase.
Код, опубликованный в Библиотеке исходных кодов, можно загрузить непосредственно из редактора, и он будет расположен в папке Downloads\ соответствующей категории.
Относительно предложенного для загрузки советника, он будет расположен в папке \MQL5\Experts\Downloads\ExpWPRBB.mq5.
Давайте создадим конфигурационный файл для запуска советника из командной строки:
[Common] Login=98271878 Server=MetaQuotes-Demo [Experts] AllowLiveTrading=0 [Tester] Expert=Downloads\ExpWPRBB Symbol=EURUSD Period=H4 Model=0 ExecutionMode=0 Optimization=1 OptimizationCriterion=0 Report=Reports\ExpWPRBB_report ReplaceReport=1
В разделе [Common] указываем
- номер счёта
- сервер, на которых будет проводиться оптимизация.
В разделе [Experts] торговля экспертами запрещена.
В разделе [Tester] указываем:
- имя тестируемого советника и путь к нему относительно папки MQL5\Experts\,
- символ и период графика, на которых будет проводиться оптимизация,
- режим генерации тиков (0 — все тики),
- режим торговли, эмулируемой тестером стратегий (0 — обычный режим),
- оптимизация включена — полный перебор параметров,
- критерий оптимизации — максимальное значение баланса,
- имя файла отчёта оптимизации и путь к нему относительно каталога данных терминала,
- каждый последующий файл отчёта переписывать (заменять новым).
Сохраним этот файл в каталоге C:\MetaQuotes\Scripts\ под именем ExpWPRBBconfig01.ini — это будет наш первый конфигурационный файл для тестирования запуска оптимизации советника из командной строки.
Теперь можно ввести такую команду в поле ввода компонента Windows "Выполнить":
C:\Program Files\MetaTrader 5\terminal64.exe /config:C:\MetaQuotes\Scripts\ExpWPRBBconfig01.ini 
Терминал будет запущен с включенной оптимизацией советника:

По окончании оптимизации терминал останется открытым, а файл отчёта будет записан в каталог данных терминала в подпапку Reports\ с именем ExpWPRBB_report.xml, который можно запустить в MS Excel и просмотреть результаты оптимизации.
На данном этапе оптимизация дала отрицательные результаты, так как в терминале установлен период, за который проводится оптимизация, "Последний месяц". Если начинать оптимизацию в первых числах нового месяца с периодом "За последний месяц", то тест начнётся с календарного начала месяца, и будет проведён всего за несколько дней (в данном случае — за шесть).
Чтобы избежать такого несоответствия (ведь тест мы хотим провести за месячный период, а не за календарное количество дней с начала месяца), нужно в конфигурационном файле указывать даты начала и окончания теста. К этому вернёмся позже. А пока решим, что такие "тесты ради тестов" просто с запуском отдельного терминала из командной строки познавательны, но не интересны. Чтобы получить пользу от возможности запуска терминала из командной строки в указанной конфигурации, необходимо сделать, например, автоматический запуск терминала в нужное время и нужную дату.
Начиная с Windows NT 4.0 и включая Windows 7, 8, 10, 11 в операционной системе есть "Планировщик заданий" — стандартный системный компонент администрирования, предназначенный для автоматизации выполнения рутинных задач, скриптов и программ в ОС. Это простой и удобный компонент, где мы легко сможем настроить задачу запуска терминала из командной строки с конфигурационным файлом.
В планировщике мы можем создать нужную нам задачу, которая будет выполняться по наступлению указанного события, например, наступления нужного времени.
Открыть интерфейс "Планировщика заданий" можно несколькими способами:
1. Через поиск- Нажать на кнопку "Пуск" или значок поиска (лупа) на панели задач;
- Начать вводить текст: "Планировщик заданий", или "Task Scheduler";
- Щелкнуть по найденному приложению.
- Нажать комбинацию клавиш Win + R;
- В появившемся окне ввести команду: "taskschd.msc";
- Нажать Enter или "ОК".
- Открыть "Панель управления";
- Перейти в раздел "Система и безопасность";
- Нажать "Администрирование";
- Найти и запустить "Планировщик заданий".
При выполнении любого из этих пунктов откроется Планировщик заданий Windows:

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

В следующем окне выбираем "Ежедневно" и нажимаем кнопку "Далее":

В следующем окне нам будет предложено ввести дату, с которой начнётся обрабатываться задача, время начала выполнения задачи и её периодичность.
Вводим нужную дату и время и устанавливаем периодичность в 1 день, то есть ежедневно, и нажимаем кнопку "Далее":

В следующем окне выбираем "Запустить программу" и нажимаем кнопку "Далее":

В следующем окне в поле "Программа или сценарий" вводим путь к терминалу и его исполняемый файл, либо выбираем его через кнопку "Обзор".
В поле аргументов вводим ключ, с которым должен запускаться терминал ( /config:C:\MetaQuotes\Scripts\ExpWPRBBconfig01.ini ), и нажимаем кнопку "Далее":

Откроется последнее окно со всеми параметрами созданной задачи:

Нажимаем кнопку "Готово", и задача появляется в корне Библиотеки планировщика задач. Её можно найти в верхнем центральном окне планировщика:

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

Здесь выбран пункт "Последний месяц", и оптимизация начинается с даты начала месяца. Мы уже говорили про эту неподходящую для нашей задачи особенность. Хотелось бы проводить тест за период, длиной в месяц, а не от начала текущего месяца. К данному вопросу вернёмся чуть позже, а на данный момент посмотрим, что мы теперь имеем.
Мы создали задачу, которая будет ежедневно запускать указанный терминал в три часа ночи, оптимизировать параметры, и файл отчёта записывать в каталог данных терминала в подпапку Reports\ в файл ExpWPRBB_report.xml.
Какие есть здесь недостатки:
- оптимизация проводится за период, установленный в настройках оптимизации в терминале;
- по окончании оптимизации терминал не закрывается и остаётся запущенным.
Для исправления недостатка 2 нужно в конфигурационном файле в секции [Tester] прописать флаг закрытия терминала:
[Common] Login=98271878 Server=MetaQuotes-Demo [Experts] AllowLiveTrading=0 [Tester] Expert=Downloads\ExpWPRBB Symbol=EURUSD Period=H4 Model=0 ExecutionMode=0 Optimization=1 OptimizationCriterion=0 Report=Reports\ExpWPRBB_report ReplaceReport=1 ShutdownTerminal=1
Теперь терминал будет автоматически закрываться по окончании оптимизации. Но с периодом оптимизации дела обстоят иначе.
Можно, конечно, сделать запуск каждую неделю и оптимизировать только последний месяц. Такой подход в большинстве случаев будет работать и приносить некоторый результат только ближе к концу месяца для конкретно этого советника ввиду небольшого количества сделок.
В итоге при таком подходе получается, необходимо настроить автозапуск терминала на конец месяца и запускать автоматическую переоптимизацию параметров раз в месяц.
Давайте посмотрим, какие ещё есть возможности.
В терминале из предустановленных периодов оптимизации есть:
- вся история — это много для переоптимизации,
- последний месяц — работает (выбирает период оптимизации) не так, как нам необходимо,
- последний год — тоже не подходит по двум вышеперечисленным причинам,
- указанный период — подходит, но с нюансами.
Итак, видим, что для нас подойти может только вариант с вручную устанавливаемыми датами. Конфигурационный файл позволяет установить нужные даты начала и окончания оптимизации:
[Common] Login=98271878 Server=MetaQuotes-Demo [Experts] AllowLiveTrading=0 [Tester] Expert=Downloads\ExpWPRBB Symbol=EURUSD Period=H4 Model=0 ExecutionMode=0 Optimization=1 OptimizationCriterion=0 FromDate=2025.10.06 ToDate=2025.11.06 Report=Reports\ExpWPRBB_report ReplaceReport=1 ShutdownTerminal=1
Но в таком случае получается, что для каждого автозапуска необходимо вручную прописывать нужные даты в файл. Давайте сохраним его в папке C:\MetaQuotes\Scripts\ под именем ExpWPRBBconfig.ini и заменим в строке аргументов автозапуска имя конфигурационного файла на новое.
Вернёмся к планировщику заданий, найдём созданное задание и дважды щёлкнем на нём. Откроется окно свойств. Войдём на вкладку "Действия", выберем строку действия и нажмём кнопку "Изменить":

В открывшемся окошке в поле аргументов поменяем имя конфигурационного файла на новое:

Нажмём ОК в обоих окнах, сохранив тем самым изменения.
Запустим задачу. Теперь оптимизация производится на указанном в конфигурационном файле отрезке времени:

После завершения оптимизации терминал автоматически закрывается.
Посмотреть результаты оптимизации можно в автоматически создаваемом файле отчёта (каталог_данных_терминала)\Reports\ExpWPRBB_report.xml.
Остаётся открытым вопрос: как изменять даты оптимизации? Здесь видятся два варианта:
- перед каждым автоматическим запуском предварительно вручную изменять даты в конфигурационном файле;
- сделать скрипт, который будет производить такие действия в автоматическом режиме.
Естественно, нам видится более удобным и практичным второй вариант. Рассмотрим какие есть возможности.
Полный цикл автоматизации средствами Windows
Итак, нам необходимо решить вопрос автоматической установки дат начала и окончания оптимизации в конфигурационном файле. Если перед каждым запуском автоматически устанавливать требуемые даты в файл, то проблема периода оптимизации будет решена. И да, мы можем такое сделать при помощи PowerShell-скриптов. Скрипт будет искать в конфигурационном файле даты, рассчитывать новые и заменять найденные строки с датами на рассчитанные значения.
В операционной системе MS Windows ранее основным инструментом автоматизации была классическая Командная строка (CMD). Но с развитием технологий, начиная с Windows XP SP2 и Windows Server 2003 (и став стандартом в Windows 7 и далее), появился PowerShell.
PowerShell — это мощный инструмент командной строки, представляющий собой одновременно и оболочку, и язык сценариев (скриптовый язык), разработанный корпорацией Microsoft. Он является ключевым инструментом для автоматизации задач системного администрирования в среде Windows.
Скрипт можно написать в обычном блокноте, но лучше воспользоваться встроенной утилитой для написания, редактирования и тестирования PowerShell-скриптов. Чтобы открыть редактор, можно в строке поиска ввести "ise" и запустить найденную программу Windows PowerShell ISE:

Откроется среда разработки PowerShell, где удобно писать и отлаживать свои скрипты:

Напишем первый скрипт, который устанавливает недельный период оптимизации:
# Путь к конфигурационному файлу для запуска MetaTrader 5 $filePath = "c:\MetaQuotes\Scripts\ExpWPRBBconfig.ini" # Вычисляем новые даты # Дата начала: 7 дней назад от текущей даты $fromDate = (Get-Date).AddDays(-7).ToString("yyyy.MM.dd") # Дата окончания: Текущая дата $toDate = (Get-Date).ToString("yyyy.MM.dd") # Читаем содержимое файла и заменяем строки с датами (Get-Content -Path $filePath) -replace '^FromDate=.*$', "FromDate=$fromDate" ` -replace '^ToDate=.*$', "ToDate=$toDate" | Set-Content -Path $filePath # Выводим информацию в консоль для отладки Write-Host "Даты в файле $filePath обновлены." Write-Host "FromDate установлен в $fromDate" Write-Host "ToDate установлен в $toDate"
Скрипт от текущей даты отнимает 7 дней и записывает получившуюся дату как начало оптимизации. Датой конца оптимизации скрипт устанавливает текущую дату.
После выполнения скрипта консоль автоматически закрывается. Чтобы оставить консоль открытой для чтения отладочных сообщений, нужно последней строкой в скрипте прописать такую строчку:
Read-Host -Prompt "Нажмите Enter для выхода или закройте окно" Хорошо. Если нам нужно установить месячный период оптимизации, то скрипт будет таким:
# Путь к конфигурационному файлу для запуска MetaTrader 5 $filePath = "c:\MetaQuotes\Scripts\ExpWPRBBconfig.ini" # Вычисляем новые даты # Дата начала: месяц назад от текущей даты $fromDate = (Get-Date).AddMonths(-1).ToString("yyyy.MM.dd") # Дата окончания: Текущая дата $toDate = (Get-Date).ToString("yyyy.MM.dd") # Читаем содержимое файла и заменяем строки с датами (Get-Content -Path $filePath) -replace '^FromDate=.*$', "FromDate=$fromDate" ` -replace '^ToDate=.*$', "ToDate=$toDate" | Set-Content -Path $filePath # Выводим информацию в консоль для отладки Write-Host "Даты в файле $filePath обновлены." Write-Host "FromDate установлен в $fromDate" Write-Host "ToDate установлен в $toDate"
Разница в двух представленных скриптах только в строке расчёта даты.
Соответственно, чтобы установить период тестирования в один год, нужно от текущей даты отнимать один год:
# Путь к конфигурационному файлу для запуска MetaTrader 5 $filePath = "c:\MetaQuotes\Scripts\ExpWPRBBconfig.ini" # Вычисляем новые даты # Дата начала: 1 год назад от текущей даты $fromDate = (Get-Date).AddYears(-1).ToString("yyyy.MM.dd") # Дата окончания: Текущая дата $toDate = (Get-Date).ToString("yyyy.MM.dd") # Читаем содержимое файла и заменяем строки с датами (Get-Content -Path $filePath) -replace '^FromDate=.*$', "FromDate=$fromDate" ` -replace '^ToDate=.*$', "ToDate=$toDate" | Set-Content -Path $filePath # Выводим информацию в консоль для отладки Write-Host "Даты в файле $filePath обновлены." Write-Host "FromDate установлен в $fromDate" Write-Host "ToDate установлен в $toDate"
То есть мы можем сделать некоторое количество отдельных скриптов для установки периодов оптимизации и запускать их по нужному условию.
Однако, лучше объединить такие скрипты в один, и передавать в него аргументом требуемый период оптимизации:
# Путь к конфигурационному файлу MetaTrader 5 $filePath = "C:\MetaQuotes\Scripts\ExpWPRBBconfig.ini" # Получаем первый аргумент, переданный скрипту. # Если аргумент не указан (пустой), используем 'Month' по умолчанию. [string]$IntervalType = $args[0] if([string]::IsNullOrEmpty($IntervalType)) { $IntervalType = 'Month' } # Вычисляем дату начала в зависимости от переданного параметра $today = Get-Date switch($IntervalType) { 'Day' { $fromDate = $today.AddDays(-1) Write-Host "Режим: Ежедневный (-1 день)" } 'Week' { $fromDate = $today.AddDays(-7) Write-Host "Режим: Еженедельный (-7 дней)" } 'Month' { $fromDate = $today.AddMonths(-1) Write-Host "Режим: Ежемесячный (-1 месяц)" } 'Quarter' { $fromDate = $today.AddMonths(-3) Write-Host "Режим: Ежеквартальный (-3 месяца)" } 'Year' { $fromDate = $today.AddYears(-1) Write-Host "Режим: Ежегодный (-1 год)" } default { $fromDate = $today.AddMonths(-1) Write-Host "Режим по умолчанию: Ежемесячный (-1 месяц)" } } # Форматируем даты: 1. дата начала 2. дата окончания $fromDateString = $fromDate.ToString("yyyy.MM.dd") $toDateString = $today.ToString("yyyy.MM.dd") # Заменяем строки в файле (Get-Content -Path $filePath) -replace '^FromDate=.*$', "FromDate=$fromDateString" ` -replace '^ToDate=.*$', "ToDate=$toDateString" | Set-Content -Path $filePath # Выводим информацию в консоль для отладки Write-Host "Даты в файле $filePath успешно обновлены." Write-Host "FromDate установлен в $fromDateString" Write-Host "ToDate установлен в $toDateString"
Этот последний скрипт сохраним в папке C:\MetaQuotes\Scripts\ под именем UpdateDates.ps1.
Этот скрипт можно просто запустить из папки его расположения, выбрав из контекстного меню ПКМ пункт "Выполнить с помощью PowerShell", либо из среды разработки нажатием F5 (если в системе разрешён запуск сценариев, отключенный по умолчанию), либо из командной строки или bat-файла, а также из Планировщика заданий. Для его запуска нужно указать нужный аргумент, по которому будет определяться период оптимизации: последние сутки, последняя неделя, месяц, квартал или год. Если скрипт будет запущен без аргументов, то по умолчанию выбирается месячный период оптимизации. Скрипт просто изменяет даты оптимизации в прописанном в начале скрипта конфигурационном файле и сохраняет его с новыми датами. Далее обновлённый конфигурационный файл будет использоваться для запуска платформы.
Видим, что нам необходимо произвести два действия:
- запустить скрипт для установки периода оптимизации в конфигурационном файле (указав при этом нужный период),
- запустить клиентский терминал с обновлённым конфигурационным файлом.
Напрашивается создание и последовательный запуск двух задач в Планировщике заданий — изменение периода оптимизации и запуск терминала.
Но можно прописать все эти действия в одном файле и уже его запускать как единую задачу. Этот вариант интереснее. Напишем такой cmd-файл:
@echo off REM Переключаем кодировку консоли на кириллицу для читаемости вывода CHCP 1251 > nul REM Запускаем PowerShell-скрипт для обновления дат в INI-файле powershell -ExecutionPolicy Bypass -File C:\MetaQuotes\Scripts\UpdateDates.ps1 REM Пауза 3 секунды timeout /t 3 /nobreak > nul REM Запускаем терминал MetaTrader 5, используя уже обновленный файл INI start "" "C:\Program Files\MetaTrader 5\terminal64.exe" /config:C:\MetaQuotes\Scripts\ExpWPRBBconfig.ini
Запуск этого файла повлечёт за собой изменение периода оптимизации на 1 месяц и далее запустит терминал с конфигурационным файлом для оптимизации параметров.
Нам нужно указывать нужный период оптимизации. Для этого потребуется доработать наш пакетный файл таким образом, чтобы он принимал внешний аргумент для передачи его в PS-скрипт:
@echo off CHCP 1251 > nul REM Определяем переданный параметр (например, Day, Week, Month) REM Если параметр не указан, то по умолчанию будет "Month" IF "%1"=="" (SET Interval=Month) ELSE (SET Interval=%1) REM Запускаем скрипт с помощью 64-битной версии PowerShell для обновления дат в INI-файле REM Передаем переменную %Interval% как аргумент C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -File C:\MetaQuotes\Scripts\UpdateDates.ps1 %Interval% REM Пауза 3 секунды timeout /t 3 /nobreak > nul REM Запускаем терминал MetaTrader 5, используя уже обновленный файл INI start "" "C:\Program Files\MetaTrader 5\terminal64.exe" /config:C:\MetaQuotes\Scripts\ExpWPRBBconfig.ini
Сохраним этот файл в папке C:\MetaQuotes\Scripts\ под именем Optimize_MT5_AutoDate.cmd.
Важное замечание: все скрипты нужно сохранять в кодировке ANSI, иначе могут быть ошибки чтения одного скрипта другим.
Запустим файл двойным щелчком по нему. Откроется терминал с месячным периодом оптимизации (по умолчанию без аргументов) и запустится оптимизация параметров советника. По окончании оптимизации файл с результатами будет записан в (каталог данных терминала)\Reports\ExpWPRBB_report.xml.
Если теперь попытаться создать несколько заданий для запуска автоматической оптимизации для разных периодов оптимизации, то мы столкнёмся с неприятными "сюрпризами":
- Файл результатов оптимизации перезаписывается новыми результатами, и он только один. То есть для любого периода оптимизации в файле будут содержаться результаты самой последней из всех выполненных;
- Мы не можем предугадать время, затрачиваемое на завершение каждой последующей оптимизации и, соответственно, запуски заданий могут пересечься по времени, что блокирует запуск следующей задачи, пока предыдущая не завершена.
Для решения первой проблемы нам нужно не только изменять даты начала и окончания оптимизации в конфигурационном файле, но и изменять имя файла отчёта так, чтобы он своим названием точно указывал на период оптимизации.
Чтобы запуски оптимизаций из Планировщика заданий точно не пересекались, создадим единый скрипт, из которого и будем запускать всю нужную цепочку запусков оптимизаций по разным периодам. В этот новый скрипт будем передавать в аргументах список периодов и в цикле запускать оптимизации одну за другой. Это точно ограничит запуск следующей оптимизации до тех пор, пока не будет завершена предыдущая.
Доработаем скрипт UpdateDates.ps1. Теперь в нём будет создаваться уникальное имя файла отчёта в зависимости от периода оптимизации и дат её начала и окончания:
# Путь к конфигурационному файлу MetaTrader 5 $filePath = "C:\MetaQuotes\Scripts\ExpWPRBBconfig.ini" # Базовое имя эксперта/отчета $expertName = "ExpWPRBB" # Путь для сохранения отчетов (относительно каталога данных MetaTrader 5, как в INI-файле) $reportPathBase = "Reports\" # Получаем первый аргумент, переданный скрипту [string]$IntervalType = $args[0] if ([string]::IsNullOrEmpty($IntervalType)) { $IntervalType = 'Month' } $today = Get-Date switch($IntervalType) { 'Day' { $fromDate = $today.AddDays(-1) Write-Host "Режим: Ежедневный (-1 день)" } 'Week' { $fromDate = $today.AddDays(-7) Write-Host "Режим: Еженедельный (-7 дней)" } 'Month' { $fromDate = $today.AddMonths(-1) Write-Host "Режим: Ежемесячный (-1 месяц)" } 'Quarter' { $fromDate = $today.AddMonths(-3) Write-Host "Режим: Ежеквартальный (-3 месяца)" } 'Year' { $fromDate = $today.AddYears(-1) Write-Host "Режим: Ежегодный (-1 год)" } default { $fromDate = $today.AddMonths(-1) Write-Host "Режим по умолчанию: Ежемесячный (-1 месяц)" } } # Форматируем даты: 1. дата начала 2. дата окончания $fromDateString = $fromDate.ToString("yyyy.MM.dd") $toDateString = $today.ToString("yyyy.MM.dd") # Генерируем уникальное имя отчета, используя даты и интервал $reportName = "${expertName}_${IntervalType}_${fromDateString}_to_${toDateString}" $fullReportPath = $reportPathBase + $reportName # Заменяем строки в файле (FromDate, ToDate и Report) (Get-Content -Path $filePath) ` -replace '^FromDate=.*$', "FromDate=$fromDateString" ` -replace '^ToDate=.*$', "ToDate=$toDateString" ` -replace '^Report=.*$', "Report=$fullReportPath" | Set-Content -Path $filePath # Выводим информацию в консоль для отладки Write-Host "Даты и путь отчета в файле $filePath успешно обновлены." Write-Host "FromDate установлен в $fromDateString" Write-Host "ToDate установлен в $toDateString" Write-Host "Report установлен в $fullReportPath"
Теперь для каждого отчёта будет создаваться собственный уникальный файл, что позволит полностью контролировать все результаты различных оптимизаций.
Доработаем скрипт Optimize_MT5_AutoDate.cmd:
@echo off IF "%1"=="" ( ECHO Ошибка: Не указан интервал оптимизации (Day, Week, Month, Quarter, Year). EXIT /B 1 ) REM Устанавливаем интервал оптимизации SET Interval=%1 ECHO --- Запуск оптимизации для интервала: %Interval% --- REM Фиксируем время начала выполнения SET StartTime=%TIME% ECHO Время начала: %StartTime% REM Запускаем скрипт UpdateDates.ps1 с помощью 64-битной версии PowerShell для обновления дат в INI-файле REM Передаем переменную %Interval% как аргумент C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -File C:\MetaQuotes\Scripts\UpdateDates.ps1 %Interval% REM Пауза 3 секунды перед запуском MT5 timeout /t 3 /nobreak > nul REM Запускаем терминал MetaTrader 5 и ждем его завершения ECHO Запуск терминала MT5. Ожидание завершения оптимизации... "C:\Program Files\MetaTrader 5\terminal64.exe" /config:C:\MetaQuotes\Scripts\ExpWPRBBconfig.ini REM Фиксируем время окончания выполнения SET EndTime=%TIME% ECHO Время окончания: %EndTime% ECHO --- Оптимизация %Interval% завершена ---
Теперь здесь нет значения по умолчанию (период оптимизации Месяц) потому, что скрипт будет вызываться из главного с передачей в него аргумента, и нам нужно точно отслеживать правильность его вызова (наличие аргумента с периодом оптимизации). Поэтому скрипт проверяет наличие аргумента и, если его нет — завершается с ошибкой. Также здесь добавлен вывод в консоль времени запуска терминала и времени его закрытия по окончании оптимизации.
Для контроля за работой скрипта добавлен вывод некоторых сообщений в консоль. Теперь этот скрипт будем запускать из главного скрипта с указанием аргументов оптимизации.
Напишем общий, главный скрипт, который и будем запускать из Планировщика заданий с указанием требуемых периодов оптимизации в аргументах запуска:
@echo off CHCP 1251 > nul ECHO =================================================== ECHO СТАРТ ОБЩЕЙ ЦЕПОЧКИ АВТОМАТИЗАЦИИ METAQUOTES MT5 ECHO Время начала: %TIME% ECHO =================================================== REM Счётчик ошибок SET ErrorCount=0 REM Если при запуске не указан ни один аргумент - возвращаем ошибку IF "%~1"=="" ( ECHO Ошибка: В главный скрипт не переданы интервалы оптимизации. Завершаем работу EXIT /B 1 ) REM Выведем на консоль все интервалы оптимизации ECHO Переданные интервалы: %* REM В цикле по количеству аргументов запускаем оптимизацию скриптом Optimize_MT5_AutoDate.cmd :Loop IF "%~1" NEQ "" ( ECHO --------------------------------------------------- REM Вызываем скрипт Optimize_MT5_AutoDate.cmd с указанием текущего аргумента в %1 REM Во время работы скрипт выводит в консоль время начала и конца текущей оптимизации CALL C:\MetaQuotes\Scripts\Optimize_MT5_AutoDate.cmd %1 REM Проверяем результат вызова скрипта Optimize_MT5_AutoDate.cmd на ошибки выполнения IF %ERRORLEVEL% NEQ 0 ( ECHO !!! ОШИБКА !!! Скрипт для интервала %1 завершился с кодом ошибки %ERRORLEVEL% SET /A ErrorCount+=1 ) ELSE ( ECHO Оптимизация %1 успешно завершена ) REM Получаем следующий аргумент SHIFT GOTO Loop ) ECHO =================================================== ECHO ВСЕ ЗАДАЧИ ЦЕПОЧКИ ОБРАБОТАНЫ ECHO Общее количество ошибок: %ErrorCount% ECHO Время окончания: %TIME% ECHO =================================================== IF %ErrorCount% NEQ 0 ( EXIT /B 1 ) ELSE ( EXIT /B 0 )
Сохраним скрипт в папку C:\MetaQuotes\Scripts\ под именем RunOptimizations.cmd (не забываем о кодировке ANSI). Его и будем запускать из Планировщика заданий.
Выше мы уже разбирались как создать простую задачу в Планировщике заданий. Сейчас уже не будем подробно и пошагово рассматривать создание задачи, а просто пройдёмся по всем пунктам мастера создания заданий.
Давайте создадим отдельную папку "MT5 automation" для задач оптимизации:

После создания папки MT5 automation, выбираем из её контекстного меню пункт "Создать простую задачу":

Откроется уже знакомый нам мастер создания простой задачи, где и будем создавать задачи для запуска терминала и оптимизации параметров советника.
Скрипт UpdateDates.ps1, устанавливающий даты начала и окончания оптимизации, принимает в качестве аргументов значения Day, Week, Month, Quarter и Year, что устанавливает даты и именование файла отчёта для оптимизации за последние- сутки,
- неделю,
- месяц,
- квартал,
- год.
Для советника, обсуждаемого в рамках этой статьи, оптимизация за последние сутки не требуется — слишком мало сделок за этот период, да и недельная оптимизация тоже не даёт стабильных результатов.
Поэтому для нас здесь важны остальные периоды — оптимизация за месяц, квартал и год.
Можно попробовать сделать переоптимизацию параметров таким образом:
- раз в неделю — за последнюю неделю, и месяц;
- раз в месяц — за последний месяц и квартал;
- раз в квартал — за последний квартал и год.
При создании задач необходимо следить за тем, чтобы они не пересекались по времени запуска. Т.е. если одна задача уже запущена и выполняется, то следующую запускать не нужно. Для упрощения будем разносить задачи по времени их запуска.
Чтобы попытаться исключить пересечение задач, мы должны обеспечить минимальный промежуток между задачами, равный максимально возможному времени выполнения самой длинной оптимизации. Минимальные промежутки между запуском разных задач зависят от того, насколько долго выполняется каждая конкретная оптимизация для каждого конкретного советника, системы, ПК.
Мы не можем точно знать, сколько времени займет каждая оптимизация в каждой из задач. Она может длиться 5 минут, а может — 5 часов, в зависимости от:
- сложности советника,
- размера периода и способа оптимизации,
- количества тестируемых параметров.
Но мы можем попытаться разнести все задачи по времени так, чтобы максимально обезопасить себя от пересечения разных по времени выполнения задач. В одной задаче выполняется два запуска оптимизации, и они точно следуют друг за другом, так как запускаются одним скриптом. Но три отдельные задачи (по два запуска оптимизаций в каждой) в планировщике могут пересечься. И вот эти-то задачи нам и следует запускать, отводя на каждую примерно по 12 часов в выходные дни.
Самая короткая по времени задача должна запускаться в начале субботы. Следующая задача — тоже в субботу, но в 12:00, а последняя, самая продолжительная — в 00:00 воскресенья. Таким образом на первые две задачи мы отводим по 12 часов на каждую, а последняя — самая длительная задача, получает на свою работу 24 часа.
Давайте создадим три такие задачи. Будем считать, что Планировщик заданий у нас уже открыт и папка MT5 automation создана. Теперь мы просто щёлкаем по ней правой кнопкой мышки и из контекстного меню выбираем самый первый пункт "Создать простую задачу..." После этого откроется мастер создания простой задачи.
Рассмотрим последовательность создания всех трёх задач в этом мастере (для каждой новой задачи нужно заново запускать мастер создания простых задач).
Задача 1. Быстрая по времени оптимизация. Запускается каждую субботу в 00:00
- Задание имени и описания:
- Имя: указываем 1. MT5_Optimization_Short_Term,
- Описание: вписываем Запуск коротких оптимизаций в начале каждых выходных,
- Нажимаем «Далее»,
- Настройка триггера:
- Выбираем «Еженедельно»,
- Нажимаем «Далее»,
- Начать: устанавливаем время 00:00:00 и текущую дату,
- Повторять каждую: указываем 1 неделю,
- Дни недели: ставим галочку в «суббота»,
- Нажимаем «Далее»,
- Настройка действия:
- Выбираем «Запустить программу»,
- Нажимаем «Далее»,
- Программа или сценарий: указываем C:\MetaQuotes\Scripts\RunOptimizations.cmd
- Добавить аргументы: вводим Week Month
- Нажимаем «Далее»,
- Сводка:
- Нажимаем «Готово».
Задача 2. Средняя по времени оптимизация. Запускается в последнюю субботу каждого месяца в 12:00
- Задание имени и описания:
- Имя: указываем 2. MT5_Optimization_Medium_Term,
- Описание: вписываем Запуск оптимизаций средней длительности в последнюю субботу месяца,
- Нажимаем «Далее»,
- Настройка триггера:
- Выбираем «Ежемесячно»,
- Нажимаем «Далее»,
- Начать: устанавливаем время 12:00:00,
- Месяцы: выбираем <Выбрать все месяцы>,
- Дни/В:
- Устанавливаем переключатель в положение «В»,
- В первом выпадающем списке выбираем «посл.»,
- Во втором выпадающем списке выбираем «суббота»,
- Нажимаем «Далее»,
- Настройка действия:
- Выбираем «Запустить программу»,
- Нажимаем «Далее».
- Программа или сценарий: указываем C:\MetaQuotes\Scripts\RunOptimizations.cmd,
- Добавить аргументы: вводим Month Quarter,
- Нажимаем «Далее»,
- Сводка:
- Нажимаем «Готово».
Задача 3. Долгая по времени оптимизация. Запускается в последнее воскресенье января, апреля, июля и октября в 00:00
- Задание имени и описания:
- Имя: указываем 3. MT5_Optimization_Long_Term,
- Описание: вписываем Ежеквартальный запуск самых долгих оптимизаций в последнее воскресенье квартала,
- Нажимаем «Далее»,
- Настройка триггера:
- Выбираем «Ежемесячно»,
- Нажимаем «Далее».
- Начать: устанавливаем время 00:00:00 и текущую дату,
- Месяцы: выбираем в маркированном списке нужные месяцы: Январь, Апрель, Июль, Октябрь,
- Дни/В:
- Устанавливаем переключатель в положение «В»,
- В первом выпадающем списке выбираем «посл.»,
- Во втором выпадающем списке выбираем «воскресенье»,
- Нажимаем «Далее».
- Настройка действия:
- Выбираем «Запустить программу»,
- Нажимаем «Далее»,
- Программа или сценарий: указываем C:\MetaQuotes\Scripts\RunOptimizations.cmd,
- Добавить аргументы: вписываем Quarter Year,
- Нажимаем «Далее».
- Сводка:
- Нажимаем «Готово».
Давайте создадим эти три задачи и запустим первую на выполнение, выбрав её в списке задач, и в правом окне в разделе "Выбранный элемент" нажав на "Выполнить".
Хорошо, если всё запустится и отработает как запланировано. Но может быть так, что никаких видимых результатов мы не увидим...
Что ж, нужно разобраться с проблемой. Вот что встретилось автору при запуске и после анализа ошибок:
- Интерпретатор очень "ревностно" относится к разным пробелам, переносам строк, и попаданием в текст скриптов управляющих символов. Запуск скриптов заканчивался ошибкой "Непредвиденное появление: .."
- Консоль скрыта, и отладочных сообщений не видно.
ОК. Давайте уберём удобное для человеческого глаза форматирование логики в тексте скриптов и напишем всё, где это возможно, однострочно, плюс сделаем вывод сообщений в лог-файл для последующего чтения и анализа.
PowerShell-скрипт UpdateDates.ps1:
# Путь к конфигурационному файлу MetaTrader 5
$filePath = "C:\MetaQuotes\Scripts\ExpWPRBBconfig.ini"
# Базовое имя эксперта/отчета
$expertName = "ExpWPRBB"
# Путь для сохранения отчетов (относительно рабочей папки MT5, как в INI-файле)
$reportPathBase = "Reports\"
# Получаем первый аргумент, переданный скрипту.
[string]$IntervalType = $args[0]
if ([string]::IsNullOrEmpty($IntervalType))
{
$IntervalType = 'Month'
}
$today = Get-Date
switch($IntervalType)
{
'Day'
{
$fromDate = $today.AddDays(-1)
Write-Host "Режим: Ежедневный (-1 день)"
}
'Week'
{
$fromDate = $today.AddDays(-7)
Write-Host "Режим: Еженедельный (-7 дней)"
}
'Month'
{
$fromDate = $today.AddMonths(-1)
Write-Host "Режим: Ежемесячный (-1 месяц)"
}
'Quarter'
{
$fromDate = $today.AddMonths(-3)
Write-Host "Режим: Ежеквартальный (-3 месяца)"
}
'Year'
{
$fromDate = $today.AddYears(-1)
Write-Host "Режим: Ежегодный (-1 год)"
}
default
{
$fromDate = $today.AddMonths(-1)
Write-Host "Режим по умолчанию: Ежемесячный (-1 месяц)"
}
}
# Форматируем даты: 1. дата начала 2. дата окончания
$fromDateString = $fromDate.ToString("yyyy.MM.dd")
$toDateString = $today.ToString("yyyy.MM.dd")
# Генерируем уникальное имя отчета, используя даты и интервал
$reportName = "${expertName}_${IntervalType}_${fromDateString}_to_${toDateString}"
$fullReportPath = $reportPathBase + $reportName
# Заменяем строки в файле (FromDate, ToDate и Report)
(Get-Content -Path $filePath) `
-replace '^FromDate=.*$', "FromDate=$fromDateString" `
-replace '^ToDate=.*$', "ToDate=$toDateString" `
-replace '^Report=.*$', "Report=$fullReportPath" | Set-Content -Path $filePath
# Выводим информацию в консоль для отладки
Write-Host "Даты и путь отчета в файле $filePath успешно обновлены."
Write-Host "FromDate установлен в $fromDateString"
Write-Host "ToDate установлен в $toDateString"
Write-Host "Report установлен в $fullReportPath"
#Для чтения сообщений раскомментировать строку ниже
#Read-Host -Prompt "Нажмите Enter для продолжения..." Пакетный сценарий (cmd-скрипт) Optimize_MT5_AutoDate.cmd:
@echo off REM Это дочерний скрипт, вызывается из RunOptimizations.cmd IF "%1"=="" (ECHO Ошибка: Не указан интервал оптимизации. & EXIT /B 1) SET Interval=%1 ECHO --- Запуск оптимизации для интервала: %Interval% --- SET StartTime=%TIME% ECHO Время начала: %StartTime% REM Запускаем PowerShell-скрипт (его вывод перенаправляется в лог родительским скриптом) C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -File C:\MetaQuotes\Scripts\UpdateDates.ps1 %Interval% timeout /t 3 /nobreak > nul ECHO Запуск терминала MT5. Ожидание завершения оптимизации... "C:\Program Files\MetaTrader 5\terminal64.exe" /config:C:\MetaQuotes\Scripts\ExpWPRBBconfig.ini SET EndTime=%TIME% ECHO Время окончания: %EndTime%
Главный пакетный сценарий (cmd-скрипт) RunOptimizations.cmd:
@echo off CHCP 1251 > nul SET LogFile=C:\MetaQuotes\Scripts\optimization_log.txt ECHO [Начало] %DATE% %TIME% > %LogFile% ECHO =================================================== >> %LogFile% ECHO СТАРТ ОБЩЕЙ ЦЕПОЧКИ АВТОМАТИЗАЦИИ METAQUOTES MT5 >> %LogFile% ECHO Время начала: %TIME% >> %LogFile% ECHO =================================================== >> %LogFile% SET ErrorCount=0 IF "%~1"=="" (ECHO Ошибка: В главный скрипт не переданы интервалы оптимизации. Завершаем работу >> %LogFile% & EXIT /B 1) ECHO Переданные интервалы: %* >> %LogFile% :Loop IF "%~1" NEQ "" ( ECHO --------------------------------------------------- >> %LogFile% CALL C:\MetaQuotes\Scripts\Optimize_MT5_AutoDate.cmd %1 >> %LogFile% 2>&1 IF %ERRORLEVEL% NEQ 0 ( ECHO !!! ОШИБКА !!! Скрипт для интервала %1 завершился с кодом ошибки %ERRORLEVEL% >> %LogFile% SET /A ErrorCount+=1 ) ELSE ( ECHO Оптимизация %1 успешно завершена >> %LogFile% ) SHIFT GOTO Loop ) ECHO =================================================== >> %LogFile% ECHO ВСЕ ЗАДАЧИ ЦЕПОЧКИ ОБРАБОТАНЫ >> %LogFile% ECHO Общее количество ошибок: %ErrorCount% >> %LogFile% ECHO Время окончания: %TIME% >> %LogFile% ECHO =================================================== >> %LogFile% ECHO [Конец] %DATE% %TIME% >> %LogFile% IF %ErrorCount% NEQ 0 (EXIT /B 1) ELSE (EXIT /B 0)
Все скрипты нужно сохранить в кодировке ANSI.
Давайте теперь запустим первую из трёх созданных задачу. После запуска видим пустую консоль (весь вывод перенаправлен в файл, а сделать вывод и в консоль, и в файл сложнее, чем просто видеть пустую консоль) и видим, как дважды запускается терминал с оптимизацией параметров (1 — недельный, 2 — месячный период) с автоматическим закрытием после завершения оптимизации.
Посмотрим в папке C:\MetaQuotes\Scripts\ лог-файл под именем optimization_log.txt:
[Начало] 10.11.2025 15:45:24,80 =================================================== СТАРТ ОБЩЕЙ ЦЕПОЧКИ АВТОМАТИЗАЦИИ METAQUOTES MT5 Время начала: 15:45:24,82 =================================================== Переданные интервалы: Week Month --------------------------------------------------- --- Запуск оптимизации для интервала: Week --- Время начала: 15:45:24,86 Режим: Еженедельный (-7 дней) Даты и путь отчета в файле C:\MetaQuotes\Scripts\ExpWPRBBconfig.ini успешно обновлены. FromDate установлен в 2025.11.03 ToDate установлен в 2025.11.10 Report установлен в Reports\ExpWPRBB_Week_2025.11.03_to_2025.11.10 Запуск терминала MT5. Ожидание завершения оптимизации... Время окончания: 15:51:11,11 Оптимизация Week успешно завершена --------------------------------------------------- --- Запуск оптимизации для интервала: Month --- Время начала: 15:51:11,15 Режим: Ежемесячный (-1 месяц) Даты и путь отчета в файле C:\MetaQuotes\Scripts\ExpWPRBBconfig.ini успешно обновлены. FromDate установлен в 2025.10.10 ToDate установлен в 2025.11.10 Report установлен в Reports\ExpWPRBB_Month_2025.10.10_to_2025.11.10 Запуск терминала MT5. Ожидание завершения оптимизации... Время окончания: 16:09:09,49 Оптимизация Month успешно завершена =================================================== ВСЕ ЗАДАЧИ ЦЕПОЧКИ ОБРАБОТАНЫ Общее количество ошибок: 0 Время окончания: 16:09:09,53 =================================================== [Конец] 10.11.2025 16:09:09,55
Хорошо. Посмотрим в каталоге данных терминала в подпапке Reports\ отчёты оптимизации. Видим два файла:
- ExpWPRBB_Week_2025.11.03_to_2025.11.10.xml — отчёт о недельном периоде оптимизации,
- ExpWPRBB_Month_2025.10.10_to_2025.11.10.xml — отчёт о месячном периоде оптимизации.
Вроде всё отлично. Но может остаться ещё одна проблема, о которой стоит упомянуть. Если теперь посмотреть статус успешно отработавшей задачи в Планировщике заданий, то увидим "Работает". Хм. Все процессы завершены успешно, в диспетчере задач в процессах отсутствуют процессы terminal64.exe, cmd.exe, powershell.exe, связанные с задачей. Это не зависание какого-либо из процессов. Значит, Планировщик заданий не может получить сообщение от вложенных запущенных скриптов об успешном завершении работы.
Это известная проблема Windows, которая зависит от версии ОС и обновлений. Так как скрипт уже делает все возможное для корректного завершения, остается только использовать административный метод контроля:
Необходимо настроить принудительное завершение задачи на вкладке «Параметры» Планировщика заданий — это стандартное, предусмотренное разработчиками Windows решение для таких ситуаций.Установите для каждой задачи ограничение по времени (например, 4 часа, либо больше в зависимости от планируемой продолжительности оптимизаций, запускаемых скриптами). Как только это время истечет, Windows принудительно обновит статус задачи на "Завершено", даже если она "зависла" в статусе "Работает". Можно даже сутки дать на выполнение задачи, а затем принудительно её завершить из планировщика в настройках задачи. В любом случае, каждый новый запуск производится не раньше следующей недели. Для ежедневных задач нужно давать часы на завершение —зависит от продолжительности конкретной оптимизации, запускаемой ежедневно. Но вопрос решаемый.
Всё. Мы подготовили все необходимые скрипты и создали три раздельные задачи для запуска различных по длительности оптимизаций. Теперь Планировщик задач возьмёт на себя всю заботу о регулярном запуске переоптимизации советника на разных промежутках тестирования. Все файлы результатов оптимизаций будут записываться в каталог данных терминала в подпапку Reports\, а имена файлов будут соответствовать продолжительности оптимизации времени её начала и окончания. Таким образом у нас под рукой всегда будут свежие данные о рекомендуемых важных параметрах советника. И далее — уже нам принимать решение о вводе новых параметров в советник, работающий на торговом счёте.
Заключение
Сегодня мы научились проводить автоматическую оптимизацию выбранного советника в клиентском терминале MetaTrader 5, используя связку из трех компонентов:- Скрипт PowerShell (.ps1) — динамически обновляет даты начала и окончания оптимизации в конфигурационном ini-файле и генерирует уникальные имена для файлов отчетов.
- Пакетные файлы (.cmd) — управляют логикой запуска. Главный скрипт последовательно вызывает дочерний для каждого интервала (Day, Week, Month, Quarter, Year), обеспечивая порядок выполнения и логирование результатов работы в единый лог-файл.
- Планировщик заданий Windows — используется для настройки расписания и автоматического запуска всех трех задач (еженедельной, ежемесячной, ежеквартальной) в непересекающееся время на выходных.
Используя простые скрипты и Планировщик заданий, можно разработать надежную и гибкую систему, которая позволит запускать сложные оптимизации без участия пользователя.
Но этим рассмотренные возможности не ограничиваются.
Помимо автоматической оптимизации параметров советника, подобным образом (через связку CMD/PowerShell + Планировщик заданий) можно автоматизировать множество других рутинных задач, связанных с MetaTrader 5, например:
- автоматический запуск контрольного тестирования,
- загрузка и обновление истории котировок,
- автоматическая перезагрузка торгового терминала,
- мониторинг и отправка уведомлений о состоянии терминала,
- резервное копирование рабочих папок, данных и логов,
- удаленное управление торговлей,
- и т.д.
Можно создать более сложные скрипты, которые взаимодействуют с файлами или API для отправки базовых команд (например, переключение торговых стратегий, изменение параметров риска) через Планировщик или по запросу.
Все эти задачи используют тот же подход: планировщик заданий запускает CMD/PowerShell-скрипт, который выполняет нужные действия с файлами, процессами и параметрами запуска терминала MetaTrader 5. При этом весь сервисный функционал может быть написан внутри торгующего советника, а определяться запуск из командной строки может самим советником и работать с блоком сервисных функций, не обращаясь к торговым функциям.
Скрипты и файлы, рассмотренные в рамках обсуждения темы автоматического запуска оптимизаций:
| Тип | Название | Назначение |
|---|---|---|
| PowerShell-скрипт | UpdateDates.ps1 | Вычисляет актуальные даты начала и окончания периода тестирования и обновляет соответствующие строки (FromDate, ToDate, Report) в конфигурационном ini-файле для запуска MetaTrader 5 |
| Пакетный файл, cmd-скрипт | Optimize_MT5_AutoDate.cmd | Дочерний (вызываемый) скрипт. Последовательно вызывает UpdateDates.ps1 для подготовки настроек и запускает терминал MetaTrader 5 (terminal64.exe) с обновленным ini-файлом для выполнения одной конкретной оптимизации |
| Пакетный файл, cmd-скрипт | RunOptimizations.cmd | Главный (родительский) скрипт. Управляет общей логикой автоматизации: принимает список интервалов (например, Week, Month), вызывает Optimize_MT5_AutoDate.cmd для каждого из них и собирает весь вывод в единый лог-файл |
| Конфигурационной ini-файл | ExpWPRBBconfig.ini | Файл настроек для терминала MetaTrader 5. Определяет параметры эксперта (Expert), торгового счета (Login, Server), инструмента (Symbol, Period), а также критически важные параметры тестирования/оптимизации (FromDate, ToDate, Optimization, ShutdownTerminal). Этот файл динамически изменяется скриптом UpdateDates.ps1 перед каждым запуском терминала |
| Конфигурационной ini-файл | ExpWPRBBconfig01.ini | Файл настроек для терминала MetaTrader 5.Используется в первом примере автоматизации запуска советника ExpWPRBB |
| MQL5-скрипт | Test_STARTED_FROM_CONFIG.mq5 | Скрипт для теста флага MQL_STARTED_FROM_CONFIG |
| MQL5-скрипт | Test_STARTED_FROM_CONFIG_2.mq5 | Скрипт для теста запуска терминала из cmd-скрипта с обработкой кодов возврата при закрытии терминала |
| Пакетный файл, cmd-скрипт | RunTest_STARTED_FROM_CONFIG_2.cmd | CMD-скрипт для запуска терминала с обработкой кодов возврата при закрытии терминала |
| Конфигурационной ini-файл | TestConfig.ini | Файл настроек для терминала MetaTrader 5. Используется в примере автоматизации запуска скрипта Test_STARTED_FROM_CONFIG.mq5 |
| Архив | MSScripts.zip | Архив со всеми скриптами, обсуждаемыми в рамках этой статьи |
Перед использованием всех скриптов и конфигурационного файла, необходимо вписать в них собственные наименования советника, конфигурации торгового счёта и пути к файлам.
Все рассмотренные файлы находятся в архиве, приложенном к статье. Архив MSScripts.zip можно распаковать в корень диска C:, и все файлы будут расположены в нужных подпапках. Файл советника можно взять в CodeBase.
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Машинное обучение и Data Science (Часть 33): Pandas Dataframe в MQL5, упрощаем сбор данных для машинного обучения
Нейросети в трейдинге: Рекуррентное моделирование микродвижений рынка (Энкодер)
Моделирование рынка (Часть 12): Сокеты (VI)
От новичка до эксперта: Утилита для управления параметрами
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Есть один нюанс, о котором автор не упомянул.
Если запустить на выполнение скрипт из конфига (не тестирование или оптимизацию на исторических данных, а именно скрипт на текущих данных!), то после окончания выполнения скрипта терминал продолжает работать.
Если вставить в конце скрипта строки
то клиентский терминал после выполнения скрипта будет остановлен.
Более того, код возврата сможет быть обработан в bat-файле запуска терминала.
Есть один нюанс, о котором автор не упомянул.
Если запустить на выполнение скрипт из конфига (не тестирование или оптимизацию на исторических данных, а именно скрипт на текущих данных!), то после окончания выполнения скрипта терминал продолжает работать.
Если вставить в конце скрипта строки
то клиентский терминал после выполнения скрипта будет остановлен.
Более того, код возврата сможет быть обработан в bat-файле запуска терминала.
Есть один нюанс, о котором автор не упомянул.
Если запустить на выполнение скрипт из конфига (не тестирование или оптимизацию на исторических данных, а именно скрипт на текущих данных!), то после окончания выполнения скрипта терминал продолжает работать.
Если вставить в конце скрипта строки
то клиентский терминал после выполнения скрипта будет остановлен.
Более того, код возврата сможет быть обработан в bat-файле запуска терминала.
Обновил и дополнил статью в разделе Программная обработка запуска из конфигурационного файла.
Спасибо, Слава.