Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 670

 
Roman Sharanov:
Как создать массив экземпляров класса?
Сделал ClassName* className[], потом на него ArrayResize, но не дает доступ к методам invalid pointer access

Ваш класс, экземпляры которого хотите в массив собирать, должен быть наследован от CObject.

А далее всё просто: создаёте список (массив) объектов CArrayObj, и в него добавляете свои объекты.

 
psyman:

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

Какое-нибудь сочетание слов из поста припомните.

Ну, прошу прощения, про шаблон индикатора может быть я попутал - шаблон трала выкладывал.

Давайте так: создайте в редакторе шаблон индикатора, при создании добавьте нужное количество входных переменных и рисуемых буферов.

Далее разберём что нужно делать из конкретной задачи.

 
psyman:

Вы если говорите что плохо, скажите как сделать хорошо. Перенести вычисления в OnInit?

Справедливый упрек ))  Вот, вариант кода, который был опубликован здесь:

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 i,limit;
   if(prev_calculated == 0) {
      limit = rates_total - 1;    //--- Первый вызов индикатора или смена таймфрейма или подгрузка данных из истории
   }
   else limit = rates_total - prev_calculated + 1;

   for(i = limit; i >= 0; i--) { //--- В этом цикле основные вычисления. Таким образом обрабатываться будет только "свежая" информация                       
   }
   return(rates_total);

Попробуйте так делать. А в OnInit ничего переносить не надо.

 
Andrei Novichkov:

Справедливый упрек ))  Вот, вариант кода, который был опубликован здесь:

Попробуйте так делать. А в OnInit ничего переносить не надо.

Я такой код не публиковал здесь - не моё :)

Использую иные конструкции - проще и понятнее.

В OnInit() нужно переносить. Зачем на каждом тике назначать массив индикаторному буферу?

 
Artyom Trishkin:

Я такой код не публиковал здесь - не моё :)

Использую иные конструкции - проще и понятнее.

это мое, куда же проще? ))) (по крайней мере у меня тоже в шаблоне есть комментарий  limit = rates_total - 1;    //--- Первый вызов индикатора или смена таймфрейма или подгрузка данных из истории) и мой стиль форматирования одна фигурная скобка около for() {

ну а по сабжу, чтобы научиться написать свой индикатор, берем шаблон указанный выше и добавляем хотя бы цену закрытия и получаем свой первый индикатор, потом учимся от этой цены закрытия делать МАшку

for(i = limit; i >= 0; i--) { //--- В этом цикле основные вычисления. Таким образом обрабатываться будет только "свежая" информация                       
Buffer[i] = close[i];   
}
 
Artyom Trishkin:

Я такой код не публиковал здесь - не моё :)

Использую иные конструкции - проще и понятнее.

В OnInit() нужно переносить. Зачем на каждом тике назначать массив индикаторному буферу?

Это не Ваш код. Публиковал кто то из коллег, но кто и где, я не могу вспомнить. Я этот код и имел в виду, когда написал, что в OnInit ничего не надо переносить, а не исходный. Не точно выразился.

А Вы какую конструкцию рекомендовали бы? Эта вроде бы проста предельно.



А, вот и автор фрагмента )))) Опередил меня. Кстати, я тоже такой стиль форматирования использую - с одной открывающейся фигурной скобкой в строке.
 
Andrei Novichkov:
А, вот и автор фрагмента )))) Опередил меня. Кстати, я тоже такой стиль форматирования использую - с одной открывающейся фигурной скобкой в строке.

ага, код шаблона индикатора чем хорош? запускаешь визард по созданию индикатора, выбираешь типы и цвет линий и если нужно добавляешь input 'ы

и все, индикатор готов, потом копируй из OnCalculate() шаблона тело и пиши расчеты,

свой первый индикатор можно написать за 1 минуту, выше код "Hello word I indicator!!!" -  я показал :)

ЗЫ: да кстати, в таком виде индикаторы можно переносить из МТ4 в МТ5, главное индикаторные буферы настроить правильно, в МТ5 там жуть, что с индексацией массивов под буфера.... они просто массивы с обычной массивовской )))) индексацией.... раньше было тяжело к индексации индикаторных буферов привыкнуть в МТ4, теперь наоборот отвыкнуть невозможно и перейти на МТ5  ))))
 
Andrei Novichkov:

Это не Ваш код. Публиковал кто то из коллег, но кто и где, я не могу вспомнить. Я этот код и имел в виду, когда написал, что в OnInit ничего не надо переносить, а не исходный. Не точно выразился.

