Помогите исправить ошибку

 
Здравствуйте. Перехожу с MQL4 на MQL5 и переписываю индикаторы, которые использовал. В этом индикаторе в левом верхнем углу выводятся
положения трех МА относительно друг друга по всем ТФ. Индикатор не работает, ошибка скорее всего в неправильном обращении к стандартному индикатору iMA.
Помогите, пожалуйста, исправить ошибку.
//+------------------------------------------------------------------+
//|                                                   3SMA_Trend.mq5 |
//|                                             Copyright 2010, MaxL |
//|                                                   maxl85@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MaxL"
#property link      "maxl85@mail.ru"
#property version   "1.00"
#property indicator_chart_window

string name1[] = {"M2","M3","M4","M5","M6","M10","M12","M15","M20","M30","H1","H2","H3","H4","H6","H8","H12","D1"};
string name2[] = {"M2B","M3B","M4B","M5B","M6B","M10B","M12B","M15B","M20B","M30B","H1B","H2B","H3B","H4B","H6B","H8B","H12B","D1B"};



double MA40[1],MA100[1],MA200[1];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+

int OnInit()
  {
//--- indicator buffers mapping
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---

   color color_trend;
   string txt[]={"M2","M3","M4","M5","M6","M10","M12","M15","M20","M30","H1","H2","H3","H4","H6","H8","H12","D1"};
   ENUM_TIMEFRAMES TF[]=
     {
      PERIOD_M2,PERIOD_M3,PERIOD_M4,PERIOD_M5,PERIOD_M6,PERIOD_M10,PERIOD_M12,PERIOD_M15,PERIOD_M20,
      PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1
     };

   int Y1[] = {32,32,32,32,32,32,32,32,32,60,60,60,60,60,60,60,60,60};
   int X1[] = {9,35,60,87,113,136,162,188,214,6,34,60,86,112,138,164,188,216};
   int Y2[] = {17,17,17,17,17,17,17,17,17,45,45,45,45,45,45,45,45,45};
   int X2[] = {0,26,52,78,104,130,156,182,208,0,26,52,78,104,130,156,182,208};

   for(int i=0; i<ArraySize(txt); i++)
     {

      MqlParam params[];
      int MA40_h,MA100_h,MA200_h;

      ArrayResize(params,4);
      //--- set ma_period
      params[0].type         =TYPE_INT;
      params[0].integer_value=40;
      //--- set ma_shift
      params[1].type         =TYPE_INT;
      params[1].integer_value=0;
      //--- set ma_method
      params[2].type         =TYPE_INT;
      params[2].integer_value=MODE_SMA;
      //--- set applied_price
      params[3].type         =TYPE_INT;
      params[3].integer_value=PRICE_CLOSE;
      //--- create MA
      MA40_h=IndicatorCreate(NULL,TF[i],IND_MA,4,params);

      params[0].integer_value=100;
      MA100_h=IndicatorCreate(NULL,TF[i],IND_MA,4,params);

      params[0].integer_value=200;
      MA200_h=IndicatorCreate(NULL,TF[i],IND_MA,4,params);

      CopyBuffer(MA40_h,0,1,1,MA40);
      CopyBuffer(MA100_h,0,1,1,MA100);
      CopyBuffer(MA200_h,0,1,1,MA200);

      color_trend=DarkGray;
      if(MA40[0]>MA100[0] && MA100[0]>MA200[0]) color_trend = Green;
      if(MA40[0]<MA100[0] && MA100[0]<MA200[0]) color_trend = Crimson;

      ObjectCreate(0,name1[i],OBJ_LABEL,0,0,0);
      ObjectSetString(0,name1[i],OBJPROP_TEXT,txt[i]);
      ObjectSetString(0,name1[i],OBJPROP_FONT,"Arial");
      ObjectSetInteger(0,name1[i],OBJPROP_FONTSIZE,7);
      ObjectSetInteger(0,name1[i],OBJPROP_COLOR,Black);
      ObjectSetInteger(0,name1[i],OBJPROP_XDISTANCE,X1[i]);
      ObjectSetInteger(0,name1[i],OBJPROP_YDISTANCE,Y1[i]);

      ObjectCreate(0,name2[i],OBJ_LABEL,0,0,0);
      ObjectSetString(0,name2[i],OBJPROP_TEXT,"O");
      ObjectSetString(0,name2[i],OBJPROP_FONT,"Arial");
      ObjectSetInteger(0,name2[i],OBJPROP_FONTSIZE,27);
      ObjectSetInteger(0,name2[i],OBJPROP_COLOR,color_trend);
      ObjectSetInteger(0,name2[i],OBJPROP_XDISTANCE,X2[i]);
      ObjectSetInteger(0,name2[i],OBJPROP_YDISTANCE,Y2[i]);

      IndicatorRelease(MA200_h);
      IndicatorRelease(MA100_h);
      IndicatorRelease(MA40_h);
     }

//--- return value of prev_calculated for next call*/
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   string txt;
   for(int i=ObjectsTotal(0,0,-1); i>=0; i--)
     {
      txt=ObjectName(0,i,0,-1);
      for(int j=0; j<ArraySize(name1); j++)
        {
         if(StringFind(txt,name1[j])>-1) ObjectDelete(0,txt);
        }
     }
   ChartRedraw(0);
  }

 

