Обсуждение статьи "Разрабатываем мультивалютный советник (Часть 2): Переход к виртуальным позициям торговых стратегий" - страница 5

 
mytarmailS #:
Не факт что на рынке усложнение модели сработает лучше чем корзина из простых тс
Ну там надо не отпить каждую ТС до талова будет, а просто докидывать новые ТС после нескольких проходов оптимизатора
 
Maxim Dmitrievsky #:
Можно сделать не bagging (корзину) стратегий, а boosting. Это когда оптится сначала одна стратегия, потом ее сигналы подставляются как параметр для второй стратегии, оптится вторая, и так далее. 

Мне кажется, что реализация выделенного является весьма нетривиальной задачей. Обычно параметры стратегии задаются при старте, а сигналы на открытие/закрытие определяются по некоторому алгоритму уже в процессе работы стратегии. Если мы в каком-то унифицированном виде будем сохранять историю открытий, то ее потом всю придется подавать на вход второй стратегии... Так получается? Если же подать эту информацию в виде алгоритма (функции) и ее фиксированных параметров, то не получится ли, что мы пришли через boosting к тому же bagging-у, только с чёрного хода?

 

Огромное спасибо, прочитал с интересом. Хочу сделать как раз что-то подобное, только с большей автоматизацией, для которой планирую нещадно ввести в эксплуатацию ваши библиотеки по работе с *.opt и *.tst файлами тестера.

 
Yuriy Bykov #:

Мне кажется, что реализация выделенного является весьма нетривиальной задачей. Обычно параметры стратегии задаются при старте, а сигналы на открытие/закрытие определяются по некоторому алгоритму уже в процессе работы стратегии. Если мы в каком-то унифицированном виде будем сохранять историю открытий, то ее потом всю придется подавать на вход второй стратегии... Так получается? Если же подать эту информацию в виде алгоритма (функции) и ее фиксированных параметров, то не получится ли, что мы пришли через boosting к тому же bagging-у, только с чёрного хода?

Не задумывался как сделать это через оптимизатор. Нет, там должно получаться, что каждая следующая стратегия будет улучшать предыдущую, то есть строиться поверх нее. Как конкретно это представить - дело наживное. Можно просто посмотреть в инете как работают boosted trees, на их основе вылепить. Там может быть много нюансов, да. Но сам делать не буду, поскольку это все уже есть в алгоритмах МО. И это не панацея, но может быть получше портфеля ТС по своим свойствам.

 
Maxim Dmitrievsky #:

Не задумывался как сделать это через оптимизатор.

Это рутина, которую можно полностью автоматизировать через подключение соответствующего mqh к mq5.


Алгоритм такой.

  1. В папке лежат предыдущие проходы (если не было проходов - пусто) в виде файлов.
  2. Запускается новая оптимизация: торгуется сама ТС + добавляется торговля из п.1. При этом ММ распределяется равномерно между п.1 и ТС.
  3. В п.1. записывается лучший проход (OnTester любой) оптимизации.
  4. п.2 столько раз, сколько хочется ТС в портфеле.

Так можно намешать чего угодно. Очевидно, что даже при полном переборе конечный результат будет зависеть от того, в какой последовательности запускаются ТС.

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

 
Yuriy Bykov #:

Спасибо большое, посмотрел код. Буду рассматривать передачу входных параметров позже. Если не получится взять полностью такой подход, то некоторые моменты, скорее всего, очень пригодятся.

Текущие результаты своей работы с инпутами снова (в приложении) применил к коду из данной статьи.

Пример того, каким стал SimpleVolumesExpertSingle.mq5.

#define INPUT_STRUCT_ADDON
#include "Advisor.mqh"
#include "SimpleVolumesStrategy.mqh"
#include "VolumeReceiver.mqh"

input string      symbol_              = "EURGBP";    // Торговый инструмент (символ)
input group "===  Параметры советника"
input ulong       magic_              = 27181; // Magic

CAdvisor     *expert;         // Указатель на объект эксперта

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
   expert = new CAdvisor(new CVolumeReceiver(magic_));

   // Добавляем один экземпляр стратегии
   expert.Add(new CSimpleVolumesStrategy( symbol_, inStrategyInput + inSimpleVolumesStrategyInput));

   return(INIT_SUCCEEDED);
}