А Вы какую конструкцию рекомендовали бы? Эта вроде бы проста предельно.



А, вот и автор фрагмента )))) Опередил меня.
//+------------------------------------------------------------------+
//| 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[])
  {
//--- Проверка количества доступных баров (1 - минимально, 4 - оптимально для большинства расчётов. Но всё "по месту"...)
   if(rates_total<4) return 0;
//--- Проверка и расчёт количества просчитываемых баров
   int limit=rates_total-prev_calculated; // 0 - пришел новый тик, новый бар формироваться не начал. 1 - пришел новый тик и начал формироваться новый бар.
   if(limit>1) 
               // если вписать "limit>0", то на нулевом баре будет расчёт только нулевого бара, на каждом новом баре будет полный перерасчёт всей истории
               // если вписать "limit>1", то на нулевом баре будет расчёт только нулевого бара, на открытии нового бара - пересчёт первого и нулевого,
               // при подгрузке истории и на первом запуске - перерасчёт всей истории
     {
      limit=rates_total-1;
      // здесь должна быть инициализация всех используемых буферов индикатора необходимыми значениями (обычно EMPTY_VALUE и 0)
     }
//--- Расчёт индикатора
   for(int i=limit; i>=0 && !IsStopped(); i--)
     {
      // необходимые действия по расчёту индикатора
     }

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
Igor Makanu:

ага, код шаблона индикатора чем хорош? запускаешь визард по созданию индикатора, выбираешь типы и цвет линий и если нужно добавляешь input 'ы

и все, индикатор готов, потом копируй из OnCalculate() шаблона тело и пиши расчеты,

свой первый индикатор можно написать за 1 минуту, выше код "Hello word I indicator!!!" -  я показал :)

ЗЫ: да кстати, в таком виде индикаторы можно переносить из МТ4 в МТ5, главное индикаторные буферы настроить правильно, в МТ5 там жуть, что с индексацией массивов под буфера.... они просто массивы с обычной массивовской )))) индексацией.... раньше было тяжело к индексации индикаторных буферов привыкнуть в МТ4, теперь наоборот отвыкнуть невозможно и перейти на МТ5  ))))

Ничего сложного. Пример кроссплатформенного индикатора (использует класс), но шаблон можно выдернуть - убрать класс и всё лишнее, что ошибки после этого будет выдавать - останется кроссплатформенный шаблон.

Этот индикатор будет одинаково работать на обеих платформах без изменения - лишь компиляция с нужным расширением. Пришлось код разбить на две части - класс и сам индикатор (всё было в одном листинге)

Класс:

