//+------------------------------------------------------------------+
//|                                             ema deviations bands |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_color1  clrPaleVioletRed
#property indicator_color2  clrDeepSkyBlue
#property indicator_color3  clrDimGray
#property indicator_color4  clrBlue
#property indicator_color5  clrRed
#property indicator_style3  STYLE_DOT
#property indicator_width4  2
#property indicator_width5  2

//
//
//
//
//

extern int                Periods         = 14;
extern ENUM_APPLIED_PRICE Price           = PRICE_CLOSE;
extern double             Deviations      = 2.0;
input int                 ArrowCodeUp     = 221;              // Arrow code up
input int                 ArrowCodeDn     = 222;              // Arrow code down
input double              ArrowGapUp      = 0.5;              // Gap for arrow up        
input double              ArrowGapDn      = 0.5;              // Gap for arrow down
input bool                showAllBreakOut = true;             // Show all b/o
input bool                alertsOn        = true;             // Alerts on/off?
input bool                alertsOnCurrent = false;            // Alerts current (still opened) bar on/off?
input bool                alertsMessage   = true;             // Alerts pop-up message on/off?
input bool                alertsSound     = false;            // Alerts sound on/off?
input bool                alertsEmail     = false;            // Alerts email on/off?
input bool                alertsNotify    = false;            // Alerts push notification on/off?

//
//
//
//
//

double buffer1[];
double buffer2[];
double buffer3[],upArr[],dnArr[],trend[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   IndicatorBuffers(6);
   SetIndexBuffer(0,buffer1);
   SetIndexBuffer(1,buffer2);
   SetIndexBuffer(2,buffer3);
   SetIndexBuffer(3,upArr); SetIndexStyle(3,DRAW_ARROW); SetIndexArrow(3,ArrowCodeUp);
   SetIndexBuffer(4,dnArr); SetIndexStyle(4,DRAW_ARROW); SetIndexArrow(4,ArrowCodeDn);
   SetIndexBuffer(5,trend);
return(0);
}
int deinit() { return(0); }
int start()
{
   int counted_bars=IndicatorCounted();
   int i,limit;

   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
           limit=MathMin(Bars-counted_bars,Bars-1);

   //
   //
   //
   //
   //
   
   for(i=limit; i>=0; i--)
   {
      double deviation = iEDev(iMA(NULL,0,1,0,MODE_SMA,Price,i),Periods,i);
            buffer3[i] = iMA(NULL,0,Periods,0,MODE_EMA,Price,i);
            buffer1[i] = buffer3[i]+Deviations*deviation;
            buffer2[i] = buffer3[i]-Deviations*deviation;
            upArr[i] = dnArr[i] = EMPTY_VALUE;
            trend[i] = (i<Bars-1 && !showAllBreakOut) ? trend[i+1] : 0;
            if (Low[i] <buffer2[i]) trend[i] = 1;
            if (High[i]>buffer1[i]) trend[i] =-1;  
            
            if (i<Bars-1 && trend[i]!=trend[i+1])
            {
               if (trend[i] ==  1) upArr[i] = fmin(buffer2[i],Low[i] )-iATR(NULL,0,15,i)*ArrowGapUp;
               if (trend[i] == -1) dnArr[i] = fmax(buffer1[i],High[i])+iATR(NULL,0,15,i)*ArrowGapDn;
            } 
   }  
   if (alertsOn)
   {
      int whichBar = 1; if (alertsOnCurrent) whichBar = 0; 
      if (trend[whichBar] != trend[whichBar+1])
      if (trend[whichBar] == 1)
               doAlert(" up");
         else  doAlert(" down");       
   }  
return(0);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

double edevWork[][2];
double iEDev(double price,double period, int i)
{
   if (ArrayRange(edevWork,0)!=Bars) ArrayResize(edevWork,Bars);
   
   int    r     = Bars-i-1;
   double alpha = 2.0/(1.0+period);
      
      edevWork[r][0] = edevWork[r-1][0]+alpha*(price      -edevWork[r-1][0]);
      edevWork[r][1] = edevWork[r-1][1]+alpha*(price*price-edevWork[r-1][1]);
         
   return(MathSqrt(period*(edevWork[r][1]-edevWork[r][0]*edevWork[r][0])/(period-1.0)));
}

//+------------------------------------------------------------------+
//
//
//
//

void doAlert(string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
      if (previousAlert != doWhat || previousTime != Time[0]) {
          previousAlert  = doWhat;
          previousTime   = Time[0];

          //
          //
          //
          //
          //

          message = timeFrameToString(_Period)+" "+_Symbol+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+" emadeviation bands "+doWhat;
          if (alertsMessage) Alert(message);
          if (alertsEmail)   SendMail(_Symbol+" ema deviation bands ",message);
          if (alertsNotify)  SendNotification(message);
          if (alertsSound)   PlaySound("alert2.wav");
      }
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};
string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}




