Прошу помощи коллективного разума

 

Введение. 

 Пишу советника, основанного на следующих статьях. 

 https://www.mql5.com/ru/articles/217

https://www.mql5.com/ru/articles/55

https://www.mql5.com/ru/articles/143

 

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

Иными словами советника, построенного на моделях который способен :

1. Самооптимизироваться

2. Использовать адаптивыный подход в управлении.

Для этого создал несколько классов:

1 - Базовый -фундамент любой торговой модели.

2 - Класс оптимизатор - способный перебором и генетически переоптимизировать модель.

3 - Класс управления торговыми ордерами (виртуальные стопы,мм, и т.д.)

4  -Сам класс торговой стратегии - взял МАКД  - фактически является лишь генератором торговых сигналов и выходов. Класс небольшой.

 

Суть проблеммы.

 

Хочу чтобы советник работал так:

Создается массив из Х торговых моделей. 1-все кастомные параметры, 2-пользовательские, (3- Х) -наилучшие результаты долгосрочной оптимизации(за год-2-3-...)Каждый период переоптимизации (пусть это будет месяц) добавляется новая модель с наилучшими результатами краткосрочной оптимизации(месяц-2-3..). Добавляется до тех пор, пока массив не достигнет максимально возможного кол-ва моделей. Затем модели не добавляются, а заменяются (худшие -новыми лучшими).

Сделать чтобы оптимизатор выдавал нужные массивы значений - не проблема.

Проблема в том, что если у меня несколько классов торговых моделей - по МАКД, по МА, по ББ, по  Стохастику и т. д. Как создать Адаптивную систему, которая сможет  работать со всеми ими. 

К примеру Если создать адаптивную систему для МАКД, до для ее инициализации надо было бы ввести (Х, Максимум кол-ва, пользовательские параметры модели МАКД)  - эту систему просто(относительно) было бы сделать. Но для другой модели она уже не подойдет. И придется делать новую адаптивную систему.

 

Помогите мне решить эту проблему. Как можно было бы реализовать в ООП адаптивную систему, способную работать с любыми моделями ?

Чтобы уменьшить количество классов и увеличить гибкость системы. Приветствую любые идеи и мнения. Заранее благодарен.

Создание мульти-экспертов на основе торговых моделей
Создание мульти-экспертов на основе торговых моделей
  • 2010.12.08
  • Василий Соколов
  • www.mql5.com
Использование объектно-ориентированного подхода в MQL5 значительно упрощает создание мультивалютных/мультисистемных/мультитаймфреймовых экспертов. Только представьте, ваш один единственный эксперт торгует сразу по нескольким десяткам торговых стратегий, сразу на всех доступных инструментах и сразу на всех возможных таймфреймах! К тому же этот эксперт прекрасно тестируется в тестере, а для всех стратегий, входящих в его состав, действует одна или сразу несколько систем управления капиталом.
 

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

Концептуально, организация видется так: 

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

public struct ParametersOfMovingAverage
{
   int FastEMA;
   int SlowEMA;
}
public class MovingAverage{
   ...;
}

public struct ParametersOfATRRange
{
   int PeriodATR;
   double RangeStopLoss;
   bool DisableSell;
}
public class ATRRange{
   ...;
}

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

Например, как можно было бы написать оптимизатор? Пишем внешний класс-оптимизатор, который загружает в модель ее набор параметров, оптимизирует ее по ее правилам и создает новую структуру параметров с оптимальными значениями. После этого модель переинициализируется с уже новой, оптимизированнной структурой параметров. Однако для правил оптимизации (шаг параметра, начальное значение, конечное значение, период оптимизации) потребуется либо расширить структуру параметров, что бы она содержала эти данные, либо создать новую Set-структуру/Класс описывающую эти значения.

Класс-оптимизатор нужен лишь один. На входе он должен получить лишь три типа правил: 

1. Торговую модель, которую требуется оптимизировать.

2. Структуру параметров торговой модели. 

3. Правила перебора параметров торговой модели. 

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

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

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

 

Спасибо за ответ. 

Модули, которые представленны в вашей статье значительно были изменены мной до такого состояния : 

1 - Базовый -фундамент любой торговой модели.

2 - Класс оптимизатор - способный перебором и генетически переоптимизировать модель.

3 - Класс управления торговыми ордерами (виртуальные стопы,мм, и т.д.)

4  -Сам класс торговой стратегии - взял МАКД  - фактически является лишь генератором торговых сигналов и выходов. Класс небольшой. 

 

И поскольку оптимизируемые параметры могут присутствовать как в базовой модели(символ, период), в классе управления торговыми ордерами(стоп-уровни, типы сопровождения, трэйлинга....) так и в самой торговой модели( к примеру Период МА) вопрос с работой оптимизатора я решил так:

1. Класс

 

class COptimizatedParam: public CObject
{
public:
 string name;
 double on;
 double step;
 double end;
 double value;
 void   Init(string Name,double On,double Step,double End, double CurValue)
         {name=Name;on=On;step=Step;end=End; value=CurValue;best_value=CurValue;}; 

2. В каждом модуле-составляющем где есть параметры которые можно оптимизировать  есть функция, которая загоняет эти параметры  в класс COptimizatedParam, и допавляет в СList-список.

3. Классу оптимизатору предоставляются -ссылка на модель типа

 

class COptimizatedModel :public CObject
{
 public:
  virtual double FitnessFunction(CList *Params){return(0.0);}
  virtual void   ServiceFunction(){return;}
};

 которая является предком моего CModel(без этого звена куча ошибок.),тип оптимизации, Список оптимиз-х параметров, настройки генетического алгоритма(при запуске советника).

4. Возвращает функция Start класса оптимизатора ссылку на все тот же СЛист, но у же со значениями оптимизированых параметров в полях value. И все составляющие моделей сами эти параметры снова "разбирают " и сами в себе выставляют. 

 5. Во время оптимизации торговля останавливается( и поэтому тоже желательно в адаптивной системе иметь спец модель только для оптимизации.). В свойствах выставляется, что идет виртуальная торговля,создается виртуальный аккаунт, и !!!Та же самая оптимизируемая модель!!! прогоняет каждый проход торговлю со сдвигом в прошлое. Это очень здорово, т.к. в торговой-Модели не нужно никаких других функций - она использует те же что и в обычной торговле, кроме того есть возможность просто виртуальной торговли( а так же я реализовал и визуальную- просто стрелочки рисует) 

 

 

 По поводу Адаптивной системы. Сложность у меня вызвало то, что если сделать параметры моделей структурами - то для каждой структуры необходимо писать свой инициализатор Адаптивной системы. 

Я решил это так. Класс параметров торговой модели, основанный на класе базовых параметров, которые есть у всех моделей. В результате входным в инициализаторе Адаптивной системы делаем Ссылку на класс Базовых параметров, а в зависимости от второго параметра меняем  тип ссылки на сооответствующий Класс-потомок параметров торговой модели. Тогда если напишу новуб торговую модель, в адаптивной системе нужно будет добавить новый тип в ENUM_MODELS_TYPE. и новый тип в инициализаторе.

За 2 дня, пока ждал тут ответа - решил что это лучший способ. Осталось только реализовать. 

Генетические алгоритмы - это просто!
Генетические алгоритмы - это просто!
  • 2010.05.25
  • Andrey Dik
  • www.mql5.com
В статье автор расскажет об эволюционных вычислениях с использованием генетического алгоритма собственной реализации. Будет показано на примерах функционирование алгоритма, даны практические рекомендации по его использованию.
 

Что можно сказать? Вы молодец. Ваши разработки опираясь на мою базовую концепцию  уже далеко ушли вперед. Поэтому что либо подсказать даже не смогу - Вам виднее.

Некоторые технические нюансы мне не понятны, но интуитивно видится проблемной выбранная Вами тактика объединения оптимизируемых параметров из нескольких независимых классов в один и его передача оптимизатору. Во-первых, это сильно усложняет межклассовую модель общения, во-вторых, требуется постоптимизационный разбор параметров обратно, в третьих генерируются  новые независимые параллельные цепочки классов COptimizatedModel, и я так подозреваю требуются интелектуальноемкие методы их связывания с цепью CModel. Думаю, эта проблема могла бы быть решена более надежным способом через механизм  наследования. В идеале, мы должны иметь либо одну единственную цепочку моделей либо максимум две цепи: одна цепь моделей, другая обслуживающая цепь. Объяcню на примере:

 

Например, создаем два класса  CModelProsessing и COptimizator. Загоняем их в список CList. Перебираем этот список. Перебираем для них список всех моделей (двойной вложенный цикл for).  Первый CProsessing только и делает, что жмет кнопку Prosessing. А вот второй должен по всей видимости работать со своей новой кнопкой, например "Optimize", которой в базовой модели нет. А вот конкретная модель должна обладать конечным набором оптимизированных параметров, включая как ее индивидуальные свойства типа периода усреднения, так и общими свойствами, например сопровождение позиции, трейлинг, уровень стопа и т.д. А вот эти общие свойства она может и должна получать лишь от своего родителя CModel. Так как механизма множественного наследования в MQL5 нет, по всей видимости между CModel и CList придется вставлять еще целый класс описывающий такие общие моменты. 

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

 

Честно признаюсь, многое из того что вы написали я не понял. Я занимаюсь программированием МQL5 может месяца три. 

