
//+------------------------------------------------------------------
//| %r 
//+------------------------------------------------------------------
//
//

#property copyright "www,forex-station.com"
#property link      "www,forex-station.com"

#property indicator_separate_window
#property indicator_buffers    2
#property indicator_color1     clrCornflowerBlue
#property indicator_color2     clrRed
#property indicator_style2     STYLE_DOT
#property indicator_levelstyle STYLE_DOT
#property indicator_levelcolor clrGold
#property strict

//
//
//

input int       WprPeriod              = 35;                 // Wpr period
enum  enMaTypes
      {        
         ma_sma,                                             // Simple moving average
         ma_ema,                                             // Exponential moving average
         ma_smma,                                            // Smoothed MA
         ma_lwma,                                            // Linear weighted MA
      };
input enMaTypes        MaMethod         = ma_smma;           // Signal moving average type
input int              Signal           = 21;                // Wpr signal MA period
input int              levelOs          = -90;               // Oversold level
input int              levelOb          = -10;               // Overbought level
input int              LineWidth        = 3;                 // Main line width

double wpr[],sig[];

//+------------------------------------------------------------------
//|                                                                  
//+------------------------------------------------------------------

int OnInit()
{
    SetIndexBuffer(0, wpr,INDICATOR_DATA); SetIndexStyle(0,DRAW_LINE,EMPTY,LineWidth);
    SetIndexBuffer(1, sig,INDICATOR_DATA); SetIndexStyle(1,DRAW_LINE);
    
    SetLevelValue(0,-50);
    SetLevelValue(1,levelOs);
    SetLevelValue(2,levelOb);
    
    IndicatorSetString(INDICATOR_SHORTNAME," Wpr ("+(string)WprPeriod+")");
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)  { }

//
//
//

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   int i=rates_total-prev_calculated+1; if (i>=rates_total) i=rates_total-1; 
   
   //
   //
   //
   	
   for (; i>=0 && !_StopFlag; i--)
   {
       double hi = high[ArrayMaximum(high,WprPeriod,i)];
       double lo =  low[ArrayMinimum(low, WprPeriod,i)];
        wpr[i]   = (hi!=lo) ? -100*(hi-close[i])/(hi-lo) : 0;
        sig[i]   = iCustomMa(MaMethod,wpr[i],Signal,i,rates_total);     
   } 
return(rates_total);
}

//------------------------------------------------------------------
//                                                                  
//------------------------------------------------------------------

string getAverageName(int method)
{
      switch(method)
      {
         case ma_ema:    return("EMA");
         case ma_lwma:   return("LWMA");
         case ma_sma:    return("SMA");
         case ma_smma:   return("SMMA");
      }
return("");      
}

//------------------------------------------------------------------
//                                                                  
//------------------------------------------------------------------

#define _maInstances 1
#define _maWorkBufferx1 1*_maInstances
#define _maWorkBufferx2 2*_maInstances
#define _maWorkBufferx3 3*_maInstances

double iCustomMa(int mode, double price, double length, int r, int bars, int instanceNo=0)
{
   r = bars-r-1;
   switch (mode)
   {
      case ma_sma   : return(iSma(price,(int)ceil(length),r,bars,instanceNo));
      case ma_ema   : return(iEma(price,length,r,bars,instanceNo));
      case ma_smma  : return(iSmma(price,(int)ceil(length),r,bars,instanceNo));
      case ma_lwma  : return(iLwma(price,(int)ceil(length),r,bars,instanceNo));
      default       : return(price);
   }
}

//
//
//
//
//

double workSma[][_maWorkBufferx1];
double iSma(double price, int period, int r, int _bars, int instanceNo=0)
{
   if (ArrayRange(workSma,0)!= _bars) ArrayResize(workSma,_bars);

   workSma[r][instanceNo+0] = price;
   double avg = price; int k=1;  for(; k<period && (r-k)>=0; k++) avg += workSma[r-k][instanceNo+0];  
   return(avg/(double)k);
}

//
//
//
//
//

double workEma[][_maWorkBufferx1];
double iEma(double price, double period, int r, int _bars, int instanceNo=0)
{
   if (ArrayRange(workEma,0)!= _bars) ArrayResize(workEma,_bars);

   workEma[r][instanceNo] = price;
   if (r>0 && period>1)
          workEma[r][instanceNo] = workEma[r-1][instanceNo]+(2.0/(1.0+period))*(price-workEma[r-1][instanceNo]);
   return(workEma[r][instanceNo]);
}

//
//
//
//
//

double workSmma[][_maWorkBufferx1];
double iSmma(double price, double period, int r, int _bars, int instanceNo=0)
{
   if (ArrayRange(workSmma,0)!= _bars) ArrayResize(workSmma,_bars);

   workSmma[r][instanceNo] = price;
   if (r>1 && period>1)
          workSmma[r][instanceNo] = workSmma[r-1][instanceNo]+(price-workSmma[r-1][instanceNo])/period;
   return(workSmma[r][instanceNo]);
}

//
//
//
//
//

double workLwma[][_maWorkBufferx1];
double iLwma(double price, double period, int r, int _bars, int instanceNo=0)
{
   if (ArrayRange(workLwma,0)!= _bars) ArrayResize(workLwma,_bars);
   
   workLwma[r][instanceNo] = price; if (period<=1) return(price);
      double sumw = period;
      double sum  = period*price;

      for(int k=1; k<period && (r-k)>=0; k++)
      {
         double weight = period-k;
                sumw  += weight;
                sum   += weight*workLwma[r-k][instanceNo];  
      }             
      return(sum/sumw);
}





