Author: Copyright � 2009, Maxim Kovalevskiy
CCIAverage

This technical tool is designed to provide traders with a clearer picture of market momentum by combining two distinct mathematical layers: the Commodity Channel Index (CCI) and a Moving Average.

Rather than looking at raw price action alone, this script filters out market "noise" to help identify trends and potential overbought or oversold conditions. Here is a breakdown of how the logic works step-by-step:

1. Establishing the Foundation (Typical Price)

The tool begins by looking at the "Typical Price" of an asset. It does this by calculating the average of three main data points for every candle: the High, the Low, and the Closing price. This provides a balanced view of the market's activity during that specific timeframe.

2. Calculating Price Movement (Moving Average)

Before it can determine momentum, the script calculates a Simple Moving Average (SMA) based on a user-defined period. This acts as a baseline, showing where the price has been "hovering" over a set amount of time. It serves as the anchor point for all subsequent calculations.

3. Measuring Deviation and Relativity

The logic then analyzes how much the current price fluctuates away from that Moving Average:

  • Relative Difference: It measures the raw distance between the current price and the moving average.
  • Standard Deviation: It calculates the "volatility" or intensity of these fluctuations over a specific period. This tells the tool whether a price move is a normal vibration or an unusually large swing.

4. Generating the CCI Value

By dividing the Relative Difference by the Standard Deviation, the script produces the CCI (Commodity Channel Index). In simple terms, this value tells you how "extreme" the current price movement is compared to recent history. A high positive number suggests the price is pushing significantly higher than usual, while a low negative number suggests it is dropping significantly lower.

5. Smoothing the Data (The Final Average)

Because raw CCI values can sometimes be jagged or "choppy," making them difficult to read at a glance, the script performs one final calculation. It takes the CCI results and applies a second Moving Average over them.

Summary for the Trader

The final output on your chart consists of two main lines:

  • The CCI Line: Represents the smoothed momentum of the market.
  • The Average Line: Acts as a secondary filter to help confirm whether the momentum is gaining strength or beginning to weaken.

By using this dual-layer approach, the script helps smooth out minor price spikes, allowing you to see the underlying trend of the market more clearly.

Indicators Used
Moving average indicator
Miscellaneous
Implements a curve of type %1
15 Views
0 Downloads
0 Favorites
CCIAverage
//+------------------------------------------------------------------+
//|                                                   CCIAverage.mq4 |
//|                              Copyright © 2009, Maxim Kovalevskiy |
//|                                       email: caspermax@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Maxim Kovalevskiy"
#property link      "caspermax@gmail.com"
//----
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 LightSeaGreen
#property indicator_color2 Red
//---- input parameters
extern int CCIPeriod = 14;
extern int AveragePeriod = 14;
//---- buffers
double CCIBuffer[];
double AverageBuffer[];

double RelBuffer[];
double DevBuffer[];
double MovBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   string short_name;
//---- 3 additional buffers are used for counting.
   IndicatorBuffers(5);
   SetIndexBuffer(2, RelBuffer);
   SetIndexBuffer(3, DevBuffer);
   SetIndexBuffer(4, MovBuffer);
//---- indicator lines
   SetIndexStyle(0, DRAW_LINE);
   SetIndexBuffer(0, CCIBuffer);
   SetIndexStyle(1, DRAW_LINE);
   SetIndexBuffer(1, AverageBuffer);
//----
   if(CCIPeriod <= 0) CCIPeriod = 14;
   if(AveragePeriod <= 0) AveragePeriod = 14;
//----
   SetIndexDrawBegin(0, CCIPeriod);
   SetIndexDrawBegin(0, AveragePeriod);
  
//---- name for DataWindow and indicator subwindow label
   short_name="CCI(" + CCIPeriod + ") Average("+ AveragePeriod +")";
   IndicatorShortName(short_name);
   SetIndexLabel(0, short_name);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Commodity Channel Index                                          |
//+------------------------------------------------------------------+
int start()
  {
   int    i, k, counted_bars = IndicatorCounted();
   double price, sum, mul; 
   
   if(CCIPeriod <= 1) return(0);
   if(Bars <= CCIPeriod) return(0);
   
   if(AveragePeriod <= 1) return(0);
   if(Bars <= AveragePeriod) 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++;
//---- 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--;
     }
//----
   i = Bars - AveragePeriod + 1;
   if(counted_bars > AveragePeriod - 1) i = Bars - counted_bars - 1;
   while(i >= 0)
     {
       int averagesum = 0;
       for (k=0; k < AveragePeriod; k++)
       {
         averagesum = averagesum + CCIBuffer[i-k];
       }
       AverageBuffer[i] = averagesum / AveragePeriod;
       
       i--;
     }
//---- average counting

//----
   return(0);
  }
//+------------------------------------------------------------------+

Comments