//+------------------------------------------------------------------+
//|                                                   CCI simple.mq4 |
//+------------------------------------------------------------------+
#property copyright "mrtools"
#property link      "willtools@aol.com"

#property indicator_separate_window
#property indicator_buffers    4
#property indicator_color1     clrDimGray
#property indicator_color2     clrDimGray
#property indicator_color3     clrDimGray
#property indicator_color4     clrLimeGreen
#property indicator_style2     STYLE_DOT
#property indicator_level1     200
#property indicator_level2     -200
#property indicator_level3     0
#property indicator_levelcolor clrMediumOrchid
#property strict

//
enum enTimeFrames
{
   tf_cu  = PERIOD_CURRENT, // Current time frame
   tf_m1  = PERIOD_M1,      // 1 minute
   tf_m5  = PERIOD_M5,      // 5 minutes
   tf_m15 = PERIOD_M15,     // 15 minutes
   tf_m30 = PERIOD_M30,     // 30 minutes
   tf_h1  = PERIOD_H1,      // 1 hour
   tf_h4  = PERIOD_H4,      // 4 hours
   tf_d1  = PERIOD_D1,      // Daily
   tf_w1  = PERIOD_W1,      // Weekly
   tf_mn1 = PERIOD_MN1,     // Monthly
   tf_n1  = -1,             // First higher time frame
   tf_n2  = -2,             // Second higher time frame
   tf_n3  = -3              // Third higher time frame
};
//
//
//
//
extern enTimeFrames   TimeFrame          = tf_cu; // Time frame
extern int                CciPeriod      = 50;             // Cci period
extern ENUM_APPLIED_PRICE CciPrice       = PRICE_TYPICAL;  // Cci price
extern int                BandsPeriod    = 20;             // Bands period
extern double             BandsDeviation = 2;              // Bands deviations
extern bool            Interpolate        = true;       // Interpolate in multi time frame mode?

double bandUp[],bandMi[],bandDn[],cci[],prices[],count[];

string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,CciPeriod,CciPrice,BandsPeriod,BandsDeviation,_buff,_ind)

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
    for (int i=0; i<indicator_buffers; i++) SetIndexStyle(i,DRAW_LINE);
    IndicatorBuffers(6);
    SetIndexBuffer(0,bandUp);
    SetIndexBuffer(1,bandMi);
    SetIndexBuffer(2,bandDn);
    SetIndexBuffer(3,cci);
    SetIndexBuffer(4,prices);
    SetIndexBuffer(5,count);
    
     indicatorFileName = WindowExpertName();
   TimeFrame         = (enTimeFrames)timeFrameValue(TimeFrame);   
    
    IndicatorShortName("CCI bands("+(string)CciPeriod+"");
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);count[0]=limit;
   //
   //
    if (TimeFrame!=_Period)
            {
               limit = (int)fmax(limit,fmin(Bars-1,_mtfCall(5,0)*TimeFrame/_Period));
             
               for (i=limit;i>=0 && !_StopFlag; i--)
               {
                  int y = iBarShift(NULL,TimeFrame,Time[i]);
                     bandUp[i]        = _mtfCall(0,y);
                     bandMi[i] = _mtfCall(1,y);
                     bandDn[i]  = _mtfCall(2,y);;
   	               cci[i]  = _mtfCall(3,y);;
                     prices[i]      = _mtfCall(4,y);
                     
                     //
                     //
                     //
                     //
                     //
                     
                     if (!Interpolate || (i>0 && y==iBarShift(NULL,TimeFrame,Time[i-1]))) continue;
                        #define _interpolate(buff) buff[i+k] = buff[i]+(buff[i+n]-buff[i])*k/n
                        int n,k; datetime time = iTime(NULL,TimeFrame,y);
                           for(n = 1; (i+n)<Bars && Time[i+n] >= time; n++) continue;	
                           for(k = 1; k<n && (i+n)<Bars && (i+k)<Bars; k++) 
                           {
                              _interpolate(bandUp);
                              _interpolate(bandMi);
                              _interpolate(bandDn);
                              _interpolate(cci);
                           }                           
               }
               
   return(0);
   }
   //
   //
   //

      for(i=limit; i>=0; i--)
      {
         prices[i]  = iMA(NULL,0,1,0,MODE_SMA,CciPrice,i);
         double avg = 0; for(int k=0; k<CciPeriod && (i+k)<Bars; k++) avg +=         prices[i+k];      avg /= CciPeriod;
         double dev = 0; for(int k=0; k<CciPeriod && (i+k)<Bars; k++) dev += MathAbs(prices[i+k]-avg); dev /= CciPeriod;
         if (dev!=0)
               cci[i] = (prices[i]-avg)/(0.015*dev);
         else  cci[i] = 0;
      }
      for(i=limit; i>=0; i--)
      {
         bandUp[i] = iBandsOnArray(cci,0,BandsPeriod,BandsDeviation,0,MODE_UPPER,i);
         bandDn[i] = iBandsOnArray(cci,0,BandsPeriod,BandsDeviation,0,MODE_LOWER,i);
         bandMi[i] = iBandsOnArray(cci,0,BandsPeriod,BandsDeviation,0,MODE_MAIN ,i);
      }
return(0);
}

  string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}

int timeFrameValue(int _tf)
{
   int add  = (_tf>=0) ? 0 : MathAbs(_tf);
   if (add != 0) _tf = _Period;
   int size = ArraySize(iTfTable); 
      int i =0; for (;i<size; i++) if (iTfTable[i]==_tf) break;
                                   if (i==size) return(_Period);
                                                return(iTfTable[(int)MathMin(i+add,size-1)]);
}
 