//+------------------------------------------------------------------+
//|                                         asymmetric ema bands.mq4 |
//|                                                                  |
//| forex-tsd elite section only                                     |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_chart_window
#property indicator_buffers  3
#property indicator_color1   DimGray
#property indicator_color2   PaleVioletRed
#property indicator_color3   DeepSkyBlue
#property indicator_style1   STYLE_DOT

//
//
//
//
//

extern int    bandsPeriod     = 14;
extern int    bandsPrice      = PRICE_CLOSE;
extern double bandsDeviations = 2;

//
//
//
//
//

double maBuffer[];
double upBuffer[];
double dnBuffer[];
double wuBuffer[];
double wdBuffer[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   for (int i=0; i<indicator_buffers; i++) SetIndexStyle(i,DRAW_LINE);
   IndicatorBuffers(5);
      SetIndexBuffer(0,maBuffer); SetIndexDrawBegin(0,bandsPeriod);
      SetIndexBuffer(1,upBuffer); SetIndexDrawBegin(1,bandsPeriod);
      SetIndexBuffer(2,dnBuffer); SetIndexDrawBegin(2,bandsPeriod);
      SetIndexBuffer(3,wuBuffer);
      SetIndexBuffer(4,wdBuffer);
   return(0);
}
int deinit() { return(0); }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int start()
{
   double alpha = 2.0 / (1.0 + bandsPeriod);
   double coeff = (bandsPeriod-1.0)/bandsPeriod;
   int i,limit,counted_bars=IndicatorCounted();

      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 price = iMA(NULL,0,1          ,0,MODE_SMA,bandsPrice,i);
      maBuffer[i]  = iMA(NULL,0,bandsPeriod,0,MODE_EMA,bandsPrice,i);
         
      //
      //
      //
      //
      //

         double diff = price-maBuffer[i];
         double edev = iEDev(price,bandsPeriod,i);
         if (maBuffer[i]  ==0) continue;
         if (maBuffer[i+1]==0)
         {
            upBuffer[i] = maBuffer[i];
            dnBuffer[i] = maBuffer[i];
            if (diff>=0)
                  { wuBuffer[i] = edev; wdBuffer[i] = 0; }
            else  { wdBuffer[i] = edev; wuBuffer[i] = 0; }                  
            continue;
         }
      
         //
         //
         //
         //
         //
         
         if(diff>=0)
              { wuBuffer[i] = edev; wdBuffer[i] = wdBuffer[i+1]+alpha*(wdBuffer[i+1]*coeff-wdBuffer[i+1]); }
         else { wdBuffer[i] = edev; wuBuffer[i] = wuBuffer[i+1]+alpha*(wuBuffer[i+1]*coeff-wuBuffer[i+1]); }
         upBuffer[i] = maBuffer[i] + bandsDeviations*wuBuffer[i];
         dnBuffer[i] = maBuffer[i] - bandsDeviations*wdBuffer[i];
   }
   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]-period*edevWork[r][0]*edevWork[r][0])/(period-1.0)));
}