//+------------------------------------------------------------------+
//|                                                   Envelope95.mq4 |
//|                                                           Kirill |
//|                                          StockProgrammer@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Kirill"
#property link      "StockProgrammer@mail.ru"
//---- indicator settings
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Blue
#property indicator_color2 Red
//---- indicator parameters
extern int MA_Period = 55;
extern int MA_Shift = 0;
extern int MA_Method = 0;
extern int MA_Price = 0;
//---- statistic parameters
extern string NOTE = "Statistical Parameters";
extern int N = 100;  
extern double fract = 0.95;
double deviation = 0.0;
//---- indicator buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
//----
int ExtCountedBars=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   int    draw_begin;
   string short_name;
//---- drawing settings
   SetIndexStyle(0,DRAW_LINE);
   SetIndexStyle(1,DRAW_LINE);
   SetIndexShift(0,0);
   SetIndexShift(1,0);
   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
   if(MA_Period<2) MA_Period=14;
   draw_begin=MA_Period-1;
//---- indicator short name
   IndicatorShortName("Env("+MA_Period+")");
   SetIndexLabel(0,"Env("+MA_Period+")Upper");
   SetIndexLabel(1,"Env("+MA_Period+")Lower");
   SetIndexDrawBegin(0,draw_begin);
   SetIndexDrawBegin(1,draw_begin);
//---- indicator buffers mapping
   SetIndexBuffer(0,ExtMapBuffer1);
   SetIndexBuffer(1,ExtMapBuffer2);



//---- initialization done
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int limit;
   
//---- deviation
   count();   
   
   if(Bars<=MA_Period) return(0);
   ExtCountedBars=IndicatorCounted();
//---- check for possible errors
   if (ExtCountedBars<0) return(-1);
//---- last counted bar will be recounted
   if (ExtCountedBars>0) ExtCountedBars--;
   limit=Bars-ExtCountedBars;
//---- EnvelopesM counted in the buffers
   for(int i=0; i<limit; i++)
     { 
      ExtMapBuffer1[i] = (1+deviation/100) * iMA(NULL, 0, MA_Period, MA_Shift, MA_Method, MA_Price, i);
      ExtMapBuffer2[i] = (1-deviation/100) * iMA(NULL, 0, MA_Period, MA_Shift, MA_Method, MA_Price, i);
      Comment("Envelopes95indicator width: ", MathRound((ExtMapBuffer1[i]-ExtMapBuffer2[i])/Point), " points");
     }
//---- done
   deviation = 0;
//---- check Alert
   CheckAlert();
   return(0);
  }
//+------------------------------------------------------------------+

void CheckAlert()
{
   static bool flag = false;
   string PerStr;
   switch(Period())
   {
      case  1: PerStr = "M1"; break;
      case  5: PerStr = "M5"; break;
      case  15: PerStr = "M15"; break;
      case  30: PerStr = "M30"; break;
      case  60: PerStr = "H1"; break;
      case  240: PerStr = "H4"; break;
      case  1440: PerStr = "D1"; break;
      case  10080: PerStr = "W1"; break;
      case  43200: PerStr = "MN1"; break;
      default : PerStr = "Unknown Period"; break;
   }
   
  //Alert(flag, " ", Close[0], " ", ExtMapBuffer1[0], " ", ExtMapBuffer2[0]); 
   
   if(Close[0] >= ExtMapBuffer1[0] || Close[0] <= ExtMapBuffer2[0])
   {
      if(!flag)
         Alert("Envelopes95 was crossed outwards: ", Symbol(),  " ", PerStr);
      flag = 1;
   }
   else
   {
      if(flag)
         Alert("Envelopes95 was crossed inwards: ", Symbol(),  " ", PerStr);
      flag = 0;
   }
}

int count()
{
//раздвигаем envelopes
   double part, K=0, N_ = N, lower, upper;
   int i;
   
   while(1)
   {
      deviation += 0.05;   
      for(i=1; i<=N; i++)
      {
         lower = iEnvelopes(Symbol(), 0, MA_Period, MA_Method, MA_Shift, MA_Price, deviation, MODE_LOWER, i);
         upper = iEnvelopes(Symbol(), 0, MA_Period, MA_Method, MA_Shift, MA_Price, deviation, MODE_UPPER, i);
         if(Open[i] <  upper
            && Close[i] < upper
               && Open[i] > lower
                  && Close[i] > lower)
                     K++;      
      }
      part = K / N_;
      if(part >= fract)
         break;
      else
         K = 0;   
   }
   
   return(0);
}