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

#property indicator_separate_window
#property indicator_buffers    6
#property indicator_color1     DeepSkyBlue
#property indicator_color2     LimeGreen
#property indicator_color3     LimeGreen
#property indicator_color4     Red
#property indicator_color5     Red
#property indicator_color6     DimGray
#property indicator_style3     STYLE_DOT
#property indicator_style5     STYLE_DOT
#property indicator_style6     STYLE_DOT
#property indicator_width1     2
#property indicator_levelcolor DarkSlateGray

//
//
//
//
//

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

//
//
//
//
//

extern int    CCIPrice                = PRICE_TYPICAL;
extern double ShortLimit              = 10;
extern double LongLimit               = 50;
extern int    CfbDepth                = 8;
extern int    CfbSmooth               = 20;
extern int    CfbNormLength           = 50;
extern int    DzLookBackBars          = 70;
extern double DzStartBuyProbability1  = 0.025;
extern double DzStartBuyProbability2  = 0.075;
extern double DzStartSellProbability1 = 0.025;
extern double DzStartSellProbability2 = 0.075;

//
//
//
//
//

double cci[];
double prices[];
double cfb[];
double bl1[];
double bl2[];
double sl1[];
double sl2[];
double zl1[];

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

int init()
{
   IndicatorBuffers(8);
      SetIndexBuffer(0,cci);
      SetIndexBuffer(1,bl1);
      SetIndexBuffer(2,bl2);
      SetIndexBuffer(3,sl1);
      SetIndexBuffer(4,sl2);
      SetIndexBuffer(5,zl1);
      SetIndexBuffer(6,prices);
      SetIndexBuffer(7,cfb);  
   IndicatorShortName("Dynamic zone cfb adaptive CCI ("+DoubleToStr(ShortLimit,2)+","+DoubleToStr(LongLimit,2)+")");
   return(0);
}
int deinit() {   return(0); }

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

int start()
{
   int counted_bars=IndicatorCounted();
   int i,k,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--)
      {
         prices[i]  = iMA(NULL,0,1,0,MODE_SMA,CCIPrice,i);
         cfb[i]     = iCfb(CCIPrice,CfbDepth,CfbSmooth,i);
    
         //
         //
         //
         //
         //
         
         double max = cfb[ArrayMaximum(cfb,CfbNormLength,i)];
         double min = cfb[ArrayMinimum(cfb,CfbNormLength,i)];
         double denominator = max-min;
            if (denominator> 0)
                  double ratio = (cfb[i]-min)/denominator;
            else         ratio = 0.5;  
            double CCIPeriod = MathMax(ShortLimit+ratio*(LongLimit-ShortLimit),3); 
            
            //
            //
            //
            //
            //
            
            double avg = 0; for(k=0; k<CCIPeriod; k++) avg +=         prices[i+k];      avg /= CCIPeriod;
            double dev = 0; for(k=0; k<CCIPeriod; k++) dev += MathAbs(prices[i+k]-avg); dev /= CCIPeriod;
               if (dev!=0)
                     cci[i] = (prices[i]-avg)/(0.015*dev);
               else  cci[i] = 0;
               
               if (DzStartBuyProbability1  > 0) bl1[i] = dzBuyP (cci,DzStartBuyProbability1, DzLookBackBars,Bars,i);
               if (DzStartBuyProbability2  > 0) bl2[i] = dzBuyP (cci,DzStartBuyProbability2, DzLookBackBars,Bars,i);
               if (DzStartSellProbability1 > 0) sl1[i] = dzSellP(cci,DzStartSellProbability1,DzLookBackBars,Bars,i);
               if (DzStartSellProbability2 > 0) sl2[i] = dzSellP(cci,DzStartSellProbability2,DzLookBackBars,Bars,i);
                                                zl1[i] = dzSellP(cci,0.5                    ,DzLookBackBars,Bars,i);
              
      }
return(0);
}  

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

int    Depths[] = {2,3,4,6,8,12,16,24,32,48,64,96,128,192};
double workCfb[][28];

//
//
//
//
//

double iCfb(double price, int depth, int smooth, int r)
{
   if (ArrayRange(workCfb,0) != Bars) ArrayResize(workCfb,Bars);
   int i = Bars-r-1;
         
   //
   //
   //
   //
   //

   double suma     = 0;
   double sumb     = 0;
   double cfb      = 0;
   double evenCoef = 1;
   double oddCoef  = 1;
   double avg      = 0;
         
      if (i>=smooth)
         for (int k=depth-1; k>=0; k--)
         {
            workCfb[i][k]    = iCfbFunc(price,i,Depths[k],k);
            workCfb[i][k+14] = workCfb[i-1][k+14] + (workCfb[i][k]-workCfb[i-smooth][k])/smooth;

                  if ((k%2)==0)
                        { avg = oddCoef  * workCfb[i][k+14]; oddCoef  = oddCoef  * (1 - avg); }
                  else  { avg = evenCoef * workCfb[i][k+14]; evenCoef = evenCoef * (1 - avg); }
               
               suma += avg*avg*Depths[k];
               sumb += avg;
         }
      else for (k=depth-1; k>=0; k--) { workCfb[i][k] = 0; workCfb[i][k+14] = 0; }            

   //
   //
   //
   //
   //

   if (sumb != 0) cfb = suma/sumb;
   return(cfb);
}

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

double  workCfbFunc[][70];
#define _prices 0
#define _roc    1
#define _value1 2
#define _value2 3
#define _value3 4

//
//
//
//

double iCfbFunc(double price, int r, int depth, int k)
{
   k *= 5;
      if (ArrayRange(workCfbFunc,0) != Bars) ArrayResize(workCfbFunc,Bars);
      if (r<=(depth+1))
      {
         workCfbFunc[r][k+_prices] = 0;
         workCfbFunc[r][k+_roc]    = 0;
         workCfbFunc[r][k+_value1] = 0;
         workCfbFunc[r][k+_value2] = 0;
         workCfbFunc[r][k+_value3] = 0;
         return(0);
      }         
      workCfbFunc[r][k+_prices] = price; 

   //
   //
   //
   //
   //

      workCfbFunc[r][k+_roc]    = MathAbs(workCfbFunc[r][k+_prices] - workCfbFunc[r-1][k+_prices]);
      workCfbFunc[r][k+_value1] = workCfbFunc[r-1][k+_value1] - workCfbFunc[r-depth][k+_roc] + workCfbFunc[r][k+_roc];
      workCfbFunc[r][k+_value2] = workCfbFunc[r-1][k+_value2] - workCfbFunc[r-1][k+_value1] + workCfbFunc[r][k+_roc]*depth;
      workCfbFunc[r][k+_value3] = workCfbFunc[r-1][k+_value3] - workCfbFunc[r-1-depth][k+_prices] + workCfbFunc[r-1][k+_prices];
   
      double dividend = MathAbs(depth*workCfbFunc[r][k+_prices]-workCfbFunc[r][k+_value3]);

      //
      //
      //
      //
      //
         
   if (workCfbFunc[r][k+_value2] != 0)
         return( dividend / workCfbFunc[r][k+_value2]);
   else  return(0.00);            
}
    
   
   