 "Некоторые технические нюансы мне не понятны, но интуитивно видится проблемной выбранная Вами тактика объединения оптимизируемых параметров из нескольких независимых классов в один и его передача оптимизатору."

Это сделано не случайно.  Как реализовать ФФ(фитнес-функцию) и проверку переоптимизации общей для любых моделей, которые потом напишу - только делегировать им задачу решения, какие ей нужно параметры оптимизировать. 

Кокда наступает момент переоптимизации Функция базовой модели использует значение функции virtual CList *GetOptimizatedParams() для запуска оптимизации. Эта самая GetOptimizatedParams() определяется в каждой Торговой модели....Это сложно может описать словами, но несложно в реализации. 

 

Дальше...В базовой модели есть такая переменная Shift которая отвечает за сдвиг в минутах в прошлое(Я не делал генератор тиков - оптимизация идет по  ценам открытия). 

Покажу наглядно в классах как происходит взаимодействие.

вспомогательные: 

 1 класс - потомок CОbject  который имеет 1 функцию virtual double  FitnessFunction(). Она взвращает какое-то значение - Прибыльность, КОэфициент Шарпа и т.д. То, по чему можно определить чем предыдущий набор лучших параметров хуже/лучше нового. Определение этого класса распологается в фаиле с определением класса-оптимизатора. ПОэтому оптимизатору нужно передать ссылку на потомок такого класса.

1.1 класс Класс Оптимизатор - имеет  свои параметры и функцию Start() которая запускает процесс оптимизации.

1.2 класс Управляющий торговыми ордерами - имеет CList виртуальных ордеров, ссылку на используемый аккаунт, Функции отправки ордера, Флаги торговых условий(определяют виртуальную/реальную, визуальную/невизуальную режимы торговли, разрешение открывать и флаг срочного закрытия всех ордеров), флаги сопровождения Торговых ордеров(усреднение, перемещение в безубыток , способы выбора начального лота и т.д).

