Учёба. Классы. Нужна помощь.

 

Вынес вопрос в отдельную тему, ибо подобные вопросы ещё будут.

Программирую на MQL4 уже 18 лет. Я не могу найти применения такой вещи, как класс. Вразумите меня глупого, где это можно применить в MQL? Какая в этом необходимость?

Берём Delphi. Есть такой класс в нём, как кнопка. Да, согласен, можно перетащить его на форму и задействовать наследование. Н это Делфи. Где в MQL применимы классы и какая в них необходимость? Наверно я что-то не знаю.

 
Поставьте мне напрямую задачу, сделать код без классов и сделать тот же код с задействованием классов.  Я хочу увидеть полезность этого на живом примере.
 
Vitaly Murlenko:

Вынес вопрос в отдельную тему, ибо подобные вопросы ещё будут.

Программирую на MQL4 уже 18 лет. Я не могу найти применения такой вещи, как класс. Вразумите меня глупого, где это можно применить в MQL? Какая в этом необходимость?

Берём Delphi. Есть такой класс в нём, как кнопка. Да, согласен, можно перетащить его на форму и задействовать наследование. Н это Делфи. Где в MQL применимы классы и какая в них необходимость? Наверно я что-то не знаю.

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

 
JRandomTrader #:

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

Сделал то же самое без классов, через Switch

 
Vitaly Murlenko #:
Поставьте мне напрямую задачу, сделать код без классов и сделать тот же код с задействованием классов.  Я хочу увидеть полезность этого на живом примере.

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

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

Ещё пример - у тебя есть данные, которые ты записывал в какой-то файл, и потом оттуда считывал при необходимости. А тут - понадобилось тоже самое сделать в виде SQL-базы. Без ООП-подхода - ты с лёгкостью можешь пропустить реализацию каких-то частей, поскольку у тебя все функции лежат отдельно. С ООП-подходом - у тебя есть общий интерфейс записи и считывания данных. Соответственно, для перехода к SQL-базе ты наследуешься от своего интерфейса, и реализуешь его в виде SQL-запросов. Ничего не пропускаешь (просто не скомпилируется), при этом точно знаешь, что никуда не "влезешь" в работающих частях всей программы. 

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

 
Dmi3 #:

Сделал то же самое без классов, через Switch

Да можно и так и так сделать! Однако, что произойдёт, когда ты захочешь добавить ещё одного робота? Со switch'ом - ты с большой вероятностью можешь "потерять" функции, и потом они "вылезут" в самый неподходящий момент. 

С классами - ты просто не сможешь скомпилировать модуль, не реализовав весь виртуальный интерфейс. 

ООП - фактически, это просто ряд соглашений. Следовать им или нет - дело твоё... 

 
Georgiy Merts #:

Да можно и так и так сделать! Однако, что произойдёт, когда ты захочешь добавить ещё одного робота? Со switch'ом - ты с большой вероятностью можешь "потерять" функции, и потом они "вылезут" в самый неподходящий момент. 

С классами - ты просто не сможешь скомпилировать модуль, не реализовав весь виртуальный интерфейс. 

ООП - фактически, это просто ряд соглашений. Следовать им или нет - дело твоё... 

Что значит "потерять"? и "вылезут"? Добавлял/Убирал многократно и без проблем.

 
Dmi3 #:

Что значит "потерять"? и "вылезут"? Добавлял/Убирал многократно и без проблем.

Зависит от того, как это реализовано. Если через switch переключаются большие блоки функций (генератор входов, фильтры по нескольким параметрам, определитель TP-SL, контроль трейлинга) - то "добавление/убирание" надо же сделать по всем этим функциям. Одно дело, если их у тебя одна-две. А вот если их два десятка - и добавление длится целую неделю, пока ты все их напишешь для нового робота, то упомнить, что уже написано, а что нет - лично я не могу. А значит, ненаписанная функция потом может "всплыть", когда ты будешь отлаживать совсем другое место. По мне - куда проще, когда сам компилятор тебе указывает, какие функции ещё не реализованы. Виртуальный интерфейсный класс, и наследники с реализацией - по мне, тут очень даже к месту. 

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

 
Dmi3 #:

Сделал то же самое без классов, через Switch

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

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

Далее производные классы с реализацией конкретных алгоритмов открытия и закрытия.

И далее - собственно файл создания этих роботов, каждому соответствует одна строчка. Вот так, например:

...
   CHK_LOT(Lot154124)STRAT(AFrSt_St(154124,MODE_144|MODE_VR, MODE_144|MODE_VR|MODE_OR, MODE_VR|MODE_A, MODE_OR|MODE_A|MODE_2, 1.0, 1.0, 2.8, 2.8, REAL, Lot154124))

   CHK_LOT(Lot153064)STRAT(AFrSt(153064,MODE_143|MODE_VR|MODE_OR|MODE_A, MODE_143|MODE_VR|MODE_OR, 0, MODE_VR|MODE_A|MODE_2, 1.3, 1.5, 1.6, 0.95, REAL, Lot153064))
   CHK_LOT(Lot153065)STRAT(AFrSt(153065,MODE_143|MODE_VR|MODE_OR|MODE_A, MODE_143|MODE_VR|MODE_OR, 0, MODE_VR|MODE_OR|MODE_A, 1.3, 1.5, 1.6, 1.23, REAL, Lot153065))

   CHK_LOT(Lot153066)STRAT(AFrSt(153066,MODE_143|MODE_VR|MODE_A, MODE_143|MODE_VR|MODE_OR, MODE_VR|MODE_A|MODE_2, MODE_VR|MODE_A|MODE_2, 1.0, 1.5, 0.95, 0.95, REAL, Lot153066))
   CHK_LOT(Lot153067)STRAT(AFrSt(153067,MODE_143|MODE_VR|MODE_A, MODE_143|MODE_VR|MODE_OR, MODE_VR|MODE_A|MODE_2, MODE_VR|MODE_OR|MODE_A, 1.0, 1.5, 0.95, 1.23, REAL, Lot153067))

   CHK_LOT(Lot153068)STRAT(AFrSt(153068,MODE_143|MODE_OR, MODE_143|MODE_VR|MODE_OR, MODE_VR|MODE_OR|MODE_A|MODE_2|MODE_SMART1, MODE_VR|MODE_A|MODE_2, 1.5, 1.5, 0.95, 0.95, REAL, Lot153068))
   CHK_LOT(Lot153069)STRAT(AFrSt(153069,MODE_143|MODE_OR, MODE_143|MODE_VR|MODE_OR, MODE_VR|MODE_OR|MODE_A|MODE_2|MODE_SMART1, MODE_VR|MODE_OR|MODE_A, 1.5, 1.5, 0.95, 1.23, REAL, Lot153069))

   CHK_LOT(Lot153546)STRAT(AFrSt(153546,MODE_143|MODE_VR|MODE_OR, MODE_143|MODE_VR|MODE_OR, MODE_VR|MODE_A|MODE_2, MODE_VR|MODE_A|MODE_2, 1.3, 1.3, 1.3, 1.3, 0.95, 0.95, 0.4, 0.4, REAL, Lot153546))
...

Это конкретно те, что у меня сейчас работают на MIX-12.24. Есть файлы с сотнями роботов, работающих в тестовом режиме - с имитацией сделок.

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

 
JRandomTrader #:

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

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

Далее производные классы с реализацией конкретных алгоритмов открытия и закрытия.

И далее - собственно файл создания этих роботов, каждому соответствует одна строчка. Вот так, например:

Это конкретно те, что у меня сейчас работают на MIX-12.24. Есть файлы с сотнями роботов, работающих в тестовом режиме - с имитацией сделок.

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

А у меня, с функциональным программированием, отдельный робот индивидуален и автономен. Есть какие-то общие функции, вынесенные в #include файл, все остальное в алгоритме свое. Есть к нему файл csv, содержащий символы для операций, необходимые наборы параметров и сохраняющий все необходимые для рестарта значения и немного аналитики результатов. Строк может быть любое количество. Каждая строка может быть отдельным алгоритмом или частью облака параметров для отдельного алгоритма или комбинацией этих вариантов.

А, ну и да, переделать тоже давно все хочется, но у меня для этого не хватает квалификации. А местные программисты почему-то считают, что более одного алгоритма на инструменте работать не может и так далее...
 

Вот с чем я столкнулся, прямо сейчас… Ещё не дописал что хотел…

Переписываю мультивалютник. Было: все параметры позиций записаны в массив структур. Ну, крайне неудобно. Теперь переписываю с помощью Артёма Тришкина, вместо массива структур применяю список объектов. Соответственно без классов это сделать вообще никак…  Так вот в массиве структур надо в цикле искать нужную запись. А в списке объектов просто как в отсортированном массиве 

  listNB.Sort(0);
//--- Получим индекс нужного объекта в списке
  int index = listNB.Search(&tmpNB);

Всё! Рыбка поймана, делай с ней что пожелаешь. Удобно…

Есть конечно варианты сортировки структур, но………… мне не нравится.