//+------------------------------------------------------------------+
//|                                                       TestMA.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/ru/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Класс скользящих средних                                         |
//+------------------------------------------------------------------+
#include <Arrays\ArrayObj.mqh>
class CAvg : public CObject
  {
protected:
   ENUM_TIMEFRAMES      m_timeframe;
   string               m_symbol;
   int                  m_period;
   ENUM_MA_METHOD       m_method;
   ENUM_APPLIED_PRICE   m_price;
   int                  m_rates_total;
   double               m_prev_value;
   //---
   bool                 CheckPosition(const int rates_total,const int period,const int index)   const { return(period>=1 && index<=rates_total-period-1);   }
   double               Open(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)      const;
   double               High(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)      const;
   double               Low(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)       const;
   double               Close(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)     const;
   double               Median(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)    const;
   double               Typical(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)   const;
   double               Weighted(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)  const;
public:
   void                 Timeframe(const ENUM_TIMEFRAMES timeframe)            { this.m_timeframe=timeframe;       }
   void                 Method(const ENUM_MA_METHOD method)                   { this.m_method=method;             }
   void                 AppliedPrice(ENUM_APPLIED_PRICE price)                { this.m_price=price;               }
   void                 Symbol(const string symbol_name)                      { this.m_symbol=symbol_name;        }
   void                 Period(const int period)                              { this.m_period=period;             }
   ENUM_TIMEFRAMES      Timeframe(void)                                 const { return this.m_timeframe;          }
   ENUM_MA_METHOD       Method(void)                                    const { return this.m_method;             }
   ENUM_APPLIED_PRICE   AppliedPrice(void)                              const { return this.m_price;              }
   string               Symbol(void)                                    const { return this.m_symbol;             }
   int                  Period(void)                                    const { return this.m_period;             }
   int                  RatesTotal(void)                                const { return this.m_rates_total;        }
   double               AppliedPrice(const ENUM_APPLIED_PRICE applied_price,const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const;
   double               AppliedPrice(const int index)                   const;
   double               SMA(const int rates_total,const int period,const int index,const double &price[]);
   double               EMA(const int rates_total,const int period,const int index,const double &price[]);
   double               SMMA(const int rates_total,const int period,const int index,const double &price[]);
   double               LWMA(const int rates_total,const int period,const int index,const double &price[]);
   double               GetMA(const int rates_total,const ENUM_MA_METHOD method,const int period,const int index,const double &price[]);
   double               GetMA(const int rates_total,const int index,const double &price[]);
   string               MethodToString(const ENUM_MA_METHOD method)     const { return ::StringSubstr(::EnumToString(method),5);       }
   string               MethodToString(void)                            const { return ::StringSubstr(::EnumToString(this.m_method),5);}
   string               PriceToString(const ENUM_APPLIED_PRICE price)   const { return ::StringSubstr(::EnumToString(price),6);        }
   string               PriceToString(void)                             const { return ::StringSubstr(::EnumToString(this.m_price),6); }
                        CAvg(const int rates_total,const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int period);
                        CAvg(void) : m_prev_value(0){;}
                       ~CAvg(void){;}
  };
//+------------------------------------------------------------------+
//| CAvg Конструктор                                                 |
//+------------------------------------------------------------------+
CAvg::CAvg(const int rates_total,const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int period) : m_prev_value(0)
  {
   this.m_symbol=symbol_name;
   this.m_timeframe=timeframe;
   this.m_period=period;
   this.m_rates_total=rates_total;
  }
//+------------------------------------------------------------------+
//| CAvg возвращает значение MA                                      |
//+------------------------------------------------------------------+
double CAvg::GetMA(const int rates_total,const int index,const double &price[])
  {
   this.m_rates_total=rates_total;
   switch(this.m_method)
     {
      case MODE_EMA  :  return this.EMA(this.m_rates_total,this.m_period,index,price);
      case MODE_SMMA :  return this.SMMA(this.m_rates_total,this.m_period,index,price);
      case MODE_LWMA :  return this.LWMA(this.m_rates_total,this.m_period,index,price);
      //---MODE_SMA
      default        :  return this.SMA(this.m_rates_total,this.m_period,index,price);
     }
  }
//+------------------------------------------------------------------+
//| CAvg возвращает значение MA                                      |
//+------------------------------------------------------------------+
double CAvg::GetMA(const int rates_total,const ENUM_MA_METHOD method,const int period,const int index,const double &price[])
  {
   switch(method)
     {
      case MODE_EMA  :  return this.EMA(rates_total,period,index,price);
      case MODE_SMMA :  return this.SMMA(rates_total,period,index,price);
      case MODE_LWMA :  return this.LWMA(rates_total,period,index,price);
      //---MODE_SMA
      default        :  return this.SMA(rates_total,period,index,price);
     }
  }
//+------------------------------------------------------------------+
//| CAvg Simple Moving Average                                       |
//+------------------------------------------------------------------+
double CAvg::SMA(const int rates_total,const int period,const int index,const double &price[])
  {
//---
   double result=0.0;
//--- check position
   if(!this.CheckPosition(rates_total,period,index))
      return 0;
//--- calculate value
   for(int i=0; i<period; i++)
     result=result+price[index+i];
   result/=period;
//---
   return result;
  }
//+------------------------------------------------------------------+
//| CAvg Exponential Moving Average                                  |
//+------------------------------------------------------------------+
double CAvg::EMA(const int rates_total,const int period,const int index,const double &price[])
  {
//---
   //static double prev_value=0;
   double result=0.0;
//--- check position
   if(!this.CheckPosition(rates_total,period,index))
      return 0;
   double pr=2.0/(period+1.0);
//--- SMA for first data
   if(index==rates_total-period-1 || this.m_prev_value==0)
      this.m_prev_value=result=this.SMA(rates_total,period,index,price);
//--- EMA
   else
     {
      result=this.m_prev_value+pr*(price[index]-this.m_prev_value);
      //--- new bar
      if(index!=0)
         this.m_prev_value=result;
     }
//---
   return result;
  }
//+------------------------------------------------------------------+
//| CAvg Smoothed Moving Average                                     |
//+------------------------------------------------------------------+
double CAvg::SMMA(const int rates_total,const int period,const int index,const double &price[])
  {
//---
   //static double prev_value=0;
   double result=0.0;
//--- check position
   if(!this.CheckPosition(rates_total,period,index))
      return 0;
//--- SMA for first data
   if(index==rates_total-period-1 || this.m_prev_value==0)
      this.m_prev_value=result=this.SMA(rates_total,period,index,price);
//--- SMMA
   else
     {
      result=(this.m_prev_value*(period-1)+price[index])/period;
      //--- new bar
      if(index!=0)
         this.m_prev_value=result;
     }
//---
   return result;
  }
//+------------------------------------------------------------------+
//| CAvg Linear Weighted Moving Average                              |
//+------------------------------------------------------------------+
double CAvg::LWMA(const int rates_total,const int period,const int index,const double &price[])
  {
//---
   double result=0.0,count=0,total=0,k=0;
//--- check position
   if(!this.CheckPosition(rates_total,period,index))
      return 0;
//--- calculate value
   for(int j=index+period-1; j>=index; j--)
     {
      count++;
      k+=count;
      total+=price[j]*count;
     }
   result=total/k;
//---
   return(result);
  }
//+------------------------------------------------------------------+
//| CAvg Возвращает цену по индексу                                  |
//+------------------------------------------------------------------+
double CAvg::AppliedPrice(const int index) const
  {
   switch(this.m_price)
     {
      case PRICE_OPEN      :  return this.Open(this.m_symbol,this.m_timeframe,index);
      case PRICE_HIGH      :  return this.High(this.m_symbol,this.m_timeframe,index);
      case PRICE_LOW       :  return this.Low(this.m_symbol,this.m_timeframe,index);
      case PRICE_CLOSE     :  return this.Close(this.m_symbol,this.m_timeframe,index);
      case PRICE_MEDIAN    :  return this.Median(this.m_symbol,this.m_timeframe,index);
      case PRICE_TYPICAL   :  return this.Typical(this.m_symbol,this.m_timeframe,index);
      //---PRICE_WEIGHTED
      default              :  return this.Weighted(this.m_symbol,this.m_timeframe,index);
     }
  }
//+------------------------------------------------------------------+
//| CAvg Возвращает цену по индексу                                  |
//+------------------------------------------------------------------+
double CAvg::AppliedPrice(const ENUM_APPLIED_PRICE applied_price,const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const
  {
   switch(applied_price)
     {
      case PRICE_OPEN      :  return this.Open(symbol_name,timeframe,index);
      case PRICE_HIGH      :  return this.High(symbol_name,timeframe,index);
      case PRICE_LOW       :  return this.Low(symbol_name,timeframe,index);
      case PRICE_CLOSE     :  return this.Close(symbol_name,timeframe,index);
      case PRICE_MEDIAN    :  return this.Median(symbol_name,timeframe,index);
      case PRICE_TYPICAL   :  return this.Typical(symbol_name,timeframe,index);
      //---PRICE_WEIGHTED
      default              :  return this.Weighted(symbol_name,timeframe,index);
     }
  }
//+------------------------------------------------------------------+
//| CAvg Возвращает цену Open по индексу                             |
//+------------------------------------------------------------------+
double CAvg::Open(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const
  {
   double array[];
   return(::CopyOpen(symbol_name,timeframe,index,1,array)==1 ? array[0] : 0);
  }  
//+------------------------------------------------------------------+
//| CAvg Возвращает цену High по индексу                             |
//+------------------------------------------------------------------+
double CAvg::High(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const
  {
   double array[];
   return(::CopyHigh(symbol_name,timeframe,index,1,array)==1 ? array[0] : 0);
  }  
//+------------------------------------------------------------------+
//| CAvg Возвращает цену Low по индексу                              |
//+------------------------------------------------------------------+
double CAvg::Low(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const
  {
   double array[];
   return(::CopyLow(symbol_name,timeframe,index,1,array)==1 ? array[0] : 0);
  }  
//+------------------------------------------------------------------+
//| CAvg Возвращает цену Close по индексу                            |
//+------------------------------------------------------------------+
double CAvg::Close(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const
  {
   double array[];
   return(::CopyClose(symbol_name,timeframe,index,1,array)==1 ? array[0] : 0);
  }  
//+------------------------------------------------------------------+
//| CAvg Возвращает медианную цену по индексу                        |
//+------------------------------------------------------------------+
double CAvg::Median(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const
  {
   double array[];
   double high=this.High(symbol_name,timeframe,index);
   double low=this.Low(symbol_name,timeframe,index);
   return(high>0 && low>0 ? (high+low)/2.0 : 0);
  }  
//+------------------------------------------------------------------+
//| CAvg Возвращает типичную цену по индексу                         |
//+------------------------------------------------------------------+
double CAvg::Typical(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const
  {
   double array[];
   double high=this.High(symbol_name,timeframe,index);
   double low=this.Low(symbol_name,timeframe,index);
   double close=this.Close(symbol_name,timeframe,index);
   return(high>0 && low>0 && close>0 ? (high+low+close)/3.0 : 0);
  }  
//+------------------------------------------------------------------+
//| CAvg Возвращает взвешенную цену по индексу                       |
//+------------------------------------------------------------------+
double CAvg::Weighted(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const
  {
   double array[];
   double high=this.High(symbol_name,timeframe,index);
   double low=this.Low(symbol_name,timeframe,index);
   double close=this.Close(symbol_name,timeframe,index);
   return(high>0 && low>0 && close>0 ? (high+low+close+close)/4.0 : 0);
  }  
//+------------------------------------------------------------------+
 

Индикатор:

//+------------------------------------------------------------------+
//|                                                       TestMA.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property indicator_chart_window
#ifdef __MQL4__
#property strict
#property indicator_buffers 2
#else 
#property indicator_buffers 3
#property indicator_plots   2
#endif 
//--- plot MAstd
#property indicator_label1  "Calculation MA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  4
//--- plot MAcalc
#property indicator_label2  "Standart MA"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrDarkOrange
#property indicator_style2  STYLE_DOT
#property indicator_width2  2
//--- input parameters
input int      InpPeriod                     =  10;            // Period
input ENUM_MA_METHOD       InpMethod         =  MODE_EMA;      // Method
input ENUM_APPLIED_PRICE   InpAppliedPrice   =  PRICE_CLOSE;   // Applied price  
//--- indicator buffers
double         BufferMAcalc[];
double         BufferMAstd[];
double         BufferPrice[];
//---
int            digits;
int            period_ma;
int            handle_ma;
CAvg           avg();
//--- includes

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
#ifdef __MQL4__
   IndicatorBuffers(3);
#endif 
   period_ma=(InpPeriod<1? 1 : InpPeriod);
   digits=Digits()+1;
//--- indicator buffers mapping
   SetIndexBuffer(0,BufferMAcalc,INDICATOR_DATA);
   SetIndexBuffer(1,BufferMAstd,INDICATOR_DATA);
   SetIndexBuffer(2,BufferPrice,INDICATOR_CALCULATIONS);
//---
   ArraySetAsSeries(BufferMAcalc,true);
   ArraySetAsSeries(BufferMAstd,true);
   ArraySetAsSeries(BufferPrice,true);
//---
#ifdef __MQL5__
   ResetLastError();
   handle_ma=iMA(NULL,PERIOD_CURRENT,period_ma,0,InpMethod,InpAppliedPrice);
   if(handle_ma==INVALID_HANDLE)
     {
      Print("Error creation iMA(",(string)period_ma,"): ",GetLastError());
      return INIT_FAILED;
     }
#endif 
//---
   Comment("\nMA type: ",avg.MethodToString(InpMethod),", price: ",avg.PriceToString(InpAppliedPrice),", period: ",(string)period_ma);
//---
   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[])
  {
//--- Установка массивов буферов как таймсерий
#ifdef __MQL5__
   ArraySetAsSeries(open,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(close,true);
#endif 
//--- Проверка количества доступных баров
   if(rates_total<fmax(period_ma,4)) return 0;
//--- Проверка и расчёт количества просчитываемых баров
   int limit=rates_total-prev_calculated;
   if(limit>1)
     {
      limit=rates_total-1;
      ArrayInitialize(BufferMAcalc,EMPTY_VALUE);
      ArrayInitialize(BufferMAstd,EMPTY_VALUE);
      ArrayInitialize(BufferPrice,0);
     }
//--- Подготовка данных
#ifdef __MQL5__
   int count=(limit>1 ? rates_total : 1),copied=0;
   copied=CopyBuffer(handle_ma,0,0,count,BufferMAstd);
   if(copied!=count) return 0;
#endif 
//--- Расчёт индикатора
   for(int i=limit; i>=0 && !IsStopped(); i--)
     {
      #ifdef __MQL4__ BufferMAstd[i]=iMA(NULL,PERIOD_CURRENT,period_ma,0,InpMethod,InpAppliedPrice,i); #endif 
      BufferPrice[i]=avg.AppliedPrice(InpAppliedPrice,NULL,PERIOD_CURRENT,i);
      BufferMAcalc[i]=avg.GetMA(rates_total,InpMethod,period_ma,i,BufferPrice);
     }

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
Причина обращения: