Обсуждение статьи "Расширение стандартной библиотеки MQL5 и повторное использование кода" - страница 2

 
//+------------------------------------------------------------------+
//|                                                   OOO_ZIGZAG.mq5 |
//|                        Copyright 2017, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#include <..\Include\Indicators\Indicator.mqh>


//--- input parameters
input ENUM_TIMEFRAMES   EAPeriod=PERIOD_CURRENT; //Период графика
input string            CurrencyPair="EURUSD.m"; //Символ

//+------------------------------------------------------------------+
//| Класс CiZigZag.                                                  |
//| Назначение: класс индикатора "ZigZag".                           |
//|          Выводится из класса CIndicator.                         |
//+------------------------------------------------------------------+
class CiZigZag : public CIndicator
  {
protected:
   int               m_depth;
   int               m_deviation;
   int               m_backstep;

public:
                     CiZigZag(void);
                    ~CiZigZag(void);
   //--- методы доступа к защищенным данным
   int               Depth(void)          const { return(m_depth);      }
   int               Deviation(void)      const { return(m_deviation);  }
   int               Backstep(void)       const { return(m_backstep);   }
   //--- метод создания
   bool              Create(const string symbol,const ENUM_TIMEFRAMES period,
                            const int depth,const int deviation_create,const int backstep);
   //--- методы доступа к данным индикатора
   double            ZigZag(const int index) const;
   double            High(const int index) const;
   double            Low(const int index) const;
   //--- метод идентификации
   virtual int       Type(void) const { return(IND_CUSTOM); }

protected:
   //--- методы настройки
   virtual bool      Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[]);
   bool              Initialize(const string symbol,const ENUM_TIMEFRAMES period,
                                const int depth,const int deviation_init,const int backstep);
  };
//+------------------------------------------------------------------+
//| Конструктор                                                      |
//+------------------------------------------------------------------+
CiZigZag::CiZigZag(void) : m_depth(-1),
                         m_deviation(-1),
                         m_backstep(-1)
  {
  }
//+------------------------------------------------------------------+
//| Деструктор                                                       |
//+------------------------------------------------------------------+
CiZigZag::~CiZigZag(void)
  {
  }
//+------------------------------------------------------------------+
//| Создаем индикатор "Zig Zag"                                      |
//+------------------------------------------------------------------+
bool CiZigZag::Create(const string symbol,const ENUM_TIMEFRAMES period,
                      const int depth,const int deviation_create,const int backstep)
  {
//--- проверяем историю
   if(!SetSymbolPeriod(symbol,period))
      return(false);
//--- создаем
   m_handle=iCustom(symbol,period,"Examples\\ZigZag",depth,deviation_create,backstep);
//--- проверяем результат
   if(m_handle==INVALID_HANDLE)
      return(false);
//--- индикатор успешно создан
   if(!Initialize(symbol,period,depth,deviation_create,backstep))
     {
      //--- ошибка инициализации
      IndicatorRelease(m_handle);
      m_handle=INVALID_HANDLE;
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Инициализируем индикатор с универсальными параметрами            |
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[])
  {
   return(Initialize(symbol,period,(int)params[0].integer_value,(int)params[1].integer_value,(int)params[2].integer_value));
  }
//+------------------------------------------------------------------+
//| Инициализируем индикатор со специальными параметрами             |
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,
                        const int depth,const int deviation_init,const int backstep)
  {
   if(CreateBuffers(symbol,period,3))
     {
      //--- строка состояния отрисовки
      m_name  ="ZigZag";
      m_status="("+symbol+","+PeriodDescription()+","+
               IntegerToString(depth)+","+IntegerToString(deviation_init)+","+
               IntegerToString(backstep)+") H="+IntegerToString(m_handle);
      //--- сохраняем настройки
      m_depth=depth;
      m_deviation=deviation_init;
      m_backstep=backstep;       
      //--- создаем буферы
      ((CIndicatorBuffer*)At(0)).Name("ZIGZAG");
      ((CIndicatorBuffer*)At(1)).Name("HIGH");
      ((CIndicatorBuffer*)At(2)).Name("LOW");
      //--- ok
      return(true);
     }
//--- ошибка
   return(false);
  }
