MQL4、MQL5に関する初心者からの質問、アルゴリズムやコードに関するヘルプ、ディスカッションなど。 - ページ 670

 
Roman Sharanov:
クラスインスタンスの配列を作成する方法は?
ClassName* className[] を作り、それにArrayResizeを かけたが、メソッドに アクセス できない。

インスタンスを配列に集めたいクラスは、CObjectを継承している必要があります。

そして、オブジェクトのリスト(配列)CArrayObjを作成し、そこにオブジェクトを追加していくだけというシンプルなものです。

 
psyman:

インジケーターテンプレートという言葉とあなたの名前で検索しても何も出てきませんし、その戦争と平和の巻についてはすでにここに書かれていますね。

投稿の中から、どんな言葉の組み合わせでもいいので、思い浮かべてみてください。

えーと、インジケーターのテンプレートの件ですが、もしかしたらごっちゃになっていたかもしれませんね~、トロールのテンプレートが掲載されていました。

エディタでインジケータ・テンプレートを作成し、必要な数の入力変数と描画するバッファを追加する、という風にしましょう。

次に、具体的なタスクからやるべきことを分解します。

 
psyman:

悪いというなら、どうすれば良くなるのか教えてほしい。OnInitに計算を移動させる?

Fair rebuke )) ここで、公開されたコードの変形版です。

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:

Fair rebuke )) ここで、公開されたコードの変形版です。

このようにしてみてください。OnInitには何も動かす必要はありません。

私はこのようなコードをここで公開していません。)

私は他の構文を使っています。その方がシンプルでわかりやすいからです。

OnInit()で転送する必要があります。なぜ、各ティックでインジケーターバッファに配列を割り当てる 必要があるのでしょうか?

 
Artyom Trishkin:

私はこのようなコードをここで公開していません。)

私は、よりシンプルでわかりやすい他の構文を使っています。

私のものなんだから、これ以上シンプルにできるわけがない。)))(少なくとも、私はまた、私のテンプレートにコメントを持っているLimit = rates_total - 1;//---インディケータの 最初の呼び出し またはタイムフレームの変更または履歴からデータのロード)と書式の私のスタイル - for(){の 近くに1つの中括弧。

自分でインジケータを書くには、上記のテンプレートに少なくとも終値を追加して最初のインジケータを取得し、この終値からMAHを作成することを学びます。

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

私はこのようなコードをここで公開していません。)

よりシンプルに、よりクリアにと、構図を使い分けています。

OnInit()には何もコピーする必要はありません。なぜ、各ティックでインジケータバッファに配列を割り当てる 必要があるのでしょうか?

あなたのコードではありません。私の同僚が出版したものだが、誰がどこで出版したかは思い出せない。何もOnInitに移動させるべきではないと書いたのはこのコードのことで、ソースコードのことではありません。よくわからないままでした。

また、どのような構造がおすすめでしょうか?これはとてもシンプルなことのように思います。



あ、この作品の作者がいる ))))先行する。ちなみに、私もこのスタイルで、1行に1つ開きの中括弧を付けて書式設定しています。
 
Andrei Novichkov:
あ、スニペットの作者はここです )))先行する。ちなみに、私もこのスタイルで、1行に1つ開きの中括弧を付けて整形しています。

インジケーターの作成 ウィザードを実行し、線の種類と色を選択し、必要に応じて入力を追加します。

で、以上でインジケータの準備は完了です。あとはテンプレートの OnCalculate() からボディをコピーして、計算を書き 込んでください。

1分で最初のインジケータを書くことができます、コード "Hello word I indicator!- 示しました :)

ZS: ちなみに、この形でMT4からMT5へインジケータを移行することができます。主なポイントは、インジケータのバッファを正しく設定することで、MT5ではバッファの下のアレイをインデックスするクリープがあります...。は,通常の配列 )))) のインデックスを持つ単なる配列です.MT4ではインジケータバッファのインデックスに慣れるのが大変でしたが、今は逆に慣れてしまってMT5に乗り換えるのは無理です ))))
 
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 :

ええ、インジケーターテンプレートコードは何に適していますか?ウィザードを実行してインジケーターを作成し、線の種類と色を選択し、必要に応じて入力を追加します。

これで、インジケーターの準備が整いました。次に、 OnCalculate()テンプレートから本文をコピーして、計算を記述します。

1分で最初のインジケーターを書くことができます。上のコードは「HellowordIインジケーター!!!」です。私が見せた:)

PS:ちなみに、この形式では、インジケーターをMT4からMT5に転送できます。主なことは、インジケーターバッファーを正しく設定することです。MT5では、バッファーのインデックス配列を使用すると、単なる配列であるという恐怖があります。通常の配列では))))インデックス付け.. ..以前はMT4のインジケーターバッファーのインデックス付けに慣れるのは困難でしたが、今では逆にそれに慣れてMT5に切り替えることは不可能です))))

複雑なことは何もありません。クロスプラットフォームインジケーターの例(クラスを使用)ですが、テンプレートを引き出すことができます-クラスとその後エラーを発生させる余分なものをすべて削除します-クロスプラットフォームテンプレートは残ります。

このインジケーターは、変更なしで両方のプラットフォームで同じように機能します。必要な拡張子を付けてコンパイルするだけです。コードを2つの部分に分割する必要がありました-クラスとインジケーター自体(すべてが1つのリストに含まれていました)

クラス:

 //+------------------------------------------------------------------+
//|                                                       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);
  }
//+------------------------------------------------------------------+