А зачем каждый раз инициализировать все индикаторы?

 Не проще в ините просто один раз создать хэндлы, а потом в калкулейт опрашивать их, ну и в деинит соответственно сделать релиз?

 
hasayama:

А зачем каждый раз инициализировать все индикаторы?

 Не проще в ините просто один раз создать хэндлы, а потом в калкулейт опрашивать их, ну и в деинит соответственно сделать релиз?

Все будет еще и красивее, если использовать структуры/классы.

 
hasayama:

А зачем каждый раз инициализировать все индикаторы?

 Не проще в ините просто один раз создать хэндлы, а потом в калкулейт опрашивать их, ну и в деинит соответственно сделать релиз?

В OnInit я не знаю возможно ли передать параметр таймфрейма, или для каждого ТФ создавать по 3 хэндла МА???
 
alexvd:

Все будет еще и красивее, если использовать структуры/классы.

А можно поподробнее а еще лучше с примером
 
MaxL:
В OnInit я не знаю возможно ли передать параметр таймфрейма, или для каждого ТФ создавать по 3 хэндла МА???

Нужно создать массив хэндлов. То есть цикл в ините будет примерно такой же, только без КопиБуфер.

В теле индикатора только обращаетесь к уже инициализированным хэндлам.

Релиз на каждой итерации тоже бред. 

Это должно ускорить работу индикатора, сейчас он уж очень неэффективно использует ресурсы.

Еще одно - создавать объекты тоже не нужно каждый раз. Короче, суть такая:

ИНИТ: инициализируем хэндлы и создаем заготовки объектов (просто размещаем их на графике с нейтральными свойствами) .

КАЛКУЛЕЙТ: запрашиваем КопиБуфер и изменяем свойства объектов, если нужно.

ДЕИНИТ: удаляем объекты и освобождаем индикаторы. 

Документация по MQL5: Стандартные константы, перечисления и структуры / Константы объектов / Свойства объектов
Документация по MQL5: Стандартные константы, перечисления и структуры / Константы объектов / Свойства объектов
  • www.mql5.com
Стандартные константы, перечисления и структуры / Константы объектов / Свойства объектов - Документация по MQL5
 

На скорую руку...

Часть кода переносим в структуру. Массив TF заменяем на массив структур.

struct STF
  {
   ENUM_TIMEFRAMES   m_tf;
   int               m_h[3];
   bool              Init()
     {
      MqlParam params[];
      ArrayResize(params,4);
      //--- set ma_period
      params[0].type         =TYPE_INT;
      params[0].integer_value=40;
      //--- set ma_shift
      params[1].type         =TYPE_INT;
      params[1].integer_value=0;
      //--- set ma_method
      params[2].type         =TYPE_INT;
      params[2].integer_value=MODE_SMA;
      //--- set applied_price
      params[3].type         =TYPE_INT;
      params[3].integer_value=PRICE_CLOSE;
      //--- create MA
      m_h[0]=IndicatorCreate(NULL,m_tf,IND_MA,4,params);

      params[0].integer_value=100;
      m_h[1]=IndicatorCreate(NULL,m_tf,IND_MA,4,params);

      params[0].integer_value=200;
      m_h[2]=IndicatorCreate(NULL,m_tf,IND_MA,4,params);
      return((m_h[0]!=INVALID_HANDLE && m_h[1]!=INVALID_HANDLE && m_h[2]!=INVALID_HANDLE)?true:false);
     }
   double            MA(int index)
     {
      if(m_h[index]!=INVALID_HANDLE || BarsCalculated(m_h[index])>=1)
        {
         double data[1];
         if(CopyBuffer(m_h[index],0,0,1,data)==1)
            return(data[0]);
        }
      return(EMPTY_VALUE);
     }
  };

В этом случае в онинит прописываем цикл инициализации (создание хэндлов).

В ОнКалькулейт пропадает блок получения хэндлов и копирования из буферов - все делается дерганием значений от структур.


Далее:

  • можно поутаскивать в структуру остальные массивы
  • замените IndicatorCreate на iMA (вы же только МАшки используете). И вам нагляднее будет и избавитесь от необходимости использования структуры MqlParam.
Документация по MQL5: Стандартные константы, перечисления и структуры / Структуры данных / Структура входных параметров индикатора
Документация по MQL5: Стандартные константы, перечисления и структуры / Структуры данных / Структура входных параметров индикатора
  • www.mql5.com
Стандартные константы, перечисления и структуры / Структуры данных / Структура входных параметров индикатора - Документация по MQL5
 
Спасибо за ответы. Сейчас буду пробовать
Причина обращения: