Toute question des nouveaux arrivants sur MQL4 et MQL5, aide et discussion sur les algorithmes et les codes. - page 670

 
Roman Sharanov:
Comment créer un tableau d'instances de classe ?
J'ai fait ClassName* className[], puis ArrayResize dessus, mais cela ne me donne pas accès aux méthodes

Votre classe, dont vous voulez rassembler les instances dans un tableau, doit être héritée de CObject.

Ensuite, c'est simple : créez une liste (tableau) d'objets CArrayObj, et ajoutez-y vos objets.

 
psyman:

Une recherche sur les mots "modèle d'indicateur" et votre nom ne donne rien, et vous avez déjà écrit ici sur ce volume de Guerre et Paix.

Toute combinaison de mots du post me vient à l'esprit.

Je suis désolé, pour le modèle d'indicateur, je me suis peut-être trompé - le modèle de chalut a été posté.

Disons-le ainsi : créez un modèle d'indicateur dans l'éditeur, ajoutez le nombre requis de variables d'entrée et de tampons à dessiner.

Ensuite, décomposez ce que vous devez faire de cette tâche spécifique.

 
psyman:

Si vous dites que c'est mauvais, dites-moi comment le rendre bon. Déplacer les calculs vers OnInit ?

Fair rebuke )) Ici, une variante du code qui a été publié ici :

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);

Essayez de le faire de cette façon. Vous n'avez pas besoin de déplacer quoi que ce soit à OnInit.

 
Andrei Novichkov:

Fair rebuke )) Ici, une variante du code qui a été publié ici :

Essayez de le faire de cette façon. Vous n'avez pas besoin de déplacer quoi que ce soit à OnInit.

Je n'ai pas publié un tel code ici - ce n'est pas mon truc :)

J'utilise d'autres constructions - c'est plus simple et plus clair.

Dans OnInit(), il devrait être transféré. Pourquoi devez-vous affecter un tableau au tampon de l'indicateur à chaque tick ?

 
Artyom Trishkin:

Je n'ai pas publié ce type de code ici - ce n'est pas mon truc :)

J'utilise d'autres constructions - plus simples et plus claires.

C'est le mien, comment cela pourrait-il être plus simple ? ))) (au moins, j'ai aussi dans mon modèle le commentairelimit = rates_total - 1;//--- Premier appel de l'indicateur ou changement de période ou chargement de données depuis l'historique) et mon style de formatage - une accolade près de for() {

Pour apprendre à écrire votre propre indicateur, prenez le modèle ci-dessus et ajoutez au moins le prix de clôture et obtenez votre premier indicateur, puis apprenez à faire la MAH à partir de ce prix de clôture.

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

Je n'ai pas publié ce type de code ici - ce n'est pas mon truc :)

J'utilise des constructions différentes - plus simples et plus claires.

Rien ne doit être copié dans OnInit(). Pourquoi dois-je affecter un tableau au tampon de l'indicateur à chaque tick ?

Ce n'est pas votre code. Il a été publié par certains de mes collègues, mais je ne me souviens plus qui et où. C'est ce code que je visais lorsque j'ai écrit que rien ne devait être déplacé vers OnInit mais pas le code source. Je n'ai pas été très clair.

Et quelle construction recommanderiez-vous ? Cela semble être très simple.



Ah, voilà l'auteur de la pièce )))). Devant moi. D'ailleurs, j'utilise aussi ce style de formatage - avec un crochet ouvrant par ligne.
 
Andrei Novichkov:
Ah, voici l'auteur de l'extrait )))) Devant moi. À propos, j'utilise également ce style de formatage - avec un crochet ouvrant par ligne.

Vous exécutez l'assistant de création d'un indicateur, sélectionnez les types et la couleur des lignes et ajoutez des entrées, si nécessaire.

et c'est tout, l'indicateur est prêt, alors copiezle corps du modèle OnCalculate() et écrivez les calculs ,

vous pouvez écrire votre premier indicateur en 1 minute, le code "Bonjour mot je indicateur ! - J'ai montré :)

ZS : A propos, les indicateurs peuvent être transférés de MT4 à MT5 sous cette forme, l'essentiel est de paramétrer correctement les tampons des indicateurs, dans MT5 il y a un glissement dans l'indexation des tableaux sous les tampons..... ce sont juste des tableaux avec l'indexation habituelle des tableaux )))) .... il était difficile de s'habituer à l'indexation des tampons d'indicateurs dans MT4, maintenant au contraire il est impossible de s'y habituer et de passer à MT5 )))).
 
Andrei Novichkov:

Ce n'est pas votre code. Il a été publié par un de mes collègues, mais je ne me souviens plus qui et où. C'est ce code que je visais quand je disais que rien ne devait être déplacé vers OnInit mais pas le code source. Je n'ai pas été très clair.

Et quelle construction recommanderiez-vous ? Celui-ci semble être très simple.



Ah, voilà l'auteur de la pièce )))). Devant moi.
//+------------------------------------------------------------------+
//| 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 :

oui, à quoi sert le code du modèle d'indicateur ? lancez l'assistant pour créer un indicateur , choisissez les types et la couleur des lignes et, si nécessaire, ajoutez des entrées

et c'est tout, l'indicateur est prêt, puis copiez le corps du modèle OnCalculate() et écrivez les calculs,

vous pouvez écrire votre premier indicateur en 1 minute, le code ci-dessus est "Bonjour mot I indicateur !!!" J'ai montré :)

PS: au fait, sous cette forme, les indicateurs peuvent être transférés de MT4 à MT5, l'essentiel est de configurer correctement les tampons d'indicateurs, dans MT5, il y a une horreur qu'avec des tableaux d'indexation pour les tampons ... ce ne sont que des tableaux avec le tableau habituel)))) indexation .. .. auparavant, il était difficile de s'habituer à l'indexation des tampons d'indicateurs dans MT4, maintenant au contraire, il est impossible de s'y habituer et de passer à MT5))))

Rien de compliqué. Un exemple d'indicateur multiplateforme (utilise une classe), mais le modèle peut être extrait - supprimez la classe et tout ce qui est superflu et qui entraînera des erreurs par la suite - le modèle multiplateforme restera.

Cet indicateur fonctionnera de la même manière sur les deux plates-formes sans modification - juste une compilation avec l'extension requise. J'ai dû diviser le code en deux parties - la classe et l'indicateur lui-même (tout était dans une seule liste)

Classe:

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

Indicateur :

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