#property copyright "www.forex-tsd.com"
#property link      "www.forex-tsd.com"


#property indicator_separate_window
#property indicator_buffers    6
#property indicator_minimum    -100
#property indicator_maximum    100
#property indicator_color1     clrRed
#property indicator_color2     clrRed
#property indicator_color3     clrLime
#property indicator_color4     clrLime
#property indicator_color5     clrYellow
#property indicator_color6     clrAqua
#property indicator_width1     2
#property indicator_width3     2
#property indicator_width5     2
#property indicator_width6     2
#property indicator_levelcolor clrGold

//
//
//
//
//

extern double WprPeriod        = 4;// 15 
extern double SigMaPeriod      = 5;
extern int    Ma_Mode          = MODE_LWMA;
extern double levelOs          = -40.0;
extern double levelOb          = 40;
extern bool   HistogramOnSlope = true;

//
//
//
//
//

double wpr[];
double wprma[];
double Upa[];
double Upb[];
double Dna[];
double Dnb[];
double trend[];
double slope[];

//
//
//
//
//

int init()
{

   IndicatorBuffers(8);
   SetIndexBuffer(0,Dna); SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,Dnb); SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(2,Upa); SetIndexStyle(2,DRAW_HISTOGRAM);
   SetIndexBuffer(3,Upb); SetIndexStyle(3,DRAW_HISTOGRAM);
   SetIndexBuffer(4,wpr);
   SetIndexBuffer(5,wprma);
   SetIndexBuffer(6,trend);
   SetIndexBuffer(7,slope);
   
   SetLevelValue(0,0);
   SetLevelValue(1,levelOs);
   SetLevelValue(2,levelOb);
   
   IndicatorShortName( "Zerolag ema wpr histo ("+DoubleToStr(WprPeriod,2)+","+DoubleToStr(SigMaPeriod,2)+")");   
return(0);
}

//
//
//
//
//

int deinit(){ return(0); }
  
//+------------------------------------------------------------------+
//| Williams? Percent Range                                          |
//+------------------------------------------------------------------+
//
//

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 hi   = High[Highest(NULL,0,MODE_HIGH,WprPeriod,i)];
       double lo   =  Low[Lowest(NULL,  0,MODE_LOW,WprPeriod,i)];
       if (hi!=lo)      
            wpr[i] = iZlema(50+(-100)*(hi - Close[i]) / (hi - lo),WprPeriod,i);
       else wpr[i] = iZlema(0,                                    WprPeriod,i);
            Dna[i] = EMPTY_VALUE;
            Dnb[i] = EMPTY_VALUE;
            Upa[i] = EMPTY_VALUE;
            Upb[i] = EMPTY_VALUE;
            trend[i] = trend[i+1];
            slope[i] = slope[i+1];
               if (wpr[i] > 0)        trend[i] =  1;
               if (wpr[i] < 0)        trend[i] = -1;
               if (wpr[i] > wpr[i+1]) slope[i] =  1;
               if (wpr[i] < wpr[i+1]) slope[i] = -1; 
               
               if (HistogramOnSlope)
               {
                  if (trend[i]== 1 && slope[i] == 1) Upa[i] = wpr[i];
                  if (trend[i]== 1 && slope[i] ==-1) Upb[i] = wpr[i];
                  if (trend[i]==-1 && slope[i] ==-1) Dna[i] = wpr[i];
                  if (trend[i]==-1 && slope[i] == 1) Dnb[i] = wpr[i];
               }
               else
               {                  
                  if (trend[i]== 1) Upa[i] = wpr[i];
                  if (trend[i]==-1) Dna[i] = wpr[i];
               }
               
               
              
    }
    for (i=limit; i>=0; i--) wprma[i] = iMAOnArray(wpr,Bars,SigMaPeriod,0,Ma_Mode,i);
return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double workZl[][2];
#define _price 0
#define _zlema 1

double iZlema(double price, double length, int r, int instanceNo=0)
{
   if (ArrayRange(workZl,0)!=Bars) ArrayResize(workZl,Bars); r = Bars-r-1; instanceNo *= 2;

   //
   //
   //
   //
   //

   double alpha = 2.0/(1.0+length); 
   int    per   = (length-1.0)/2.0; 

   workZl[r][_price+instanceNo] = price;
   if (r<per)
          workZl[r][_zlema+instanceNo] = price;
   else   workZl[r][_zlema+instanceNo] = workZl[r-1][_zlema+instanceNo]+alpha*(2.0*price-workZl[r-per][_price+instanceNo]-workZl[r-1][_zlema+instanceNo]);
   return(workZl[r][_zlema+instanceNo]);
}

