//+------------------------------------------------------------------+
//|                                                       IG-CCI.mq5 |
//|                                          Copyright 2023,JBlanked |
//|                                  https://www.github.com/jblanked |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023,JBlanked"
#property link      "https://www.github.com/jblanked"
#property version   "1.00"
#property indicator_separate_window

#property indicator_buffers 3
#property indicator_plots 3

#property indicator_color1 DodgerBlue
#property indicator_color2 Lavender
#property indicator_color3 DeepPink

#property indicator_level1     0.0
#property indicator_levelcolor clrSilver
#property indicator_levelstyle STYLE_DOT

#property indicator_type1 DRAW_LINE
#property indicator_type2 DRAW_LINE
#property indicator_type3 DRAW_LINE


input int InpKPeriod=1; // K Period
input int InpDPeriod=3; // D Period
input int InpSlowing=11; // Slowing
input int CCI    = 34; // CCI Period
input double c1     = 0.5;
input double c2     = 0.5;
input double c3     = 0.5;
input int    p      = 6;
input int MaPeriod  = 61; 
input ENUM_MA_METHOD MaMethod = MODE_SMA; 
input int    period  = 21;
//---- buffers

double ExtMapBuffer1[];
double ExtMapBuffer2[];
double ExtMapBuffer3[];
double CCI1,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,max,min;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
SetIndexBuffer(0,ExtMapBuffer1);
SetIndexBuffer(1,ExtMapBuffer2);
SetIndexBuffer(2,ExtMapBuffer3);

string short_name = "igcci2";
IndicatorSetString(INDICATOR_SHORTNAME,short_name);
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
int counted_bars=prev_calculated;
if (counted_bars<0) return(-1);
if (counted_bars>0) counted_bars--;
int pos=Bars(_Symbol,PERIOD_CURRENT) -counted_bars;
int limit = Bars(_Symbol,PERIOD_CURRENT) ;
if(pos > limit) 
{
   pos = limit;
}
double  dResult1;
int i ;
double a[];
//---- main calculation loop
while(pos>=0)
{
ArrayInitialize(a, EMPTY_VALUE);
ArrayResize(a, 0);
for(i=0; i<p; i++) {
   int size_a = ArraySize(a);
   ArrayResize(a, size_a+1);
  
a[size_a] =iCCI_Price(_Symbol,PERIOD_CURRENT,CCI,PRICE_TYPICAL,pos+i)*c1
+iCCI_Price(_Symbol,PERIOD_CURRENT,CCI,PRICE_TYPICAL,pos+(i-1))*c2-iCCI_Price(_Symbol,PERIOD_CURRENT,CCI,PRICE_TYPICAL,pos+i)*c3
+iCCI_Price(_Symbol,PERIOD_CURRENT,CCI,PRICE_TYPICAL,pos+(i-2))*c2-iCCI_Price(_Symbol,PERIOD_CURRENT,CCI,PRICE_TYPICAL,pos+(i-1))*c3
+iCCI_Price(_Symbol,PERIOD_CURRENT,CCI,PRICE_TYPICAL,pos+(i-3))*c2-iCCI_Price(_Symbol,PERIOD_CURRENT,CCI,PRICE_TYPICAL,pos+(i-2))*c3
+iCCI_Price(_Symbol,PERIOD_CURRENT,CCI,PRICE_TYPICAL,pos+(i-4))*c2-iCCI_Price(_Symbol,PERIOD_CURRENT,CCI,PRICE_TYPICAL,pos+(i-3))*c3
+iCCI_Price(_Symbol,PERIOD_CURRENT,CCI,PRICE_TYPICAL,pos+(i-5))*c2-iCCI_Price(_Symbol,PERIOD_CURRENT,CCI,PRICE_TYPICAL,pos+(i-4))*c3;
}  
double a_max = a[ArrayMaximum(a)];
double a_min = a[ArrayMinimum(a)];
max = a_max;
min = a_min;
dResult1 = (max+min) ;
ExtMapBuffer1[pos] = dResult1 ;
 
ExtMapBuffer3[pos] = iMAOnArrayMQL4(ExtMapBuffer1,PERIOD_CURRENT,MaPeriod,period,MaMethod,pos); 
   
pos--;
} 

  int limits=Bars(_Symbol,PERIOD_CURRENT) - counted_bars;
  
  for(int j=0; j<limits; j++)
   {
   ExtMapBuffer2[j]=iCustom(Symbol(),PERIOD_CURRENT,"Stochastic",InpKPeriod,InpDPeriod,InpSlowing,0,j);
   } 
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
double iCCI_Price(string symbol, ENUM_TIMEFRAMES timeframe,int cci_period, ENUM_APPLIED_PRICE applied_price, int shift)
 {  
   int handle = iCCI(symbol,timeframe,cci_period, applied_price);
   
   return CopyBufferMQL4(handle,0,shift);
}


double CopyBufferMQL4(int handle,int index,int shift)
  {
   double buf[];
   switch(index)
     {
      case 0: if(CopyBuffer(handle,0,shift,1,buf)>0)
         return(buf[0]); break;
      default: break;
     }
   return(EMPTY_VALUE);
  }
  
  
  
double iMAOnArrayMQL4(double &array[],
                      int total,
                      int periodd,
                      int ma_shift,
                      int ma_methoddd,
                      int shift)
  {
   double buf[],arr[];
   if(total==0) total=ArraySize(array);
   if(total>0 && total<=periodd) return(0);
   if(shift>total-periodd-ma_shift) return(0);
   switch(ma_methoddd)
     {
      case MODE_SMA :
        {
         total=ArrayCopy(arr,array,0,shift+ma_shift,periodd);
         if(ArrayResize(buf,total)<0) return(0);
         double sum=0;
         int    i,pos=total-1;
         for(i=1;i<periodd;i++,pos--)
            sum+=arr[pos];
         while(pos>=0)
           {
            sum+=arr[pos];
            buf[pos]=sum/periodd;
            sum-=arr[pos+periodd-1];
            pos--;
           }
         return(buf[0]);
        }
      case MODE_EMA :
        {
         if(ArrayResize(buf,total)<0) return(0);
         double pr=2.0/(periodd+1);
         int    pos=total-2;
         while(pos>=0)
           {
            if(pos==total-2) buf[pos+1]=array[pos+1];
            buf[pos]=array[pos]*pr+buf[pos+1]*(1-pr);
            pos--;
           }
         return(buf[shift+ma_shift]);
        }
      case MODE_SMMA :
        {
         if(ArrayResize(buf,total)<0) return(0);
         double sum=0;
         int    i,k,pos;
         pos=total-periodd;
         while(pos>=0)
           {
            if(pos==total-periodd)
              {
               for(i=0,k=pos;i<periodd;i++,k++)
                 {
                  sum+=array[k];
                  buf[k]=0;
                 }
              }
            else sum=buf[pos+1]*(period-1)+array[pos];
            buf[pos]=sum/period;
            pos--;
           }
         return(buf[shift+ma_shift]);
        }
      case MODE_LWMA :
        {
         if(ArrayResize(buf,total)<0) return(0);
         double sum=0.0,lsum=0.0;
         double price;
         int    i,weight=0,pos=total-1;
         for(i=1;i<=periodd;i++,pos--)
           {
            price=array[pos];
            sum+=price*i;
            lsum+=price;
            weight+=i;
           }
         pos++;
         i=pos+periodd;
         while(pos>=0)
           {
            buf[pos]=sum/weight;
            if(pos==0) break;
            pos--;
            i--;
            price=array[pos];
            sum=sum-lsum+price*periodd;
            lsum-=array[i];
            lsum+=price;
           }
         return(buf[shift+ma_shift]);
        }
      default: return(0);
     }
   return(0);
  }