//------------------------------------------------------------------
#property copyright "mladen"
#property link      "www,forex-tsd.com"
//------------------------------------------------------------------
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color5  Silver
#property indicator_width1  2
#property indicator_width2  1
#property indicator_width3  2
#property indicator_width4  1
#property indicator_width5  3

//
//
//
//
//

extern int                CCIPeriod       = 50;
extern int                RsxPeriod       = 30;
extern ENUM_APPLIED_PRICE RsxPrice        = PRICE_CLOSE;
extern int                AtrPeriod       = 30;
extern double             OverSold        = -100;
extern double             OverBought      =  100;
extern color              OverSoldColor   = clrLimeGreen; 
extern color              OverBoughtColor = clrOrange; 

//
//
//
//
//

double cci[];
double cciUpa[];
double cciUpb[];
double cciDna[];
double cciDnb[];
double prices[];
double trend[];
double slope[];

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int init()
{
   IndicatorBuffers(8);
      SetIndexBuffer(0,cciUpa); SetIndexStyle(0,DRAW_HISTOGRAM,EMPTY,EMPTY,OverSoldColor);
      SetIndexBuffer(1,cciUpb); SetIndexStyle(1,DRAW_HISTOGRAM,EMPTY,EMPTY,OverSoldColor);
      SetIndexBuffer(2,cciDna); SetIndexStyle(2,DRAW_HISTOGRAM,EMPTY,EMPTY,OverBoughtColor);
      SetIndexBuffer(3,cciDnb); SetIndexStyle(3,DRAW_HISTOGRAM,EMPTY,EMPTY,OverBoughtColor);
      SetIndexBuffer(4,cci);
      SetIndexBuffer(5,prices);
      SetIndexBuffer(6,trend);
      SetIndexBuffer(7,slope);
         SetLevelValue(0,OverBought);
         SetLevelValue(1,OverSold);
         
         //
         //
         //
         //
         //
         
   IndicatorShortName(" CCI of rsx & atr ("+CCIPeriod+","+RsxPeriod+")");
   return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//

double wrkBuffer[][13];
int start()
{
   int i,r,counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
         int limit = MathMin(Bars-counted_bars,Bars-1);
         if (ArrayRange(wrkBuffer,0) != Bars) ArrayResize(wrkBuffer,Bars);

   //
   //
   //
   //
   //

      double Kg = (3.0)/(2.0+RsxPeriod); 
      double Hg = 1.0-Kg;
      for(i=limit, r=Bars-i-1; i>=0; i--, r++)
      {
         wrkBuffer[r][12] = iMA(NULL,0,1,0,MODE_SMA,RsxPrice,i);
         if (i==(Bars-1)) { for (int c=0; c<12; c++) wrkBuffer[r][c] = 0; continue; }  

         //
         //
         //
         //
         //
      
         double mom = wrkBuffer[r][12]-wrkBuffer[r-1][12];
         double moa = MathAbs(mom);
         for (int k=0; k<3; k++)
         {
            int kk = k*2;
               wrkBuffer[r][kk+0] = Kg*mom                + Hg*wrkBuffer[r-1][kk+0];
               wrkBuffer[r][kk+1] = Kg*wrkBuffer[r][kk+0] + Hg*wrkBuffer[r-1][kk+1]; mom = 1.5*wrkBuffer[r][kk+0] - 0.5 * wrkBuffer[r][kk+1];
               wrkBuffer[r][kk+6] = Kg*moa                + Hg*wrkBuffer[r-1][kk+6];
               wrkBuffer[r][kk+7] = Kg*wrkBuffer[r][kk+6] + Hg*wrkBuffer[r-1][kk+7]; moa = 1.5*wrkBuffer[r][kk+6] - 0.5 * wrkBuffer[r][kk+7];
         }
         if (moa != 0)
              prices[i] = iATR(NULL,0,AtrPeriod,i)*(MathMax(MathMin((mom/moa+1.0)*50.0,100.00),0.00)-50); 
         else prices[i] = 0;
         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;
         
            //
            //
            //
            //
            //
         
            cciUpa[i] = EMPTY_VALUE;
            cciUpb[i] = EMPTY_VALUE;
            cciDna[i] = EMPTY_VALUE;
            cciDnb[i] = EMPTY_VALUE;
            trend[i]  = trend[i+1];
            slope[i]  = slope[i+1];
               if (cci[i]>OverBought)                    trend[i] =  1;
               if (cci[i]<OverSold)                      trend[i] = -1;
               if (cci[i]>OverSold && cci[i]<OverBought) trend[i] =  0;
               if (cci[i]>cci[i+1])                      slope[i] =  1;
               if (cci[i]<cci[i+1])                      slope[i] = -1;
               if (trend[i]==1)
                  if (slope[i]==1)
                        cciUpa[i] = cci[i];
                  else  cciUpb[i] = cci[i];
               if (trend[i]==-1)
                  if (slope[i]==-1)
                        cciDna[i] = cci[i];
                  else  cciDnb[i] = cci[i];
      }
      return(0);
}

//+------------------------------------------------------------------
//|                                                                 
//+------------------------------------------------------------------
//
//
//
//
//

double vPrices[][1];
double iVel(double price, double length,int i, int instanceNo=0)
{
   static int vel_length = -1;
          if (vel_length != length)
          {
              vel_length = length;
                  static double coeff0; coeff0 = length + 1;
                  static double coeff1; coeff1 = coeff0 * (    coeff0+1.0)/2.0;
                  static double coeff2; coeff2 = coeff1 * (2.0*coeff0+1.0)/3.0;
                  static double coeff3; coeff3 = coeff1 * coeff1 * coeff1 - coeff2 * coeff2; 
          }
          if (ArrayRange(vPrices,0)!=Bars) ArrayResize(vPrices,Bars); i = Bars-i-1;
          vPrices[i][instanceNo] = price;
      
   //
   //
   //
   //
   //

   double suma = 0.0;
   double sumb = 0.0;
      for(int l=0; l<=length && (i-l)>=0; l++)
      {
         suma += vPrices[i-l][instanceNo] * (coeff0-l);
         sumb += vPrices[i-l][instanceNo] * (coeff0-l) * (coeff0-l);
      }
   double tvel = (sumb*coeff1 - suma*coeff2) / (coeff3*Point); 
   return(tvel);
}