 По этим флагам определяется - отправлять ли ордера на сервер, или только использовать виртуальную торговлю. Кстати к вашим ORDER_ADD & ORDER_DELETE я добавил ORDER_NONE и ORDER_MODIFY.

Поскольку Список ордеров один для виртуальной и реальной торговли -перед оптимизацией модель дожидается пока все ордера закроются( и удалятся из списка), а после оптимизации список тоже очищается на всякий случай.

1.3 Виртуальный аккаунт - то же что и класс просто АккаунтИнфо, а точнее является его потомком, с возможностью определения маржи по списку виртуальных торговых ордеров и т.п. 

основные: 

2 класс - потомок 1 класса (базовая модель)  имеет в себе класс 1.1,1.2 , Определение ФФ из класса 1,  Функцию проверки необходимости переоптимизации. 

3 класс - потомок 2 класса - торговая модель. Имеет обязательно определение виртуальных функций из 2 класса Processing и Trading. Поскольку во время реальной торговли необходимо проверять условие переоптимизации, а для торговли во время самой оптимизации это не нужно - это 2 разные обязательные функции.

 

Как происходит переоптимизация(упрощенно, к примеру если есть открытые ордера выставляется флаг запрета открытия новых ордеров и ожидание, пока открытые закроются):

3 класс Processing  => 2 класс CheckReoptimizate => Опрос всех необходимых классов которые добавляют свои параметры в Список параметров => Запуск Start класса 1.1 =>  Цикл (Класс 1.1 вызывает ФФ из класса 1-или его потомка тут ведь указатель - , класс 2 прогоняет в цикле Определенное кол-во времени по истории каждый раз меняя Shift и запуская Trading , ФФ возвращает значаение результата прогона, класс 1.1 обрабатывает это значение и решает, определить ли эти параметры как лучшие или нет) => Start класса 1.1 возвращает ту же ссылку которую передали ему ( но там уже другие параметры) => 2 классс передает эту ссылку по очереди классу 2( поскольку функции в 2 классе виртуальные, то на деле передаются классу 3) , классу 1.2 => классы 3 и 1.2 выставляют эти параметры и снова переинициализируются( индикаторы там создаются к примеру, если требуется) => Выставляется время последней оптимизации. Пишется что оптимизация завершшилась и рез-ты оптимизации - какие параметры какие значения получили.

В результате в классе 3 требуется реализовать функции Processing, Trading,  GetOptimizatedParams,SetOptimizatedParams  и Инициализации. Достаточно гибко. Моей целью всех этих заморочек было сделать так, чтобы при создании новых моделей - нужно было минимум лишнего писать, только основное. Так и получилось.

 

Как я планирую реализовать адаптивные системы.

1. Создается Clist моделей. добавляются модели 1 с пользовательскими, 2 с стандартными параметрами( это тоже сами классы решают - заполняют данную им структуры константами), 3 - с переиодом оптимизации   1 год, 4  с переиодом переоптимизации 6 месяцев, 5 с периодом переоптимизации 3 месяца. (3,4,5 модели поддерживают автоматическую переоптимизацию. )

2. Каждый месяц( к примеру) создается новая модель, с периодом переоптимизации месяц. После ее начальной оптимизации ее возможность заново оптимизироваться отключается( чтобы впоследствии не появлялись ее "копии")

3. Когда В момент создания какой-то новой модели количество уже достигло уровня Max. Происходит выбор между коэфицентами новоиспеченной и 6..x моделями. Происходит замена одной из старых худших моделей новой.

 4.Изначально Флаг класса 1.2 каждой модели настроен на виртуальную торговлю.  Всех кроме модели с пользовательскими параметрами. Она торгует в первый "безадаптивный период"

 5. Остальные модели торгуют виртуально. В период переадаптации ( 1-2 недели к примеру) происходит выбор между моделями - у той у которой коэфициент(какой-нибудь -пока остановился прибыль/макс.просадка по средствам) выше  - закрывает все виртуалные ордера, переставляет настройки с виртуального аккаунта на реальный, флаг - на реальную торговлю, у остальных моделей -переинициализация аккаунтов, очистка списков(чтобы на новом эстафетном участке ус-ловия равные были) и установка флагов виртуальной торговли.

 

Настроенная уже ранее система Моделей позволяет и виртуально торговать и визуально....только вот не позволяет реальных рыночных стоп-уровней и отложек ставить - я решил что воплотить стоп уровни невозможно, так как по одному символу торговать могут разные модели, и пусть каждая сама решает когда ей входить а когда выходить из рынка, а  отложки - решил что контролировать их создание и выполненеие легче виртуально нежели реализовывать взаимодействие с сервером.

Пока не приступал  - сессия, экзамены на носу.

 
mi__x__an:

Настроенная уже ранее система Моделей позволяет и виртуально торговать и визуально....только вот не позволяет реальных рыночных стоп-уровней и отложек ставить - я решил что воплотить стоп уровни невозможно, так как по одному символу торговать могут разные модели, и пусть каждая сама решает когда ей входить а когда выходить из рынка, а  отложки - решил что контролировать их создание и выполненеие легче виртуально нежели реализовывать взаимодействие с сервером.


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

К сажалению, мои знания по MQL5 соответсвуют 1,5 летней давности. Тогда не было возможности автоматической переоптимизации, поэтому этот механизм мне совершенно не понятен. Но в любом случае нужно придерживаться концепции максимальной простоты, настолько насколько это возможно. Это значит, что структура любой торговой модели должна быть максимально простой. В идеале в ней должен быть только один единственный метод управления Prosessing() и открытая структура ее параметров. Всё. Весь остальной функционал должен навязываться неявно. Т.е. модель не должна знать, оптимизируют ли ее, торгует ли она виртуально или по-настоящему, инвертируют ее сигналы или нет. Все это должно быть от нее скрыто и происходить за кулисами. Представтье пользователя, который лишь в общих чертах знаком с ООП и программированием. Все что он может, это описать элементарные правила вроде "если скользящая_средняя > 20 тогда покупка иначе продажа". Должен ли он думать о возможности оптимизации, виртуальной торговли, управления ММ и пр.пр.пр.? Нет, не должен. Все что от него должно требоваться - это использовать функцию библиотеки SendOrder и писать свои правила в методе с нозванием Prosessing. Старайтесь решить задачу максимально приближенно к этому утверждению. Иначе, что бы написать робота на базе этой библиотеки придется получать второе высшее образование и тратить 90% времени не на саму идею, а на связку торговой модели с этой библиотекой. 

Другой вопрос как это сделать?  Вот общие правила:

1. Нагружать необходимыми параметрами  лишь базовый класс моделей CModel.

2. Конекретная торговая модель должна быть конечным классом в цепочке наследования и всегда должна содержать только правила генерации сигналов: Покупка, продажа, сопровождение ордеров.

3. Все что нужно знать библиотеке о конкретной модели, это ее уникальные параметры. Все остальное общие моменты, либо наследуемые с CModel либо реализуемые "за кулисами" функциями типа OrderSend().

4. Использовать длинные цепочки наследования. Т.к. возможности множественного наследования нет, придется разработать систему иерархии наследования. Смысл в том, что бы свести к минимуму количество конечных классов. Если есть возможность сделать какой-либо класс подмножеством другого - надо это делать.

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

6. Четко разделять управляющие модули от управляемых торговых моделей. Создавайте минимальное количество интерфейсов взаимодействия между ними.  

 

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

К сожалению полностью отстранить модель от этого невозможно просто. Предположим что модель МАКД торгует в реале. Тогда используемые данные будут читаться с последних(самых новых) баров буфферов индикатора, цен, спредов и т.д.

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

 

"1. Нагружать необходимыми параметрами  лишь базовый класс моделей CModel.

2. Конекретная торговая модель должна быть конечным классом в цепочке наследования и всегда должна содержать только правила генерации сигналов: Покупка, продажа, сопровождение ордеров.

 

Так и стараюсь делать - менять только основу, чтобу торговая модель позльовалась "плодами" других классов. И торговая модель у меня и есть конечный класс.

 "6. Четко разделять управляющие модули от управляемых торговых моделей. Создавайте минимальное количество интерфейсов взаимодействия между ними.  "

 Постараюсь.

 

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

 
В любом случае Вам виднее. Я уже год не занимаюсь MQL5 поэтому разными техническими тонкостями уже не владею. А вообще было бы здорово развить этот концепт в удобную опорную библиотеку, что бы создание эксперта занимало считанные минуты и пользователю не надо было ломать голову над мультисистемностью, мультивалютностью и пр., пр.
Причина обращения: