MQL4 및 MQL5에 대한 초보자 질문, 알고리즘 및 코드에 대한 도움말 및 토론 - 페이지 670

 
Roman Sharanov :
클래스 인스턴스의 배열을 만드는 방법은 무엇입니까?
ClassName* className[] , ArrayResize 를 만들었지만 유효하지 않은 포인터 액세스 방법 에 대한 액세스 권한을 부여하지 않습니다.

배열에서 인스턴스를 수집하려는 클래스는 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() {

글쎄, 주제에 따르면, 자신의 지표를 작성하는 방법을 배우기 위해 위에 표시된 템플릿을 사용하고 최소한 종가를 추가하고 첫 번째 지표를 얻은 다음 이 종가에서 Mashka를 만드는 방법을 배웁니다.

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

나는 여기에 그러한 코드를 게시하지 않았습니다 - 내 것이 아닙니다 :)

다른 구성을 사용합니다. 더 간단하고 명확합니다.

OnInit()에서는 전송이 필요합니다. 각 틱 에서 표시기 버퍼에 배열을 할당하는 이유는 무엇입니까?

이것은 귀하의 코드가 아닙니다. 내 동료 중 일부가 그것을 출판했지만 누가 어디에서 기억할 수 없습니다. 원래 OnInit이 아닌 OnInit으로 전송할 필요가 없다고 썼을 때 이 코드를 염두에 두었습니다. 정확히 표현되지 않습니다.

어떤 디자인을 추천하시겠습니까? 이것은 매우 간단한 것 같습니다.



그리고 여기 조각의 저자가 있습니다)))) 나보다 앞서 있습니다. 그건 그렇고, 나는 또한 한 줄에 하나의 여는 중괄호와 함께 이 서식 스타일을 사용합니다.
 
Andrei Novichkov :
그리고 여기 조각의 저자가 있습니다.)))) 나보다 앞서 있습니다. 그건 그렇고, 나는 또한 한 줄에 하나의 여는 중괄호와 함께 이 서식 스타일을 사용합니다.

예, 표시기 템플릿 코드는 무엇에 적합합니까? 마법사를 실행하여 표시기를 만들고 선의 유형과 색상을 선택하고 필요한 경우 입력을 추가하십시오.

그게 다야, 표시기가 준비되었습니다. 그런 다음 OnCalculate() 템플릿에서 본문을 복사하고 계산을 작성합니다.

1분 안에 첫 번째 지표를 작성할 수 있습니다. 위의 코드는 "Hello word I indicator!!!"입니다. 나는 보여 주었다 :)

추신: 그건 그렇고, 이 형식에서 표시기는 MT4에서 MT5로 전송될 수 있습니다. 가장 중요한 것은 표시기 버퍼를 올바르게 설정하는 것입니다. MT5에는 버퍼용 인덱싱 배열이 있다는 공포가 있습니다.... 그것들은 단지 배열일 뿐입니다 일반적인 배열)))) 인덱싱 .. .. 이전에는 MT4에서 표시기 버퍼의 인덱싱에 익숙해지기 어려웠지만 이제는 반대로 익숙해지고 MT5))))로 전환하는 것이 불가능합니다.
 
Andrei Novichkov :

이것은 귀하의 코드가 아닙니다. 내 동료 중 일부가 그것을 출판했지만 누가 어디에서 기억할 수 없습니다. 원래 OnInit이 아닌 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분 안에 첫 번째 지표를 작성할 수 있습니다. 위의 코드는 "Hello word I indicator!!!"입니다. 나는 보여 주었다 :)

추신: 그건 그렇고, 이 형식에서 표시기는 MT4에서 MT5로 전송될 수 있습니다. 가장 중요한 것은 표시기 버퍼를 올바르게 설정하는 것입니다. MT5에는 버퍼용 인덱싱 배열이 있다는 공포가 있습니다.... 그것들은 단지 배열일 뿐입니다 일반적인 배열)))) 인덱싱 .. .. 이전에는 MT4에서 표시기 버퍼의 인덱싱에 익숙해지기 어려웠지만 이제는 반대로 익숙해지고 MT5))))로 전환하는 것이 불가능합니다.

복잡하지 않습니다. 크로스 플랫폼 표시기(클래스 사용)의 예이지만 템플릿을 빼낼 수 있습니다. 클래스와 그 이후에 오류를 발생시키는 불필요한 모든 것을 제거합니다. 크로스 플랫폼 템플릿은 그대로 유지됩니다.

이 표시기는 수정 없이 두 플랫폼 모두에서 동일하게 작동합니다. 필요한 확장으로 컴파일만 하면 됩니다. 코드를 클래스와 표시기 자체(모든 것이 하나의 목록에 있음)의 두 부분으로 분할해야 했습니다.

수업:

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