MetaTrader 5 / Библиотеки

Balance_Reset - библиотека для MetaTrader 5

247
(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();  // Выведите результаты сброса баланса в журнал } 


Ключевые функции

  1. Настраиваемые пороги прибыли и убытков

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

    Пример:

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