//+------------------------------------------------------------------+ //| Expert.mq5 | //| Copyright 2024, Yuriy Bykov | //| https://www.mql5.com/ru/users/antekov | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, Yuriy Bykov" #property link "https://www.mql5.com/ru/articles/16913" #property version "1.23" #include "../Virtual/VirtualAdvisor.mqh" #include "../Utils/ExpertHistory.mqh" // Если не задана константа с именем итогового советника, то #ifndef __NAME__ // Задаём её равной названию файла советника #define __NAME__ MQLInfoString(MQL_PROGRAM_NAME) //+------------------------------------------------------------------+ //| Функция формирования строки инициализации стратегии | //| из входных параметров по умолчанию (если не было задано имя). | //| Импортирует строку инициализации из базы данных советника | //| по идентификатору группы стратегий | //+------------------------------------------------------------------+ string GetStrategyParams() { // Берём строку инициализации из новой библиотеки для выбранной группы // (из базы данных эксперта) string strategiesParams = CVirtualAdvisor::Import( CVirtualAdvisor::FileName(__NAME__, magic_), groupId_ ); // Если группа стратегий из библиотеки не задана, то прерываем работу if(strategiesParams == NULL && useAutoUpdate_) { strategiesParams = ""; } return strategiesParams; } #endif //+------------------------------------------------------------------+ //| Входные параметры | //+------------------------------------------------------------------+ input group "::: Использовать группу стратегий" sinput int groupId_ = 0; // - ID группы из новой библиотеки (0 - последняя) sinput bool useAutoUpdate_ = true; // - Использовать автообновление? input group "::: Управление капиталом" sinput double expectedDrawdown_ = 10; // - Максимальный риск (%) sinput double fixedBalance_ = 10000; // - Используемый депозит (0 - использовать весь) в валюте счета input double scale_ = 1.00; // - Масштабирующий множитель для группы input group "::: Риск-менеджер" input bool rmIsActive_ = true; // - Активен? input double rmStartBaseBalance_ = 10000; // - Базовый баланс input ENUM_RM_CALC_DAILY_LOSS rmCalcDailyLossLimit_ = RM_CALC_DAILY_LOSS_MONEY_BB; // - Способ расчёта дневного убытка input double rmMaxDailyLossLimit_ = 500; // - Значение дневного убытка input double rmCloseDailyPart_ = 1.0; // - Значение пороговой части дневного убытка input ENUM_RM_CALC_OVERALL_LOSS rmCalcOverallLossLimit_ = RM_CALC_OVERALL_LOSS_MONEY_BB; // - Способ расчёта общего убытка input double rmMaxOverallLossLimit_ = 1000; // - Значение общего убытка input double rmCloseOverallPart_ = 1.0; // - Значение пороговой части общего убытка input ENUM_RM_CALC_OVERALL_PROFIT rmCalcOverallProfitLimit_ = RM_CALC_OVERALL_PROFIT_MONEY_BB; // - Способ расчёта общей прибыли input double rmMaxOverallProfitLimit_ = 1000000; // - Значение общей прибыли input datetime rmMaxOverallProfitDate_ = 0; // - Предельное время ожидания общей прибыли (дней) input double rmMaxRestoreTime_ = 0; // - Время ожидания лучшего входа на просадке input double rmLastVirtualProfitFactor_ = 1; // - Множитель начальной лучшей просадки input group "::: Прочие параметры" input ulong magic_ = 27183; // - Magic input bool useOnlyNewBars_ = true; // - Работать только на открытии бара input bool usePrevState_ = true; // - Загружать предыдущее состояние input string symbolsReplace_ = ""; // - Правила замены символов CVirtualAdvisor *expert; // Объект эксперта //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // Устанавливаем параметры в классе управления капиталом CMoney::DepoPart(expectedDrawdown_ / 10.0); CMoney::FixedBalance(fixedBalance_); // Строка инициализации с наборами параметров стратегий string strategiesParams = NULL; // Берём строку инициализации из новой библиотеки для выбранной группы // (из базы данных эксперта) strategiesParams = GetStrategyParams(); // Если группа стратегий из библиотеки не задана, то прерываем работу if(strategiesParams == NULL) { return INIT_FAILED; } // Подготавливаем строку инициализации для эксперта с группой из нескольких стратегий string expertParams = StringFormat( "class CVirtualAdvisor(\n" " class CVirtualStrategyGroup(\n" " [\n" " %s\n" " ],%f\n" " ),\n" " class CVirtualRiskManager(\n" " %d,%.2f,%d,%.2f,%.2f,%d,%.2f,%.2f,%d,%.2f,%d,%.2f,%.2f" " )\n" " ,%d,%s,%d\n" ")", strategiesParams, scale_, rmIsActive_, rmStartBaseBalance_, rmCalcDailyLossLimit_, rmMaxDailyLossLimit_, rmCloseDailyPart_, rmCalcOverallLossLimit_, rmMaxOverallLossLimit_, rmCloseOverallPart_, rmCalcOverallProfitLimit_, rmMaxOverallProfitLimit_, rmMaxOverallProfitDate_, rmMaxRestoreTime_, rmLastVirtualProfitFactor_, magic_, __NAME__, useOnlyNewBars_ ); PrintFormat(__FUNCTION__" | Expert Params:\n%s", expertParams); // Создаем эксперта, работающего с виртуальными позициями expert = NEW(expertParams); // Если эксперт не создан, то возвращаем ошибку if(!expert) return INIT_FAILED; // Если при замене символов возникла ошибка, то возвращаем ошибку if(!expert.SymbolsReplace(symbolsReplace_)) return INIT_FAILED; // Если требуется восстанавливать состояние, то if(usePrevState_) { // Загружаем прошлое состояние при наличии if(!expert.Load()) return INIT_FAILED; //expert.Tick(); } // Успешная инициализация return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { expert.Tick(); // Если одновременно выполнено: if(groupId_ == 0 // - не задан конкретный идентификатор группы && useAutoUpdate_ // - разрешено автообновление && IsNewBar(Symbol(), PERIOD_D1) // - наступил новый день && expert.CheckUpdate() // - обнаружена новая группа стратегий ) { // Сохраняем текущее состояние эксперта expert.Save(); // Удаляем объект эксперта delete expert; // Вызываем функцию инициализации советника для загрузки новой группы стратегий OnInit(); } } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(!!expert) delete expert; } //+------------------------------------------------------------------+ //| Результат тестирования | //+------------------------------------------------------------------+ double OnTester(void) { CExpertHistory::Export(); return expert.Tester(); } //+------------------------------------------------------------------+