//+------------------------------------------------------------------+
//|                                             EMA_Adaptive_v22.mq4 |
//|                                                        GrayMan77 |
//|                                                                  |
//|  EMA с адаптивным периодом.                                      |
//|                                                                  |
//|  Период рассчитывается от MaxPeriod в сторону MinPeriod,         |
//|  пока Standard Deviation (СКО) не станет меньше порогового уровня|
//|                                   LevelStdDevPoint (в пунктах).  |
//|                                                                  |
//|  v2 - добвлено сглаживание.                                      |
//|  v22 - изменен алгоритм перебора периода                         |
//|                         (для сокращения времени вычисления);     |
//|      - добавлен вывод мин. и макс. периода на истории;           |
//+------------------------------------------------------------------+
#property copyright "GrayMan77"
#property link      ""

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red

extern int MinPeriod=2;
extern int MaxPeriod=48;
extern int LevelStdDevPoint=8;
extern int Smooth=2;
extern bool ShowComment=False;

double LevelStdDev;
int MaxPeriodHistory,MinPeriodHistory;

//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   IndicatorBuffers(2);
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,ExtMapBuffer1);
   SetIndexBuffer(1,ExtMapBuffer2);
   
   LevelStdDev=LevelStdDevPoint*Point;
   MinPeriodHistory=MaxPeriod;
   MaxPeriodHistory=MinPeriod;
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   if(ShowComment) Comment("");
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int counted_bars=IndicatorCounted();
   int limit,i;
   double ValueStdDev;
   int MinPer,MaxPer,Per;
      
//----
   //---- проверка на возможные ошибки
   if(counted_bars<0) return(-1);
   
   //---- последний посчитанный бар будет пересчитан
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;
   if(limit>Bars-MaxPeriod-1) limit=Bars-MaxPeriod-1;
   
   //---- основной цикл
   for(i=limit;i>=0;i--)
     {
     // Вычисление периода средней
     MaxPer=MaxPeriod+1;
     MinPer=MinPeriod;
     while(MaxPer-MinPer>1)
       {
       Per=MinPer+(MaxPer-MinPer)/2.;
       ValueStdDev=iStdDev(Symbol(),Period(),Per,0,MODE_EMA,PRICE_WEIGHTED,i);
       if(ValueStdDev>=LevelStdDev) MaxPer=Per;
         else MinPer=Per;
       //if(i<5) Print(" i=",i,"        MaxPer=",MaxPer,"      MinPer=",MinPer);
       }
     
     // Вычисление адаптивной EMA
     ExtMapBuffer2[i]=iMA(Symbol(),Period(),MinPer,0,MODE_EMA,PRICE_CLOSE,i);
     //if(i<50) Print("i=",i,"    MA_Period=",MinPer);
     
     // Изменение значений макс. и мин. периода на истории (для комментария)
     if(i<Bars-MaxPeriod)
       {
       if(MinPer>MaxPeriodHistory) MaxPeriodHistory=MinPer;
       if(MinPer<MinPeriodHistory) MinPeriodHistory=MinPer;
       }
     }
   
   // Если разрешен вывод комментария - вывести
   if(ShowComment) Comment("\n Минимальный период EMA_Adaptive на истории: ",MinPeriodHistory,"\n Максимальный период EMA_Adaptive на истории: ",MaxPeriodHistory);
   
   //---- Сглаживание адаптивной EMA
     for(i=limit;i>=0;i--)
       {
       ExtMapBuffer1[i]=iMAOnArray(ExtMapBuffer2,0,Smooth,0,MODE_EMA,i);
       }
   
//----
   return(0);
  }
//+------------------------------------------------------------------+