Balance_Reset - библиотека для MetaTrader 5
Обновление:
Я значительно обновил эту библиотеку, которую я использую для оптимизации своих советников. Эта версия упрощена, но вы можете легко расширить ее, чтобы включить в нее повседневные задачи, которые вы, возможно, захотите автоматизировать. Например, вы можете добавить ограничения на торговлю после неудачного вызова проп-фирмы или возобновить торговлю в понедельник после успешного или неудачного вызова.
Все изменения и дополнения к этой библиотеке описаны в конце кода. Этот фреймворк является гибким и может быть адаптирован под ваши конкретные нужды, будь то добавление более сложной логики для торговых ограничений, планирование сделок или тонкая настройка производительности на основе результатов оптимизации.
Не стесняйтесь и дальше настраивать его под свои рутинные задачи!
Эта библиотека предназначена для тестирования советников (EA) в MetaTrader 5 с особым акцентом на требования собственной торговой компании. Цель - смоделировать торговую среду, в которой трейдер должен достичь определенных порогов прибыли и убытков, чтобы пройти испытание фирмы. Советник корректирует баланс счета, возвращая его к начальному значению при достижении заданных процентов прибыли или убытков, что имитирует правила многих проп-фирм.
Вот полная структура советника (EA), использующего библиотеку BalanceReset.mqh. Эта установка интегрирует логику сброса баланса непосредственно в советник, сохраняя чистое разделение функций с помощью директивы #include:
#include <BalanceReset.mqh> // Включите библиотеку сброса баланса //+------------------------------------------------------------------+ //| Функция инициализации эксперта| //+------------------------------------------------------------------+ int OnInit() { InitBalance(); // Инициализация начального баланса return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Функция экспертного тика| //+------------------------------------------------------------------+ void OnTick() { CheckBalanceAndReset(); // Проверка и сброс баланса на основе пороговых значений } //+------------------------------------------------------------------+ //| Функция деинициализации эксперта| //+------------------------------------------------------------------+ void OnDeinit(const int reason) { PrintBalanceResetResults(); // Выведите результаты сброса баланса в журнал }
Ключевые функции
-
Настраиваемые пороги прибыли и убытков
- Библиотека позволяет настраивать пороговые значения прибыли и убытков, которые вызывают сброс баланса в процессе бэктестинга. Эти пороги могут быть изменены с помощью входных параметров, что облегчает настройку условий тестирования.
Пример:
input double profit_threshold = 8.0; // Порог прибыли, по умолчанию 8% input double loss_threshold = -6.0; // Порог потерь, по умолчанию -6%.
2. Начальный баланс Инициализация
- Эта функция сохраняет начальный баланс счета в начале теста. Она запускается только на первом тике, чтобы зафиксировать начальный стартовый баланс.
Пример:
void InitBalance() { initial_balance = AccountInfoDouble(ACCOUNT_BALANCE); // Хранение начального баланса }
3. Логика сброса баланса
- Ядро библиотеки сверяет текущий баланс с начальным балансом, чтобы вычислить процент прибыли или убытка. Если прибыль превышает заданный порог (например, 8%) или убыток превышает порог (например, -6%), баланс сбрасывается до начального значения.
- Сброс прибыли: Функция TesterWithdrawal используется для снятия избыточной суммы, чтобы вернуть баланс к начальному значению при достижении порога прибыли.
- Сброс убытков: Функция TesterDeposit восстанавливает баланс до начального значения при достижении порога убытков.
Пример:
void CheckBalanceAndReset() { double current_balance = AccountInfoDouble(ACCOUNT_BALANCE); if (initial_balance == 0) { initial_balance = current_balance; // Первый тик, сохраните начальный баланс } double profit_percentage = (current_balance - initial_balance) / initial_balance * 100.0; if (profit_percentage >= profit_threshold) { double withdrawal_amount = current_balance - initial_balance; if (TesterWithdrawal(withdrawal_amount)) { successful_resets++; ArrayResize(reset_times, ArraySize(reset_times) + 1); reset_times[ArraySize(reset_times) - 1] = TimeCurrent(); Print("Profit reached. Balance has been reset to the initial value."); } } if (profit_percentage <= loss_threshold) { double deposit_amount = initial_balance - current_balance; if (TesterDeposit(deposit_amount)) { unsuccessful_resets++; ArrayResize(reset_times, ArraySize(reset_times) + 1); reset_times[ArraySize(reset_times) - 1] = TimeCurrent(); Print("Loss reached. Balance has been reset to the initial value."); } } }
4. Регистрация результатов
- После завершения теста эта функция выводит количество успешных сбросов (как для прибыли, так и для убытка) и количество дней между каждым сбросом. Это дает представление о том, как часто происходили сбросы баланса во время теста.
Пример:
void PrintBalanceResetResults() { PrintFormat("Number of successful profit resets: %d", successful_resets); PrintFormat("Number of successful loss resets: %d", unsuccessful_resets); for (int i = 1; i < ArraySize(reset_times); i++) { int days_between_resets = (reset_times[i] - reset_times[i-1]) / 86400; // 86400 секунд в одном дне PrintFormat("Days between reset %d and reset %d: %d days", i, i + 1, days_between_resets); } }

Заключение
Эта библиотека помогает смоделировать торговую среду, соответствующую общим требованиям собственных торговых компаний. Сбрасывая баланс при достижении заданных пороговых значений прибыли и убытков, она позволяет трейдерам более эффективно тестировать свои стратегии и анализировать работу советника на основе правил собственной торговой компании.
Описание изменений и дополнений кода:
Новый код содержит несколько улучшений и дополнений по сравнению со старым кодом. Ниже приведено подробное объяснение того, что было добавлено и изменено:
Новые входные параметры:
-
max_loss и min_won :
input double max_loss = 1; // Максимальная потеря input double min_won = 1; // Min won
Назначение: Эти входные параметры позволяют установить максимально допустимый убыток ( max_loss ) и минимальное количество необходимых успешных сбросов прибыли ( min_won ). Они обеспечивают больший контроль над условиями оптимизации.
Дополнительные переменные:
-
reset_status[] :
string reset_status[]; // Массив для хранения статуса каждого сброса
Назначение: Массив, добавленный для хранения статуса ("Сброс прибыли" или "Сброс убытков") каждого события сброса баланса.
stopOptimization :
bool stopOptimization = false;
Назначение: Флаг, используемый для указания того, когда оптимизация должна быть остановлена на основании определенных условий.
badResult :
bool badResult = false; // Флаг, указывающий на плохой результат оптимизации
Назначение: Флаг для пометки результата оптимизации как неблагоприятного, который может быть использован для влияния на результат в OnTester().
Изменения в CheckBalanceAndReset() :
-
Запись состояния сброса:
ArrayResize(reset_status, ArraySize(reset_status) + 1); // Измените размер массива для записи состояния сброса reset_status[ArraySize(reset_status) - 1] = "Profit reset"; // Запись состояния
Назначение: Когда происходит сброс прибыли, статус записывается в массив reset_status[].
Обработка сброса убытков с условием остановки оптимизации:
if (TesterDeposit(deposit_amount)) { unsuccessful_resets++; // Увеличиваем счетчик неудачных сбросов потерь // Запись времени и состояния сброса ArrayResize(reset_status, ArraySize(reset_status) + 1); reset_status[ArraySize(reset_status) - 1] = "Loss reset"; { stopOptimization = true; CheckStopCondition(); // Проверьте, следует ли остановить оптимизацию } PrintFormat("Loss reached. Balance has been reset to the initial value."); }
Цель: После сброса потерь код теперь инкрементирует unsuccessful_resets, записывает статус, устанавливает stopOptimization в true и вызывает CheckStopCondition(), чтобы определить, следует ли остановить оптимизацию.
Новая функция CheckStopCondition() :
void CheckStopCondition() { if(stopOptimization) { Print("Stopping current optimization pass"); badResult = true; // Пометьте результат как плохой TesterStop(); } }
Назначение: Эта функция проверяет, истинно ли значение stopOptimization, и, если да, помечает результат как плохой и останавливает текущий проход оптимизации с помощью TesterStop().
Новая функция OnTester() :
double OnTester() { // Если количество успешных сбросов меньше минимально необходимого или установлен badResult if(successful_resets < min_won || badResult) { Print("Optimization failed: returning a highly unfavorable result."); // Возвращаем крайне неблагоприятный результат, чтобы испортить оптимизационный проход return -999999; } // Вычислите разницу между успешными и неуспешными сбросами int reset_difference = successful_resets - unsuccessful_resets; // Проверьте, является ли разница отрицательной if(reset_difference < 0) { Print("Negative difference between successful and unsuccessful resets. Returning a highly unfavorable result."); // Возвращаем крайне неблагоприятный результат, если разница отрицательна return -999999; } // Выведите разницу в журнал PrintFormat("Difference between successful and unsuccessful resets: %d", reset_difference); // Верните разницу как результат работы тестера return reset_difference; }

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

Усовершенствования в функции PrintBalanceResetResults() :
// Выведите даты каждого сброса и количество дней между ними for(int i = 1; i < ArraySize(reset_times); i++) { // Вычислите количество дней между сбросами int days_between_resets = (reset_times[i] - reset_times[i-1]) / 86400; // 86400 секунд в одном дне // Выведите даты сброса, статус и дни между ними PrintFormat("Reset %d: %s (%s), Reset %d: %s (%s), Days between: %d days", i, TimeToString(reset_times[i-1], TIME_DATE), reset_status[i-1], i + 1, TimeToString(reset_times[i], TIME_DATE), reset_status[i], days_between_resets); }
Назначение: Теперь функция не только выводит количество сбросов, но и подробно описывает каждое событие сброса, включая дату, статус и количество дней между сбросами. Это позволяет получить более полный журнал действий по сбросу.
Инициализация и использование переменных:
-
Начальная проверка баланса:
if(initial_balance == 0) { initial_balance = current_balance; }
Назначение: Обеспечивает правильную установку начального_баланса при первом тике.
Расчет процента прибыли:
double profit_percentage = (current_balance - initial_balance) / initial_balance * 100.0;
Назначение: Вычисляет процент прибыли или убытка по отношению к начальному балансу.
Сводка дополнений:
-
Контроль над процессом оптимизации:
- Теперь в коде предусмотрены механизмы остановки процесса оптимизации на основе определенных условий, таких как превышение максимального количества неудачных сбросов или недостижение минимального количества успешных сбросов.
-
Улучшенное протоколирование и отслеживание:
- Добавление функции reset_status[] и подробное протоколирование в PrintBalanceResetResults() позволяет лучше отслеживать события сброса и их результаты.
-
Интеграция с Optimizer через OnTester() :
- Реализовав функцию OnTester(), скрипт может передавать результаты обратно в механизм оптимизации, влияя на выбор наборов параметров на основе пользовательских критериев.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная публикация: https://www.mql5.com/en/code/52163
