Обсуждение статьи "Разрабатываем мультивалютный советник (Часть 13): Автоматизация второго этапа — отбор в группы"

 

Опубликована статья Разрабатываем мультивалютный советник (Часть 13): Автоматизация второго этапа — отбор в группы:

Первый этап автоматизированного процесса оптимизации у нас уже реализован. Для разных символов и таймфреймов мы проводим оптимизацию по нескольким критериям и сохраняем информацию о результатах каждого прохода в базе данных. Теперь займёмся отбором лучших групп наборов параметров из найденных на первом этапе.

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

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

Давайте теперь модифицируем тот советник, который занимался оптимизацией подбора группы, так, чтобы он мог использовать результаты первого этапа из базы данных. Свои результаты он также должен сохранять в базу данных. Также рассмотрим создание заданий на проведение оптимизаций второго этапа путём добавления нужных записей в нашу базу данных.


Автор: Yuriy Bykov

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

Спасибо за отзывы, будем двигаться дальше.

Александр, наверное, вы не совсем доразбирались с тем, как можно использовать static. С его помощью паттерн проектирования Singleton спокойно реализуется и на MQL5, как и на C++. Я применял его, например, для класса CVirtualReceiver в третьей части. Этот модификатор никак не связан с тем графиком, на котором будет запущен советник. Связь может быть у переменной или свойства, объявленного с этим модификатором, если мы присваиваем им, например, результат вызова функции Symbol(). Но это не значит, что мы потом не можем поменять значение таких переменных

 
Юрий здравствуйте! Подскажите, а в какой Вы программе открываете и редактируете базу данных? У меня в редакторе mql5 она открывается, но там редактирование недоступно (кнопки серые, и пункты меню) и сем интерфейс немного по другому выглядит?
 

Здравствуйте, Виктор.

Использую SQLiteStudio. За последнее время эта бесплатная программа сильно расширила функционал, поэтому не сталкивался с отсутствием в ней чего-то необходимого. В MetaEditor можно редактировать БД только через выполнение SQL-запросов. Это менее удобно, конечно.

 

Юрий спасибо за программу, получилось теперь открыть базу и редактировать. И я провёл первый этап вычислений, а со вторым проблема - не запускается. Я сначала провёл первый этап, потом добавил вручную строку второго этапа как у Вас на скриншоте и выполнил два запроса из Вашей статьи. Задачи и работы в базе данных появились и советник пытается запускать второй этап. Но почему-то не видит проходы первого этапа, хотя они в базе есть. Я может что-то не так понимаю, (я с базами никого не работал).

Ошибки вот на скринщётах. Как это запустить?

Файлы:
37yepqooe5.png  129 kb
7339o8y4fn1.png  21 kb
 

И ещё, как я понимаю вот эти параметры:

input int      count_         = 16;                   // - Количество стратегий в группе (1 .. 16)

input int   i1_ = 1;       // - Индекс стратегии #1
input int   i2_ = 2;       // - Индекс стратегии #2
input int   i3_ = 3;       // - Индекс стратегии #3
input int   i4_ = 4;       // - Индекс стратегии #4
input int   i5_ = 5;       // - Индекс стратегии #5
input int   i6_ = 6;       // - Индекс стратегии #6
input int   i7_ = 7;       // - Индекс стратегии #7
input int   i8_ = 8;       // - Индекс стратегии #8
input int   i9_ = 9;       // - Индекс стратегии #9
input int   i10_ = 10;     // - Индекс стратегии #10
input int   i12_ = 11;     // - Индекс стратегии #11
input int   i11_ = 12;     // - Индекс стратегии #12
input int   i13_ = 13;     // - Индекс стратегии #13
input int   i14_ = 14;     // - Индекс стратегии #14
input int   i15_ = 15;     // - Индекс стратегии #15
input int   i16_ = 16;     // - Индекс стратегии #16

должны перебираться в рамках каждой задачи второго этапа. А в каких диапазонах их перебирать и с каким шагом? А сам параметр count_ как я понимаю перебирать не нужно?

 

Для второго этапа должна автоматически создаваться вторая база данных, которая будет рассылаться агентам тестирования. Её название указывается в директиве

#define PARAMS_FILE "database892.stage2.sqlite"

Оно должно отличаться от имени основной базы данных. На скриншоте вам сообщается, что таблицы passes в этой базе нет, хотя ожидалось, что она там будет. Попробуйте внимательно разобраться с работой функции CreateTaskDB(), которая создаёт вторую базу из исходной.

Шаг и пределы перебора параметров вида i{N}_ устанавливаются автоматически оптимизирующим советником Optimization.mq5 по информации из второй базы данных.

Параметр count_ перебирать не нужно. Его можно поменять на меньшее значение, если мы захотим подбирать группы не из 16, а из меньшего количества экземпляров. Например из 12 или из 8. Но у меня он всегда был равен 16.

 

