Обсуждение статьи "Создание пользовательских индикаторов с использованием класса CCanvas"

 

Опубликована статья Создание пользовательских индикаторов с использованием класса CCanvas:

В статье рассмотрен пример создания рисованных пользовательских индикаторов с помощью графических примитивов класса CCanvas.

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


Рис.5 Базовая структура кругового индикатора с дуговой секционной индикацией.

Автор: Alexander Fedosov

 

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

 

О, какая красота! Добавляю себе в мемориз ;) 
 

Обращу еще раз внимание на то, что при применении нескольких копий одного и того же индикатора, реализованного с помощью классов CustomGUI, имена в методе Create() должны отличаться. В качестве примера, реализация ниже.

#property version   "1.00"
#property indicator_chart_window
#property indicator_plots 0
//---
#include <CustomGUI\CustomGUI.mqh>
CCircleSection ind;
//+------------------------------------------------------------------+
//|  Входные параметры индикатора                                    |
//+------------------------------------------------------------------+
input ENUM_TIMEFRAMES   tf=PERIOD_CURRENT;
input int               period=10;
input int               indsize=50;
input ENUM_ORIENTATION  orient=VERTICAL;
input int               X=100;
input int               Y=100;
//---
int      IndHandle;
double   rsi[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- получение хендла индикатора
   IndHandle=iRSI(Symbol(),tf,period,PRICE_CLOSE);
   if(IndHandle==INVALID_HANDLE)
     {
      Print("Failed to get indicator handle");
      return(INIT_FAILED);
     }
   ArraySetAsSeries(rsi,true);
//---
   ind.Radius(indsize);
   ind.LabelSize(15);
   ind.LabelValue("RSI "+"("+IntegerToString(period)+")");
   ind.Orientation(orient);
   ind.Create("rsi_custom"+IntegerToString(MathRand()),X,Y);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   if(CopyBuffer(IndHandle,0,0,1,rsi)<1)
      return(0);
   ind.NewValue(rsi[0]);
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ind.Delete();
   ChartRedraw();
  }
//+------------------------------------------------------------------+

Метод Create() имеет уникальное имя.

Файлы:
 

спасибо.

можно ли реализовать в МТ4 или МТ5 функцию выделения объекта индикатора? (например, линия).

к примеру двойной щелчок по линии и она выделяется жирной линией, появляется описание линии, и наоборот.

 
Ilmir Galiev:

спасибо.

можно ли реализовать в МТ4 или МТ5 функцию выделения объекта индикатора? (например, линия).

к примеру двойной щелчок по линии и она выделяется жирной линией, появляется описание линии, и наоборот.

Нет. Суть данного способа в том, что это картинка, которая перерисовывается при изменении каких-либо условий. Она не реагирует на события горячих клавиш или щелчков мыши.
 
Alexander Fedosov:
Нет. Суть данного способа в том, что это картинка, которая перерисовывается при изменении каких-либо условий. Она не реагирует на события горячих клавиш или щелчков мыши.

Да ладно. А щелчки мыши это что? Не "изменение каких-либо условий". При этом генерируется событие, по которому и перерисовывайте канвас, как надо. Ilmir, на Ваш вопрос правильный ответ -- конечно можно.

 

Хорошая тема. Спасибо автору, буду делать тиковый индикатор на холсте...

Приметил такое. 

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CCanvasBase
  {
private:
   //--- Имя холста
   string            m_canvas_name;
   //--- Координаты холста
   int               m_x;
   int               m_y;
   //--- Размер холста
   int               m_x_size;
   int               m_y_size;
protected:
   CCanvas           m_canvas;
   //--- Создает графический ресурс для объекта
   bool              CreateCanvas(void);
   //--- Удаляет графический ресурс
   bool              DeleteCanvas(void);
public:
                     CCanvasBase(void);
                    ~CCanvasBase(void);
   //--- Устанавливает и возвращает координаты
   void              X(const int x)                         { m_x=x;                      }
   void              Y(const int y)                         { m_y=y;                      }
   int               X(void)                                { return(m_x);                }
   int               Y(void)                                { return(m_y);                }
   //--- Устанавливает и возвращает размеры
   void              XSize(const int x_size)                { m_x_size=x_size;            }
   void              YSize(const int y_size)                { m_y_size=y_size;            }
   int               XSize(void)                            { return(m_x_size);           }
   int               YSize(void)                            { return(m_y_size);           }
   //--- Устанавливает имя индикатора при создании
   void              Name(const string canvas_name) { m_canvas_name=canvas_name;  }
  };

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

 
Dennis Kirichenko:

Хорошая тема. Спасибо автору, буду делать тиковый индикатор на холсте...

Как будут наброски, скиньте скрины/видео. Сам выложил такой индикатор, но не пошел в народ. Хотя лучше так и не встретил. Интересно посмотреть другие решения на канвасе.

 
fxsaber:

Сам выложил такой индикатор, но не пошел в народ.

Пошел, пошел.

Я даже на его основе пробую индикатор тиковой скорости запилить.

 
Andrey Khatimlianskii:
Пошел, пошел.

Я даже на его основе пробую индикатор тиковой скорости запилить.

Это приятная новость! А в чем идея? Вместо тиковой истории подставлять кастомный временной ряд?

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