Удалось добиться единоразового прописывания в коде входных (SimpleVolumesStrategyInput.mqh).

// https://www.mql5.com/ru/code/47932
// Use this string to find all Inputs mqh.
// #include <fxsaber\Input_Struct\Input_Struct.mqh> // Original

#define TYPENAME_INPUT SimpleVolumesStrategyInput

#define MACROS_MULTI                    \
  MACROS(signalPeriod, int, 13)         \ // Количество свечей для усреднения объемов
  MACROS(signalDeviation, double, 0.3)  \ // Относ. откл. от среднего для открытия первого ордера
  MACROS(signaAddlDeviation, double, 1) \ // Относ. откл. от среднего для открытия второго и последующих ордеров
  MACROS(openDistance, int, 0)          \ // Расстояние от цены до отлож. ордера
  MACROS(stopLevel, double, 10500)      \ // Stop Loss (в пунктах)
  MACROS(takeLevel, double, 465)        \ // Take Profit (в пунктах)
  MACROS(ordersExpiration, int, 1000)   \ // Время истечения отложенных ордеров (в минутах)
  MACROS(maxCountOfOrders, int, 3)        // Макс. количество одновременно отрытых ордеров

Файлы:
 
fxsaber #:

Текущие результаты своей работы с инпутами снова (в приложении) применил к коду из данной статьи.

Пример того, каким стал SimpleVolumesExpertSingle.mq5.


Удалось добиться единоразового прописывания в коде входных (SimpleVolumesStrategyInput.mqh).

Это мне показалось как-то заметно проще чем предыдущий вариант. Хотя, может, просто когда смотришь на чужой код в очередной раз, то он с каждым разом становится всё понятнее и проще. Спасибо большое! В процессе изучения возник вопрос, нельзя ли код, который идет после "// Copy-Paste update from here:" разместить во включаемом файле и подключать вместо вставки? Сейчас просто поэкспериментировать неудобно, поэтому решил спросить. 