Юрий что-то не получается у меня заставить её работать... Файл общей базы данной у меня указан как у вас в советнике database892.sqlite , я его не менял и он есть на диске реально, и к нему советник Optimization.mq5 подключается и задачи запускает. В советнике SimpleVolumesStage2.mq5 оно тоже указан. А файл базы данных задачи указан database892.stage2.sqlite . Как я понимаю это разные файлы. Файл общей базы лежит в папке Common\Files.

Я попробовал вставить проверки в функцию GetParamsTotal и указать переменную fileName в функции DB::Connect вот код:

//+------------------------------------------------------------------+
//| Количество наборов параметров стратегий в базе данных задачи     |
//+------------------------------------------------------------------+
int GetParamsTotal(const string fileName) {
   int paramsTotal = 0;
         PrintFormat(__FUNCTION__" 1 ");

// Если база данных задачи открыта, то
   if(DB::Connect(fileName, 0)) {
         PrintFormat(__FUNCTION__" 2 ");

      // Создаём запрос на получение количества проходов для данной задачи
      string query = "SELECT COUNT(*) FROM passes p";
         PrintFormat(__FUNCTION__" 3 ");

      int request = DatabasePrepare(DB::Id(), query);
         PrintFormat(__FUNCTION__" 4 ");
      

      if(request != INVALID_HANDLE) {
         // Структура данных для результата запроса
         PrintFormat(__FUNCTION__" 5 ");

         struct Row {
            int      total;
         } row;
         PrintFormat(__FUNCTION__" 6 ");
         
         // Получаем результат запроса из первой строки
         if (DatabaseReadBind(request, row)) {
            paramsTotal = row.total;
         }
      } else {
         PrintFormat(__FUNCTION__" | ERROR: request \n%s\nfailed with code %d", query, GetLastError());
      }
      DB::Close();
   }
         PrintFormat(__FUNCTION__" 7 ");

   return paramsTotal;
}

При выполнении в лог он выдаёт вот так:

2024.08.21 22:05:27.964 Optimization (EURUSD,M5)        idTask_=124||0||0||0||N
2024.08.21 22:05:27.964 Optimization (EURUSD,M5)        idParentJob_=7||0||1||10||N
2024.08.21 22:05:27.964 Optimization (EURUSD,M5)        
2024.08.21 22:05:29.096 SimpleVolumesStage2 (GBPUSD,H1) GetParamsTotal 1 
2024.08.21 22:05:29.097 SimpleVolumesStage2 (GBPUSD,H1) GetParamsTotal 2 
2024.08.21 22:05:29.097 SimpleVolumesStage2 (GBPUSD,H1) GetParamsTotal 3 
2024.08.21 22:05:29.097 SimpleVolumesStage2 (GBPUSD,H1) database error, no such table: passes
2024.08.21 22:05:29.097 SimpleVolumesStage2 (GBPUSD,H1) GetParamsTotal 4 
2024.08.21 22:05:29.097 SimpleVolumesStage2 (GBPUSD,H1) GetParamsTotal | ERROR: request 
2024.08.21 22:05:29.097 SimpleVolumesStage2 (GBPUSD,H1) SELECT COUNT(*) FROM passes p
2024.08.21 22:05:29.097 SimpleVolumesStage2 (GBPUSD,H1) failed with code 5039
2024.08.21 22:05:29.098 SimpleVolumesStage2 (GBPUSD,H1) GetParamsTotal 7 
2024.08.21 22:05:29.098 SimpleVolumesStage2 (GBPUSD,H1) OnTesterInit | ERROR: Can't load data from file database892.sqlite.
2024.08.21 22:05:29.098 SimpleVolumesStage2 (GBPUSD,H1) Check that it exists in data folder or in common data folder.
2024.08.21 22:05:32.900 Optimization (EURUSD,M5)        OnTimer | Current Task ID = 124
2024.08.21 22:05:33.008 Optimization (EURUSD,M5)        FinishTask | Task ID = 124
2024.08.21 22:05:33.022 Optimization (EURUSD,M5)        StartTask | Task ID = 125
2024.08.21 22:05:33.022 Optimization (EURUSD,M5)        [Tester]

Где номер ошибки может ещё писать 5602 . Как я понимаю он спотыкается на функции DatabasePrepare

Базу я брал как у Вас выложено в файле к статье 11 Единственное поменял имя файла с  database.sqlite на  database892.sqlite и поменял в базе названия советника первого этапа на актуальный в этой части и после того как выполнил первый этап добавил строку второго этапа в таблицу stages и выполнил 2 набора команд с Вашей статьи. Больше я ничего не менял. В таблице passes имеется около 388 000 строк с проходами.

 

Ошибка возникает раньше, просто там про неё не сообщается, так как с точки зрения выполнения программы всё в порядке.

Это сообщение

2024.08.21 22:05:29.097 SimpleVolumesStage2 (GBPUSD,H1) database error, no such table: passes

прямо говорит, что нет таблицы passes во второй базе данных, а мы пытаемся получить из неё данные. Поэтому надо разбираться с той функцией, которая должна её создавать - CreateTaskDB().