//+------------------------------------------------------------------+
//| Доступ к буферу ZigZag индикатора "Zig Zag"                      |
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- проверяем
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| Доступ к буферу High индикатора "Zig Zag"                        |
//+------------------------------------------------------------------+
double CiZigZag::High(const int index) const
  {
   CIndicatorBuffer *buffer=At(1);
   //--- проверяем
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| Доступ к буферу Low индикатора "Zig Zag"                         |
//+------------------------------------------------------------------+
double CiZigZag::Low(const int index) const
  {
   CIndicatorBuffer *buffer=At(2);
//--- проверяем
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+



CiZigZag *Zig;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   Zig=new CiZigZag;
   Zig.Create(CurrencyPair,EAPeriod,12,5,3);
//---
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   delete(Zig);
  }  
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   int limit;
   if(prev_calculated==0)limit=0;
   else
     limit=prev_calculated-1; 
     
   for(int i=limit;i<rates_total && !IsStopped();i++)
      {
       Zig.Refresh();
       if (Zig.ZigZag(i)!=0) Print(Zig.ZigZag(i)," ",time[i]);  
      }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

Привожу полный код индикатора, где вывод значений индикатора происходит от настоящего в прошлое - а нужно наоборот

 
Tango_X:

Извините но все равно не понятно как менять направление индексации, к примеру если нет доступа к исходнику Zigzag. Направление индексации задает ArraySetAsSeries() - где входным параметром является массив по ссылке,  

но у нас этого массива нет а есть только указатель на массив буфера индикатора в виде

Базовый класс CIndicator имеет метод GetData, с помощью которого можно получить данные из индикаторного буфера.

Получает данные из буфера индикатора по стартовой позиции и количеству

int  GetData(
   const int      start_pos,      // позиция
   const int      count,          // количество
   const int      buffer_num,     // номер буфера
   double&        buffer[]        // массив
   ) const



После этого задавайте для вашего массива нужное направление индексации  с помощью ArraySetAsSeries

 
Rashid Umarov:

Базовый класс CIndicator имеет метод GetData, с помощью которого можно получить данные из индикаторного буфера.

Получает данные из буфера индикатора по стартовой позиции и количеству 

int  GetData(
   const int      start_pos,      // позиция
   const int      count,          // количество
   const int      buffer_num,     // номер буфера
   double&        buffer[]        // массив
   ) const



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

т.е. получается два раза обращаться к буферу индикатора но по разному? Ведь тут ниже мы имеем уже доступ к значениям буфера индикатора? Получаем как бы промежуточный массив  double &buffer[]    Я Вас правильно понял?

//+------------------------------------------------------------------+
//| Доступ к буферу ZigZag индикатора "Zig Zag"                      |
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- проверяем
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
 
Rashid Umarov:

Базовый класс CIndicator имеет метод GetData, с помощью которого можно получить данные из индикаторного буфера.

Получает данные из буфера индикатора по стартовой позиции и количеству

int  GetData(
   const int      start_pos,      // позиция
   const int      count,          // количество
   const int      buffer_num,     // номер буфера
   double&        buffer[]        // массив
   ) const



После этого задавайте для вашего массива нужное направление индексации  с помощью ArraySetAsSeries

Я Вас правильно понял???

CiZigZag *Zig;
double ArrZig[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   Zig=new CiZigZag;
   Zig.Create(CurrencyPair,EAPeriod,12,5,3);

   SetIndexBuffer(0,ArrZig,INDICATOR_CALCULATIONS);
   ArraySetAsSeries(ArrZig,false);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   delete(Zig);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   int limit;
   if(prev_calculated==0) limit=0;
   else
      limit=prev_calculated-1;

   Zig.Refresh();
   Zig.GetData(0,rates_total-1,0,ArrZig);

   for(int i=limit;i<rates_total-1 && !IsStopped();i++)
     {

      //if (Zig.ZigZag(i)!=0) Print(Zig.ZigZag(i)," ",time[i]);  
      if(ArrZig[i]!=0) Print(ArrZig[i]," ",time[i]);
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
Получается что надо на каждом тике нужно копировать всю историю?
 
Tango_X:

Я Вас правильно понял???

Получается что надо на каждом тике нужно копировать всю историю?

1. Можно на открытие нового бара

2. А зачем все значения индикатора получать каждый раз, и при этом еще заботиться о направлении индексации? какая вообще задача стоит?

 

Зачем оборачивать простой индикатор в класс если он используется потом или на графике или через iCustom?

Второе решение лучше, потому что является объектно-ориентированным

ООП ради ООП, ну ок.

 
Rashid Umarov:

1. Можно на открытие нового бара

2. А зачем все значения индикатора получать каждый раз, и при этом еще заботиться о направлении индексации? какая вообще задача стоит?


Проблему решил по условиям цикла, теперь все работает как хотелось. спасибо!

 
Комбинатор:

Зачем оборачивать простой индикатор в класс если он используется потом или на графике или через iCustom?

ООП ради ООП, ну ок.


Все верно))

Очень удобно, всем советую
Причина обращения: