//+------------------------------------------------------------------+
//|                              dynamic zone williams percent range |
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1  DeepSkyBlue
#property indicator_color2  LimeGreen
#property indicator_color3  Red
#property indicator_width1  2
#property indicator_minimum -100
#property indicator_maximum 0

//
//
//
//
//

extern int    WprLength              = 14;
extern int    WprSmooth              =  3;
extern int    WprSmoothMode          = MODE_SMA;
extern int    DzLookBackBars         = 70;
extern double DzStartBuyProbability  = 0.20;
extern double DzStartSellProbability = 0.20;

//
//
//
//
//

double wps[];
double wpr[];
double bli[];
double sli[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   IndicatorBuffers(4);
   SetIndexBuffer(0,wps);
   SetIndexBuffer(1,bli);
   SetIndexBuffer(2,sli);
   SetIndexBuffer(3,wpr);

   //
   //
   //
   //
   //
   
   WprLength = MathMax(WprLength ,1);
   IndicatorShortName ("Dynamic zone WPR ("+WprLength+","+WprSmooth+","+DzLookBackBars+","+DoubleToStr(DzStartBuyProbability,3)+","+DoubleToStr(DzStartSellProbability,3)+")");
   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--) wpr[i] = iWPR(NULL,0,WprLength,i);
   for(i=limit; i >= 0; i--)
   {
      wps[i] = iMAOnArray(wpr,0,WprSmooth,0,WprSmoothMode,i);
      bli[i] = dzBuy (i, wps, DzStartBuyProbability,  DzLookBackBars);
      sli[i] = dzSell(i, wps, DzStartSellProbability, DzLookBackBars);
   }
   return(0);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

double dzBuy(int i, double& array[], double initValue, int lookBackBars)
{
   double left  = -10000;
   double right =  10000;
   
   if ((Bars-i)<lookBackBars) return(EMPTY_VALUE);
   
   //
   //
   //
   //
   //

   double eps      = 0.001;
   double yval     = (left+right)/2.0;
	double delta    = yval-left;
	int    maxSteps = 0;
	
		while (delta>0.005 && maxSteps<50)
		{
			maxSteps++;
   	      double count = 0;
			   for (int k=0; k<lookBackBars;k++) if (array[i+k]<yval) count++;
	
				double prob = count/lookBackBars;
               if (prob>(initValue+eps))
               {
                  right = yval;
                  yval  = (yval+left)/2.0;
               }                  
               if (prob<(initValue-eps))
               {
                  left = yval;
                  yval = (yval+right)/2.0;
               }
               if (prob<(initValue+eps) && prob>(initValue-eps))
               {
                  right = yval;
                  yval  = (yval+left)/2.0;
               }
               delta=yval-left;
      }               
      return(yval);   
}

//
//
//
//
//

double dzSell(int i, double& array[], double initValue, int lookBackBars)
{
   double left  = -10000;
   double right =  10000;
   
   if ((Bars-i)<lookBackBars) return(EMPTY_VALUE);
   
   //
   //
   //
   //
   //

   double eps      = 0.001;
   double yval     = (left+right)/2.0;
	double delta    = yval-left;
	int    maxSteps = 0;
	
		while (delta>0.005 && maxSteps<50)
		{
			maxSteps++;
   	      double count = 0;
			   for (int k=0; k<lookBackBars;k++) if (array[i+k]>yval) count++;
	
				double prob = count/lookBackBars;
               if (prob>(initValue+eps))
               {
                  left = yval;
                  yval = (yval+right)/2.0;
               }                  
               if (prob<(initValue-eps))
               {
                  right = yval;
                  yval  = (yval+left)/2.0;
               }
               if (prob<(initValue+eps) && prob>(initValue-eps))
               {
                  left = yval;
                  yval = (yval+right)/2.0;
               }
               delta=yval-left;
      }               
      return(yval);   
}