//+------------------------------------------------------------------+
//|                                                          CCI.mq4 |
//|                      Copyright © 2004, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2004, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net/"

/*--------------------------------------------------------------------
_v2:  Adds individually colorable level lines.  These three lines
terminate at the current candle, leaving open space to the right in 
the indicator window to accomodate maybe other indicator.  The High
and the Low level lines can be assigned values.  Typical is the value
of 100 (makes 100 and -100).  Default here is the value 150.
                                                       - Traderathome
--------------------------------------------------------------------*/
                                                       
#property indicator_separate_window
#property indicator_buffers   4
#property indicator_color1    Green
#property indicator_color2    C'185,185,0'
#property indicator_color3    FireBrick
#property indicator_color4    LightSeaGreen

#property indicator_width1    1
#property indicator_width2    1
#property indicator_width3    1
#property indicator_width4    1

#property indicator_style1    STYLE_DOT
#property indicator_style2    STYLE_DOT
#property indicator_style3    STYLE_DOT
#property indicator_style4    STYLE_SOLID

//---- input parameters
extern bool   Indicator_On? = true;
extern int CCIPeriod        = 63;
extern int CCIHighLowLevels = 150;

//---- buffers
double Highline[];
double Zeroline[];
double Lowline[];
double CCIBuffer[];
double RelBuffer[];
double DevBuffer[];
double MovBuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {

//---- 3 additional buffers are used for counting.

   IndicatorBuffers(7);
     
   SetIndexBuffer(4, RelBuffer);
   SetIndexBuffer(5, DevBuffer);
   SetIndexBuffer(6, MovBuffer);
   
//---- Level lines
   SetIndexStyle(0,DRAW_LINE); 
   SetIndexBuffer(0,Highline);
   
   SetIndexStyle(1,DRAW_LINE); 
   SetIndexBuffer(1,Zeroline);
      
   SetIndexStyle(2,DRAW_LINE); 
   SetIndexBuffer(2,Lowline);
   
//---- CCI indicator line
   SetIndexStyle(3, DRAW_LINE);
   SetIndexBuffer(3, CCIBuffer);
     
//----
   if(CCIPeriod <= 0){CCIPeriod = 63;}
   SetIndexDrawBegin(0, CCIPeriod);
  
//---- name for DataWindow and indicator subwindow labels 
   string short_name="CCI_v2  ("+CCIPeriod+")   ";
   if (Indicator_On? == false)short_name=("CCI_v2  ("+CCIPeriod+")   Indicator is off   ");
   IndicatorShortName(short_name);           
   SetIndexLabel(0, NULL);
   SetIndexLabel(1, NULL); 
   SetIndexLabel(2, NULL);
   SetIndexLabel(3, NULL);
   SetIndexLabel(4, NULL);
   SetIndexLabel(5, NULL);
   SetIndexLabel(6, NULL); 
     
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Commodity Channel Index                                          |
//+------------------------------------------------------------------+
int start()
  {
   if (Indicator_On? == false) {return(0);}
   int    i, k, counted_bars = IndicatorCounted();
   double price, sum, mul; 
   if(CCIPeriod <= 1)
       return(0);
   if(Bars <= CCIPeriod) 
       return(0);
//---- initial zero
   if(counted_bars < 1)
     {
       for(i = 1; i <= CCIPeriod; i++) 
           CCIBuffer[Bars-i] = 0.0;
       for(i = 1; i <= CCIPeriod; i++) 
           DevBuffer[Bars-i] = 0.0;
       for(i = 1; i <= CCIPeriod; i++) 
           MovBuffer[Bars-i] =0.0;
     }
//---- last counted bar will be recounted
   int limit = Bars - counted_bars;
   if(counted_bars > 0) 
       limit++;
       
//---- level lines 
    for(i=0; i<limit; i++)     
       Highline[i] = CCIHighLowLevels; 
    for(i=0; i<limit; i++)
       Zeroline[i] = 0;   
    for(i=0; i<limit; i++)   
       Lowline[i]  = -CCIHighLowLevels;
             
//---- moving average
   for(i = 0; i < limit; i++)
       MovBuffer[i] = iMA(NULL, 0, CCIPeriod, 0, MODE_SMA, PRICE_TYPICAL, i);
//---- standard deviations
   i = Bars - CCIPeriod + 1;
   if(counted_bars > CCIPeriod - 1) 
       i = Bars - counted_bars - 1;
   mul = 0.015 / CCIPeriod;
   while(i >= 0)
     {
       sum = 0.0;
       k = i + CCIPeriod - 1;
       while(k >= i)
        {
          price =(High[k] + Low[k] + Close[k]) / 3;
          sum += MathAbs(price - MovBuffer[i]);
          k--;
        }
       DevBuffer[i] = sum*mul;
       i--;
     }
   i = Bars - CCIPeriod + 1;
   if(counted_bars > CCIPeriod - 1) 
       i = Bars - counted_bars - 1;
   while(i >= 0)
     {
       price = (High[i] + Low[i] + Close[i]) / 3;
       RelBuffer[i] = price - MovBuffer[i];
       i--;
     }
//---- cci counting
   i = Bars - CCIPeriod + 1;
   if(counted_bars > CCIPeriod - 1) 
       i = Bars - counted_bars - 1;
   while(i >= 0)
     {
       if(DevBuffer[i] == 0.0) 
           CCIBuffer[i] = 0.0;
       else 
           CCIBuffer[i] = RelBuffer[i] / DevBuffer[i];
       i--;
     }
//----
   return(0);
  }
//+------------------------------------------------------------------+