//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "www,forex-tsd.com"
#property link      "www,forex-tsd.com"

#property indicator_separate_window
#property indicator_buffers    3
#property indicator_color1     clrLimeGreen
#property indicator_color2     clrOrange
#property indicator_color3     clrOrange
#property indicator_levelcolor clrMediumOrchid
#property strict

//
//
//
//
//

#import "dynamicZone.dll"
   double dzBuyP(double& sourceArray[],double probabiltyValue, int lookBack, int bars, int i, double precision);
   double dzSellP(double& sourceArray[],double probabiltyValue, int lookBack, int bars, int i, double precision);
#import

//
//
//
//
//

extern double             Length            = 20;   // Bband Ma Length
extern ENUM_MA_METHOD     MaMethod          = 0;    // Bband Ma Method
extern ENUM_APPLIED_PRICE Price             = 0;    // Bband Price
extern double             Deviation         = 0.5;  // Bband standard deviation
extern int                DzLookBackBars    = 35;   // Dynamic zone lookback
extern double             DzBuyProbability  = 0.1;  // Dynamic zone buy probability
extern double             DzSellProbability = 0.1;  // Dynamic zone sell probability
extern double             T3Period          = 32;   // T3 smoothing period
extern double             T3Hot             = 0.7;  // T3 smoothing hot
extern bool               T3Original        = false;// T3 original Tim Tillson calculation?
extern int                LinesWidth        = 3;    // Bband line width 
extern double             UpperLevel        = 2.0;  // Upper Level
extern double             LowerLevel        = -2.0; // Lower Level

//
//
//
//
//

double pdz[];
double pdzda[];
double pdzdb[];
double bbLine[];
double up[];
double dn[];
double slope[];

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

int init()
{
   IndicatorBuffers(7);
      SetIndexBuffer(0,pdz);   SetIndexStyle(0,DRAW_LINE,EMPTY,LinesWidth);
      SetIndexBuffer(1,pdzda); SetIndexStyle(1,DRAW_LINE,EMPTY,LinesWidth);
      SetIndexBuffer(2,pdzdb); SetIndexStyle(2,DRAW_LINE,EMPTY,LinesWidth);
      SetIndexBuffer(3,bbLine);  
      SetIndexBuffer(4,up);
      SetIndexBuffer(5,dn);
      SetIndexBuffer(6,slope);
      SetLevelValue(0,0.0);
      SetLevelValue(1,UpperLevel);
      SetLevelValue(2,LowerLevel);
   IndicatorShortName("Percent DZ("+(string)Length+","+(string)Deviation+")");
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);

   //
   //
   //
   //
   //
   
   if (slope[limit]==-1) CleanPoint(limit,pdzda,pdzdb);   
   for(i=limit; i>=0; i--)
   { 
      bbLine[i] = ibbLine(Length,MaMethod,Price,Deviation,i);
      up[i] = dzSellP(bbLine,DzSellProbability,DzLookBackBars,Bars,i,0.00001);
      dn[i] = dzBuyP (bbLine,DzBuyProbability ,DzLookBackBars,Bars,i,0.00001);
         if (up[i]-dn[i]>0.0)
              pdz[i] = iT3((Close[i] - dn[i])/(up[i] - dn[i]),T3Period,T3Hot,T3Original,i);
         else pdz[i] = iT3(0,                                 T3Period,T3Hot,T3Original,i); 
              pdzda[i] = EMPTY_VALUE;
              pdzdb[i] = EMPTY_VALUE;
              if (i<Bars-1)
              {
                 slope[i] = slope[i+1];
                    if (pdz[i]>pdz[i+1]) slope[i] =  1;
                    if (pdz[i]<pdz[i+1]) slope[i] = -1;
              }
              if (slope[i]==-1) PlotPoint(i,pdzda,pdzdb,pdz);
      }
return(0);
}

//
//
//
//
//

double workBb[][3];
#define smin   0
#define smax   1
#define trend  2

double ibbLine(double _Length, double _MaMethod, double _Price, double _Deviation, int i)
{
      if (ArrayRange(workBb,0)!=Bars) ArrayResize(workBb,Bars);
      int r = Bars-i-1; 
      
      double StdDev = iStdDev(NULL,0,(int)Length,0,MODE_SMA,Price,i);
      double ma     = iMA(NULL,0,(int)Length,0,MaMethod,Price,i);
      double result = 0; 
      
      //
      //
      //
      //
      //
      
      if (r==0)
      {
         workBb[r][smax]  = ma + (StdDev*Deviation);
         workBb[r][smin]  = ma - (StdDev*Deviation);
         workBb[r][trend] = 0;
         return(Close[i]);
      }
      
      //
      //
      //
      //
      //
      
      workBb[r][smax]  = ma + (StdDev*Deviation);
      workBb[r][smin]  = ma - (StdDev*Deviation);
      workBb[r][trend] = workBb[r-1][trend];
      if (Close[i]>workBb[r-1][smax]) workBb[r][trend] = 1; 
	   if (Close[i]<workBb[r-1][smin]) workBb[r][trend] =-1; 
	   if (workBb[r][trend] ==  1) 
	   { 
	     if (workBb[r][smin] < workBb[r-1][smin]) workBb[r][smin]=workBb[r-1][smin]; result = workBb[r][smin]; 
	   }
      if (workBb[r][trend] == -1) 
      { 
        if (workBb[r][smax] > workBb[r-1][smax]) workBb[r][smax]=workBb[r-1][smax]; result = workBb[r][smax]; 
      }
      
return(result);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

#define t3Instances 1
double workT3[][t3Instances*6];
double workT3Coeffs[][6];
#define _tperiod 0
#define _c1      1
#define _c2      2
#define _c3      3
#define _c4      4
#define _alpha   5

//
//
//
//
//

double iT3(double price, double period, double hot, bool original, int i, int tinstanceNo=0)
{
   if (ArrayRange(workT3,0) != Bars)                 ArrayResize(workT3,Bars);
   if (ArrayRange(workT3Coeffs,0) < (tinstanceNo+1)) ArrayResize(workT3Coeffs,tinstanceNo+1);

   if (workT3Coeffs[tinstanceNo][_tperiod] != period)
   {
     workT3Coeffs[tinstanceNo][_tperiod] = period;
        double a = hot;
            workT3Coeffs[tinstanceNo][_c1] = -a*a*a;
            workT3Coeffs[tinstanceNo][_c2] = 3*a*a+3*a*a*a;
            workT3Coeffs[tinstanceNo][_c3] = -6*a*a-3*a-3*a*a*a;
            workT3Coeffs[tinstanceNo][_c4] = 1+3*a+a*a*a+3*a*a;
            if (original)
                 workT3Coeffs[tinstanceNo][_alpha] = 2.0/(1.0 + period);
            else workT3Coeffs[tinstanceNo][_alpha] = 2.0/(2.0 + (period-1.0)/2.0);
   }
   
   //
   //
   //
   //
   //
   
   int instanceNo = tinstanceNo*6;
   int r = Bars-i-1;
   if (r == 0)
      {
         workT3[r][0+instanceNo] = price;
         workT3[r][1+instanceNo] = price;
         workT3[r][2+instanceNo] = price;
         workT3[r][3+instanceNo] = price;
         workT3[r][4+instanceNo] = price;
         workT3[r][5+instanceNo] = price;
      }
   else
      {
         workT3[r][0+instanceNo] = workT3[r-1][0+instanceNo]+workT3Coeffs[tinstanceNo][_alpha]*(price                  -workT3[r-1][0+instanceNo]);
         workT3[r][1+instanceNo] = workT3[r-1][1+instanceNo]+workT3Coeffs[tinstanceNo][_alpha]*(workT3[r][0+instanceNo]-workT3[r-1][1+instanceNo]);
         workT3[r][2+instanceNo] = workT3[r-1][2+instanceNo]+workT3Coeffs[tinstanceNo][_alpha]*(workT3[r][1+instanceNo]-workT3[r-1][2+instanceNo]);
         workT3[r][3+instanceNo] = workT3[r-1][3+instanceNo]+workT3Coeffs[tinstanceNo][_alpha]*(workT3[r][2+instanceNo]-workT3[r-1][3+instanceNo]);
         workT3[r][4+instanceNo] = workT3[r-1][4+instanceNo]+workT3Coeffs[tinstanceNo][_alpha]*(workT3[r][3+instanceNo]-workT3[r-1][4+instanceNo]);
         workT3[r][5+instanceNo] = workT3[r-1][5+instanceNo]+workT3Coeffs[tinstanceNo][_alpha]*(workT3[r][4+instanceNo]-workT3[r-1][5+instanceNo]);
      }

   //
   //
   //
   //
   //
   
   return(workT3Coeffs[tinstanceNo][_c1]*workT3[r][5+instanceNo] + 
          workT3Coeffs[tinstanceNo][_c2]*workT3[r][4+instanceNo] + 
          workT3Coeffs[tinstanceNo][_c3]*workT3[r][3+instanceNo] + 
          workT3Coeffs[tinstanceNo][_c4]*workT3[r][2+instanceNo]);
}

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

void CleanPoint(int i,double& first[],double& second[])
{
   if (i>=Bars-3) return;
   if ((second[i]  != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE))
        second[i+1] = EMPTY_VALUE;
   else
      if ((first[i] != EMPTY_VALUE) && (first[i+1] != EMPTY_VALUE) && (first[i+2] == EMPTY_VALUE))
          first[i+1] = EMPTY_VALUE;
}

void PlotPoint(int i,double& first[],double& second[],double& from[])
{
   if (i>=Bars-2) return;
   if (first[i+1] == EMPTY_VALUE)
      if (first[i+2] == EMPTY_VALUE) 
            { first[i]  = from[i];  first[i+1]  = from[i+1]; second[i] = EMPTY_VALUE; }
      else  { second[i] =  from[i]; second[i+1] = from[i+1]; first[i]  = EMPTY_VALUE; }
   else     { first[i]  = from[i];                           second[i] = EMPTY_VALUE; }
}