В третьей статье до входных параметров очередь еще не дошла :(. Но дойдет обязательно.

 
Yuriy Bykov #:

В процессе изучения возник вопрос, нельзя ли код, который идет после "// Copy-Paste update from here:" разместить во включаемом файле и подключать вместо вставки? Сейчас просто поэкспериментировать неудобно, поэтому решил спросить.

К сожалению, нельзя, т.к. #include одного и того же файла происходит только один раз - первая встреча. Дальше игнорируется.

Это одна из причин, почему здесь пришлось делать полностью идентичный файл с другим названием.


Но в целом Copy-Paste вариант - пара нажатий. Понимать тот код не требуется.

PriceChannel
PriceChannel
  • www.mql5.com
Ценовой канал произвольной длительности (таймфрейм) бара.
 
Yuriy Bykov #:

В третьей статье до входных параметров очередь еще не дошла :(. Но дойдет обязательно.

Ваша архитектура несколько отличается от моей, поэтому не предусматривал в INPUT_STRUCT многое из того, что пригодилось бы в данном проекте.

Хорошо, что не стали публиковать, т.к. снова переделал - на самый лаконичный и удобный вариант (похоже, окончательный).

Добавил group, string-инпуты и кое-что по мелочи для удобства на будущее.

#define TYPENAME_INPUT StrategyInput

#define MACROS_MULTI                           \
  INPUT(symbol, string, "EURGBP")              \ // Торговый инструмент (символ)
  INPUT(timeframe, ENUM_TIMEFRAMES, PERIOD_H1) \ // Период графика (таймфрейм)
  GROUP("===  Параметры управление капиталом") \
  INPUT(fixedLot, double, 0.01)                  // Размер открываемых позиций (фиксированный)
#define TYPENAME_INPUT SimpleVolumesStrategyInput

#define MACROS_MULTI                           \
  GROUP("===  Параметры сигнала к открытию")   \
  INPUT(signalPeriod, int, 13)                 \ // Количество свечей для усреднения объемов
  INPUT(signalDeviation, double, 0.3)          \ // Относ. откл. от среднего для открытия первого ордера
  INPUT(signaAddlDeviation, double, 1)         \ // Относ. откл. от среднего для открытия второго и последующих ордеров
  GROUP("===  Параметры отложенных ордеров")   \
  INPUT(openDistance, int, 0)                  \ // Расстояние от цены до отлож. ордера
  INPUT(stopLevel, double, 10500)              \ // Stop Loss (в пунктах)
  INPUT(takeLevel, double, 465)                \ // Take Profit (в пунктах)
  INPUT(ordersExpiration, int, 1000)           \ // Время истечения отложенных ордеров (в минутах)
  GROUP("===  Параметры управление капиталом") \
  INPUT(maxCountOfOrders, int, 3)                // Макс. количество одновременно отрытых ордеров


Куски кода применения для демонстрации, как используется.

#define INPUT_STRUCT_ADDON
#include "Advisor.mqh"
#include "SimpleVolumesStrategy.mqh"
#include "VolumeReceiver.mqh"

input group "===  Параметры советника"
input ulong       magic_              = 27181; // Magic

CAdvisor     *expert;         // Указатель на объект эксперта

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
   expert = new CAdvisor(new CVolumeReceiver(magic_));

   // Добавляем один экземпляр стратегии
   expert.Add(new CSimpleVolumesStrategy(inStrategyInput + inSimpleVolumesStrategyInput));

   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Конструктор                                                      |
//+------------------------------------------------------------------+
CSimpleVolumesStrategy::CSimpleVolumesStrategy( const string sInputs ) : CStrategy(sInputs)
{
   this.Input = sInputs;

   ArrayResize(m_orders, this.Input.maxCountOfOrders);

   // Загружаем индикатор для получения тиковых объемов
   iVolumesHandle = iVolumes(this.InputStrategy.symbol, this.InputStrategy.timeframe, VOLUME_TICK);

// Устанавливаем размер массива-приемника тиковых объемов и нужную адресацию
   ArrayResize(volumes, this.Input.signalPeriod);
   ArraySetAsSeries(volumes, true);
}
//+------------------------------------------------------------------+
//| Конструктор                                                                |
//+------------------------------------------------------------------+
CStrategy::CStrategy( const string sInputs ) : m_isChanged(false)
{
  this.InputStrategy = sInputs;
}
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
// Проверяем корректность параметров
   if(startIndex_ < 0 || startIndex_ + totalStrategies_ > 9) {
      return INIT_PARAMETERS_INCORRECT;
   }

// Создаем и наполняем массив из экземпляров стратегий
   CStrategy *strategies[9];

   StrategyInput InputBase;
   SimpleVolumesStrategyInput Input;

   InputBase.timeframe = PERIOD_H1;

   // Первый способ задания - через инициализацию.
   const StrategyInput InputBase0 = {"EURGBP", PERIOD_H1, NormalizeDouble(0.01 / 0.16 * depoPart_, 2)};
   const SimpleVolumesStrategyInput Input0 = {13, 0.3, 1.0, 0, 10500, 465, 1000, 3};
   strategies[0] = new CSimpleVolumesStrategy(InputBase0 + Input0);

   // Второй способ задания - через строку и массив.
   InputBase.fixedLot = NormalizeDouble(0.01 / 0.09 * depoPart_, 2);
   const double Array1[] = {17, 1.7, 0.5, 0, 16500, 220, 1000, 3};
   strategies[1] = new CSimpleVolumesStrategy(InputBase["symbol = EURGBP"] + "," + Input[Array1]);

   // Третий способ задания - через задание полей.
   InputBase.fixedLot = NormalizeDouble(0.01 / 0.16 * depoPart_, 2);
   InputBase.symbol = "EURGBP";
   const double Array2[] = {51, 0.5, 1.1, 0, 19500, 370, 22000, 3};
   strategies[2] = new CSimpleVolumesStrategy(InputBase + Input[Array2]);
Файлы:
 
fxsaber #:

Хорошо, что не стали публиковать, т.к. снова переделал - на самый лаконичный и удобный вариант (похоже, окончательный).

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

Спасибо!

Причина обращения: