ООП: создаем простой класс для объекта "линия"

Программирование прибыли: от азов к секретам мастерства. Читайте, спрашивайте, делитесь опытом.
Бонус за сообщение 0.5$
Ответственный Модератор - Haos

ООП: создаем простой класс для объекта "линия"

Сообщение Kalkin » 30 сен 2017, 17:07

Часто в советниках или индикаторах возникает необходимость графически отобразить какие-то ценовые уровни или метки времени. Например, мне часто приходится внедрять в советники условия, по которым устанавливается рабочее время. Пример того, как можно заставить советник работать не круглосуточно, а в заданное время, отражена в статье уважаемого Haosa Как торговать в промежутке времени?. А для визуального отображения начала и конца этого периода имеет смысл на графике автоматически устанавливать вертикальные временныЫе метки. Сейчас мы создадим инструмент, который позволит легко внедрять в код программы все необходимое для простого создания и управления объектом "вертикальная линия". Потом перейдем и к горизонтальным линиям.

Чем приятно объектно ориентированное программирование (ООП), так это тем, что в одном месте можно собрать все, что касается функционирования описываемого объекта. Для вертикальной линии для подавляющего большинства случаев нужно совсем немного - создать линию, определить ей цвет, стиль отрисовки и самое главное - время на ценовом графике, на котором она будет установлена. Для решения задачи создадим класс:
Код: выделить все
class CTimeLine
{
private:
   string m_name;
public:
   CTimeLine(string Name) {m_name = Name; }  // конструктор класса
   ~CTimeLine() { ObjectDelete(m_name);}            // деструктор класса
   void SetLine(datetime Zone, color LineColor)
   {
      if (ObjectFind(m_name)<0)
      {
         ObjectCreate(m_name,OBJ_VLINE,0,Zone,0);
      }
      ObjectSet(m_name,OBJPROP_TIME1,Zone);
      ObjectSet(m_name,OBJPROP_STYLE,STYLE_DASHDOTDOT);
      ObjectSet(m_name,OBJPROP_COLOR,LineColor);
   }
};

Этот код вставляется в текст программы или присоединяется отдельным файлом директивой #include.
Класс получил название CTimeLine, оно будет использоваться в качестве типа для объявления экземпляров класса. Так как любой объект на графике должен иметь свое имя, в приватной части описания класса под имя выделено строковое поле m_name. В это поле единожды в момент создания экземпляра класса будет записано имя объекта, и затем все методы класса могут с ним работать. Для этого в параметры конструктора передается строка, которая и записывается в поле m_name:
Код: выделить все
   CTimeLine(string Name) {m_name = Name; }  // конструктор класса

Еще при использовании ООП нет необходимости удалять объекты в функции деинициализации, так как эту процедуру можно выполнить при описании класса в его деструкторе. Сколько бы мы объектов ни создали, при завершении работы советника или индикатора автоматически вызовутся все деструкторы классов, в которых мы пропишем удаление объекта с графика:
Код: выделить все
~CTimeLine() { ObjectDelete(m_name);}            // деструктор класса

Как видите, поскольку имя объекта у нас есть, то нет необходимости в переборе всех объектов графика и поиске нужного.
Дальнейшие методы, включенные в класс, могут быть самые разнообразные, необходимые для функциональности программы. Например, можно объявить отдельные методы для создания, перемещения, управления цветом и стилем объекта. Мы же для упрощения управлением линии все функции запишем в один метод SetLine(...), в который передадим местоположение и цвет объекта, а все функции по созданию и установкой свойств впишем в его тело:
Код: выделить все
   void SetLine(datetime Zone, color LineColor)
   {
      if (ObjectFind(m_name)<0)
      {
         ObjectCreate(m_name,OBJ_VLINE,0,Zone,0);  // создание объекта "вертикальная линия"
      }
      ObjectSet(m_name,OBJPROP_TIME1,Zone); // установка времени
      ObjectSet(m_name,OBJPROP_STYLE,STYLE_DASHDOTDOT); // установка типа линии
      ObjectSet(m_name,OBJPROP_COLOR,LineColor);// установка цвета линии
   }
Аватар пользователя
Kalkin
 
Сообщений: 1589
Зарегистрирован: 05 мар 2015, 06:51
Средств на руках: 108.80 Доллар
Награды: 2
Ветеран I (1) Медаль за научный вклад (1)
Группа: Базовая
Благодарил (а): 633 раз.
Поблагодарили: 1190 раз.
Ace Register Votive

ООП: создаем простой класс для объекта "линия"

Сообщение Kalkin » 30 сен 2017, 17:35

Как использовать класс CTimeLine

Если нам надо две линии (начало и окончание торговой зоны), то мы объявляем два экземпляра класса как глобальные переменные:
Код: выделить все
CTimeLine objStartLine("НачалоТорговли");
CTimeLine objStopLine("ОкончаниеТорговли");

В настройках советника можно создать параметры, определяющие начало и окончание торгов:
Код: выделить все
input string   strTradeT1  = "09:00";   // Время начала торговли (hh:mi)
input string   strTradeT2  = "20:00";   // Время окончания торговли (hh:mi)

А в коде советника или индикатора просто для каждой линии устанавливаем свое значение времени и цвета:
Код: выделить все
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   .......
  objStartLine.SetLine(StrToDate(strTradeT1), clrGreen); // устанавливаем линию начала зоны торговли
  objStopLine.SetLine(StrToDate(strTradeT2), clrRed); // устанавливаем линию окончания зоны торговли
}


Как видите, ничего сложного в ООП нет совершенно и теперь ежедневно зоны начала и окончания торгов будут отображаться вертикальными линиями.
Аватар пользователя
Kalkin
 
Сообщений: 1589
Зарегистрирован: 05 мар 2015, 06:51
Средств на руках: 108.80 Доллар
Награды: 2
Ветеран I (1) Медаль за научный вклад (1)
Группа: Базовая
Благодарил (а): 633 раз.
Поблагодарили: 1190 раз.
Ace Register Votive

ООП: создаем простой класс для объекта "линия"

Сообщение Kalkin » 11 окт 2017, 10:15

Горизонтальная линия
Таким же образом можно создать класс для работы с горизонтальной линией. Все, что надо изменить по сравнению с предыдущим классом - при создании объекта указать тип "горизонтальная линия", а при вызове метода установки линии вместо времени передавать значение цены, на которой должна быть установлена линия:

Код: выделить все
    class CPriceLine
    {
    private:
       string m_name;
    public:
       CPriceLine(string Name) {m_name = Name; }  // конструктор класса
       ~CPriceLine() { ObjectDelete(m_name);}            // деструктор класса
       void SetLine(double Price, color LineColor)
       {
          if (ObjectFind(m_name)<0)
          {
             ObjectCreate(m_name,OBJ_HLINE,0,0,0);
          }
          ObjectSet(m_name,OBJPROP_PRICE1,Price);
          ObjectSet(m_name,OBJPROP_STYLE,STYLE_DASHDOTDOT);
          ObjectSet(m_name,OBJPROP_COLOR,LineColor);
       }
    };



Использование класса CPriceLine.

Для наглядности сделаем индикатор, который будет в реальном времени на графике отображать уровни StopLevel. Создадим два экземпляра класса CPriceLine для верхнего и нижнего уровня:
Код: выделить все
CPriceLine plHighLevel("Верхний StopLevel");
CPriceLine plLowLevel("Нижний StopLevel");

В функции расчета индикатора вычислим оба интересующих нас уровня:
Код: выделить все
   double HighStopLevel = Ask+MarketInfo(NULL,MODE_STOPLEVEL)*Point; // верхнее значение уровня StopLevel
   double LowStopLevel = Bid-MarketInfo(NULL,MODE_STOPLEVEL)*Point;  // нижнее значение уровня StopLevel

И передадим полученные уровни методам установки линии для каждого объекта:
Код: выделить все
   plHighLevel.SetLine(HighStopLevel,clrOrange);
   plLowLevel.SetLine(LowStopLevel,clrOrange);


Индикатор будет на расстоянии, равном StopLevel от цен Bid и Ask отображать уровни:
Индикатор STOPLEVELS.png

Сам индикатор можно скачать по ссылке ниже:
Вложения
KI_StopLevels.mq4
(5.03 KB) Скачиваний: 69
Аватар пользователя
Kalkin
 
Сообщений: 1589
Зарегистрирован: 05 мар 2015, 06:51
Средств на руках: 108.80 Доллар
Награды: 2
Ветеран I (1) Медаль за научный вклад (1)
Группа: Базовая
Благодарил (а): 633 раз.
Поблагодарили: 1190 раз.
Ace Register Votive


Вернуться в MQL – теория и практика

Кто сейчас на форуме?

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 37

Права доступа к форуму

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения