/*
вызов из кодов:
iCustom(
   string symbol,    // символьное имя инструмента (NULL- текущий)
   int timeframe,    // тайм-фрейм (0- текущий)
   "iCCI.Gap",       // имя этого индикатора
   //
   int CCIperiod     // период индикатора
   int Price,        // тип цены:
                        // 0 - PRICE_CLOSE - цена закрытия 
                        // 1 - PRICE_OPEN - цена открытия
                        // 2 - PRICE_HIGH - макс.цена
                        // 3 - PRICE_LOW - мин.цена
                        // 4 - PRICE_MEDIAN - средняя цена,(high+low)/2
                        // 5 - PRICE_TYPICAL - типичная цена,(high+low+close)/3
                        // 6 - PRICE_WEIGHTED - взвешенная цена закрытия,(high+low+close+close)/4
   double Sens,      // порог чувствительности в пп.
   //
   int mode,         // mode - номер буфера индикатора: 0 - CCI
   int shift         // сдвиг
);

==============

iCustom(NULL,0,"iCCI.NR", CCIperiod,Price,Sens, 0,i);
*/

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 LightSeaGreen
#property indicator_maximum  300
#property indicator_minimum -300
#property indicator_level1  100
#property indicator_level2    0
#property indicator_level3 -100

// входные параметры
   // MA
 int MAperiod=1; // период предварительного сглаживания
 int MAmethod=0; // метод предварительного сглаживания
   // CCI
extern int CCIperiod=10; // период индикатора
extern int Price=5; // тип цены
extern double Sens=0; // порог в пп.
   double sens; // порог в ценах

// массивы инд.буферов
double Ind[]; // индикатора
double price[]; // безгэповых котировок
double Mov[]; // опорная MA

double mul; // нормирующий множитель

void init() {
   mul=0.015/CCIperiod; // нормирующий множитель
   sens=Sens*CCIperiod*Point;
   string short_name="CCI("+CCIperiod+")";
   // буферы
   IndicatorBuffers(3); 
   SetIndexBuffer(0,Ind); // индикатора
   SetIndexLabel(0,short_name);
   SetIndexBuffer(1,price); // безгэповых котировок
   SetIndexBuffer(2,Mov); // опорной MA
   // короткое имя
   if(Sens>0) short_name=DoubleToStr(Sens,1)+" "+short_name;
   IndicatorShortName(short_name);   
  }

void start() {
   // граница пересчета
   int limit=Bars-IndicatorCounted()-1;  
   if(limit>1) limit=Bars-1; 
   // заполнение массива значениями MA
   for(int i=limit; i>=0; i--) 
      price[i]=iMA(NULL,0,MAperiod,0,MAmethod,Price, i); 
   // опорная MA по массиву price[]
   for(i=limit; i>=0; i--) 
      Mov[i]=iMAOnArray(price,0,CCIperiod,0,0, i);
   for(i=limit; i>=0; i--) {
      double div=0,dif;
      double ma=Mov[i];
      // модуль отклонений 
      for(int j=i+CCIperiod-1;j>=i;j--) div+=MathAbs(price[j]-ma); 
      div=mul*MathMax(div,sens); // шумоподавление
      dif=price[i]-ma; // отклонения
      // расчет осциллятора
      if(div==0) Ind[i]=0;
      else Ind[i]=dif/div;
     }
  }

