158 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
//+------------------------------------------------------------------+
 | 
						|
//|                                                       Stage3.mqh |
 | 
						|
//|                                 Copyright 2024-2025, Yuriy Bykov |
 | 
						|
//|                            https://www.mql5.com/ru/users/antekov |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
#property copyright "Copyright 2024-2025, Yuriy Bykov"
 | 
						|
#property link      "https://www.mql5.com/ru/articles/17328"
 | 
						|
#property description "Советник, сохраняющий сформированную нормированную группу стратегий "
 | 
						|
#property description "в библиотеку групп с заданным именем."
 | 
						|
 | 
						|
#property version "1.05"
 | 
						|
 | 
						|
#ifndef __NAME__
 | 
						|
#define  __NAME__ "EmptyStrategy"
 | 
						|
#endif
 | 
						|
 | 
						|
#include "../Virtual/VirtualAdvisor.mqh"
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Входные параметры                                                |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
sinput int      idTask_  = 38;       // - Идентификатор задачи оптимизации
 | 
						|
sinput string fileName_  = "article.16373.db.sqlite"; // - Файл с основной базой данных
 | 
						|
 | 
						|
input group "::: Отбор в группу"
 | 
						|
input string     passes_ = "";      // - Идентификаторы проходов через запятую
 | 
						|
 | 
						|
input group "::: Сохранение в библиотеку"
 | 
						|
input string groupName_  = "SimpleVolumes_v.1.20_2023.01.01";      // - Название версии (если пустое - не сохранять)
 | 
						|
input string advFileName_  = "SimpleVolumes-27183.test.db.sqlite"; // - Название базы данных эксперта
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
double expectedDrawdown_  = 10;    // - Максимальный риск (%)
 | 
						|
double fixedBalance_      = 10000; // - Используемый депозит (0 - использовать весь) в валюте счета
 | 
						|
double scale_             = 1.00;  // - Масштабирующий множитель для группы
 | 
						|
 | 
						|
ulong    magic_           = 27183; // - Magic
 | 
						|
 | 
						|
CVirtualAdvisor     *expert;       // Объект эксперта
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Expert initialization function                                   |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
int OnInit() {
 | 
						|
// Устанавливаем параметры в классе управления капиталом
 | 
						|
   CMoney::DepoPart(expectedDrawdown_ / 10.0);
 | 
						|
   CMoney::FixedBalance(fixedBalance_);
 | 
						|
   CVirtualAdvisor::TesterInit(idTask_, fileName_);
 | 
						|
 | 
						|
// Строка инициализации с наборами параметров стратегий
 | 
						|
   string strategiesParams = NULL;
 | 
						|
 | 
						|
// Если соединение с основной базой данных установлено, то
 | 
						|
   if(DB::Connect(fileName_)) {
 | 
						|
      // Формируем запрос на получение проходов с указанными идетификаторами
 | 
						|
      string query = (passes_ == "" ?
 | 
						|
                      StringFormat("SELECT DISTINCT FIRST_VALUE(p.params) OVER (PARTITION BY p.id_task ORDER BY custom_ontester DESC) AS params "
 | 
						|
                                   "  FROM passes p "
 | 
						|
                                   " WHERE p.id_task IN ("
 | 
						|
                                   "           SELECT pt.id_task "
 | 
						|
                                   "             FROM tasks t "
 | 
						|
                                   "                  JOIN "
 | 
						|
                                   "                  jobs j ON j.id_job = t.id_job "
 | 
						|
                                   "                  JOIN "
 | 
						|
                                   "                  stages s ON s.id_stage = j.id_stage "
 | 
						|
                                   "                  JOIN "
 | 
						|
                                   "                  jobs pj ON pj.id_stage = s.id_parent_stage "
 | 
						|
                                   "                  JOIN "
 | 
						|
                                   "                  tasks pt ON pt.id_job = pj.id_job "
 | 
						|
                                   "            WHERE t.id_task = %d "
 | 
						|
                                   " ) ", idTask_)
 | 
						|
                      : StringFormat("SELECT params"
 | 
						|
                                     "  FROM passes "
 | 
						|
                                     " WHERE id_pass IN (%s);", passes_)
 | 
						|
                     );
 | 
						|
 | 
						|
      Print(query);
 | 
						|
      int request = DatabasePrepare(DB::Id(), query);
 | 
						|
 | 
						|
      if(request != INVALID_HANDLE) {
 | 
						|
         // Структура для чтения результатов
 | 
						|
         struct Row {
 | 
						|
            string         params;
 | 
						|
         } row;
 | 
						|
 | 
						|
         // Для всех строк результата запроса, соединяем строки инициализации
 | 
						|
         while(DatabaseReadBind(request, row)) {
 | 
						|
            strategiesParams += row.params + ",";
 | 
						|
         }
 | 
						|
      }
 | 
						|
      DB::Close();
 | 
						|
   }
 | 
						|
 | 
						|
// Если наборов параметрв не найдено, то прерываем тестирование
 | 
						|
   if(strategiesParams == NULL) {
 | 
						|
      return INIT_FAILED;
 | 
						|
   }
 | 
						|
 | 
						|
// Подготавливаем строку инициализации для эксперта с группой из нескольких стратегий
 | 
						|
   string expertParams = StringFormat(
 | 
						|
                            "class CVirtualAdvisor(\n"
 | 
						|
                            "    class CVirtualStrategyGroup(\n"
 | 
						|
                            "       [\n"
 | 
						|
                            "        %s\n"
 | 
						|
                            "       ],%f\n"
 | 
						|
                            "    ),\n"
 | 
						|
                            "    class CVirtualRiskManager(\n"
 | 
						|
                            "       0,0,0,0,0,0,0,0,0,0,0,0,0"
 | 
						|
                            "    )\n"
 | 
						|
                            "    ,%d,%s,%d\n"
 | 
						|
                            ")",
 | 
						|
                            strategiesParams, scale_,
 | 
						|
                            magic_, __NAME__, true
 | 
						|
                         );
 | 
						|
 | 
						|
   PrintFormat(__FUNCTION__" | Expert Params:\n%s", expertParams);
 | 
						|
 | 
						|
// Создаем эксперта, работающего с виртуальными позициями
 | 
						|
   expert = NEW(expertParams);
 | 
						|
   
 | 
						|
// Если эксперт не создан, то возвращаем ошибку
 | 
						|
   if(!expert) return INIT_FAILED;
 | 
						|
   
 | 
						|
// Успешная инициализация
 | 
						|
   return(INIT_SUCCEEDED);
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Expert tick function                                             |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void OnTick() {
 | 
						|
   expert.Tick();
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Expert deinitialization function                                 |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void OnDeinit(const int reason) {
 | 
						|
   if(!!expert) delete expert;
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Результат тестирования                                           |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
double OnTester(void) {
 | 
						|
   // Обрабатываем завершение прохода в объекте эксперта
 | 
						|
   double res = expert.Tester();
 | 
						|
 | 
						|
   // Если имя группы не пустое, то сохраняем проход в библиотеку
 | 
						|
   if(groupName_ != "") {
 | 
						|
      expert.Export(groupName_, advFileName_);
 | 
						|
   }
 | 
						|
   
 | 
						|
   return res;
 | 
						|
}
 | 
						|
//+------------------------------------------------------------------+
 |