//+------------------------------------------------------------------+
//|                                       asymmetric ema bands 1.mq4 |
//|                                                                  |
//| forex-tsd elite section only                                     |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_separate_window
#property indicator_buffers  4
#property indicator_color1   clrMediumOrchid  //PaleVioletRed
#property indicator_color2   clrCornflowerBlue  //DeepSkyBlue
#property indicator_color3   clrRed  //DimGray
#property indicator_color4   clrLime  //PaleVioletRed
#property indicator_style3   STYLE_DOT
#property indicator_width4   2

//
//
//
//
//

extern int                 bandsPeriod     = 12;
extern ENUM_APPLIED_PRICE  bandsPrice      = PRICE_CLOSE;
extern double              bandsDeviations = 1.618;

//
//
//
//
//

double zlBuffer[];
double prBuffer[];
double maBuffer[];
double upBuffer[];
double dnBuffer[];
double wuBuffer[];
double wdBuffer[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   IndicatorBuffers(7);
      SetIndexBuffer(0,upBuffer);  SetIndexStyle(0,DRAW_LINE);  SetIndexDrawBegin(0,bandsPeriod);
      SetIndexBuffer(1,dnBuffer);  SetIndexStyle(1,DRAW_LINE);  SetIndexDrawBegin(1,bandsPeriod);
      SetIndexBuffer(2,zlBuffer);  SetIndexStyle(2,DRAW_LINE);  SetIndexDrawBegin(2,bandsPeriod);
      SetIndexBuffer(3,prBuffer);  SetIndexStyle(3,DRAW_LINE);  SetIndexDrawBegin(3,bandsPeriod);
      SetIndexBuffer(4,maBuffer);
      SetIndexBuffer(5,wuBuffer);
      SetIndexBuffer(6,wdBuffer);
   IndicatorShortName("Asymetric EMA Deviation Oscillator ["+(string)bandsPeriod+"*"+DoubleToStr(bandsDeviations,2)+"]"); 
   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]); }
         
         double range = bandsDeviations*(wuBuffer[i]+wdBuffer[i]);
         
            zlBuffer[i] = 2.0*(bandsDeviations*wdBuffer[i])/range-1.0;
            prBuffer[i] = 2.0*(bandsDeviations*wdBuffer[i]+price-maBuffer[i])/range-1.0;
            upBuffer[i] =   1;
            dnBuffer[i] =  -1;
   }
   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)));
}