//+------------------------------------------------------------------
//+------------------------------------------------------------------
#property  copyright "www.forex-tsd.com"
#property  link      "www.forex-tsd.com"

#property  indicator_separate_window
#property  indicator_buffers 8
#property  indicator_minimum 0
#property  indicator_maximum 5
//
//
//
//
//

extern string _                 = "Parameters";
extern int    pq                =  2;
extern int    pr                = 10;
extern int    ps                =  5;
extern int    trigger           =  3;
extern int    BarWidth          =  0;
extern color  BarColorUp        = LimeGreen;
extern color  BarColorDown      = Red;
extern color  BarTextColor      = DimGray;
extern int    BarTextShiftRight = 10;
extern bool   LabelsVisible     = true;
extern string LabelsUniqueID    = "14tfErgodicCCI";
extern bool   alertsOn          = false;
extern bool   alertsMessage     = false;
extern bool   alertsSound       = false;
extern bool   alertsEmail       = false;
extern int    mintf             = 15;  //1 - m1,m5,m15,h1 минимальный отображаемый ТФ
                                       //5 - m5,m15,h1,h4
                                       //15 - m15,h1,h4,d1
                                       //60 - h1,h4,d1,w1
                                       //................

//
//
//
//
//

double valueTf1Up[];
double valueTf1Dn[];
double valueTf2Up[];
double valueTf2Dn[];
double valueTf3Up[];
double valueTf3Dn[];
double valueTf4Up[];
double valueTf4Dn[];

//
//
//
//
//

string indicatorFileName;
bool   returnBars;
bool   calculateValue;
string shortName;
int    per1,per2,per3,per4;

//+------------------------------------------------------------------
//|                                                                  
//+------------------------------------------------------------------
//
//
//
//
//

int init()
{
   SetIndexBuffer(0,valueTf1Up);
   SetIndexBuffer(1,valueTf1Dn);
   SetIndexBuffer(2,valueTf2Up);
   SetIndexBuffer(3,valueTf2Dn);
   SetIndexBuffer(4,valueTf3Up);
   SetIndexBuffer(5,valueTf3Dn);
   SetIndexBuffer(6,valueTf4Up);
   SetIndexBuffer(7,valueTf4Dn);
      
      //
      //
      //
      //
      //
      
         indicatorFileName = WindowExpertName();
         calculateValue    = (_=="calculateValue"); if (calculateValue) return(0);
         returnBars        = (_=="returnBars");     if (returnBars)     return(0);
         per1 = mintf;
         setPeriods(per1,per2,per3,per4);
         shortName = LabelsUniqueID;
   
      //
      //
      //
      //
      //
      
   IndicatorShortName(shortName);         
   return(0);
}


//
//
//
//
//

int deinit()
{
   string lookFor       = LabelsUniqueID+":";
   int    lookForLength = StringLen(lookFor);
   for (int i=ObjectsTotal()-1; i>=0; i--)
   {
      string objectName = ObjectName(i);
            if (StringSubstr(objectName,0,lookForLength) == lookFor) ObjectDelete(objectName);
   }
   return(0);
}

//+------------------------------------------------------------------
//|                                                                  
//+------------------------------------------------------------------
//
//
//
//
//

double buffer[][8];
#define mtm    0
#define absmtm 1
#define var1   2
#define var2   3
#define var2a  4
#define var2b  5
#define var2c  6
#define var2d  7

//
//
//
//
//

int start()
{
   int i,r,limit,counted_bars=IndicatorCounted();

   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
           limit=MathMin(Bars-counted_bars,Bars-1);
           if (returnBars) { valueTf1Up[0] = limit+1; return(0); }
 
   //
   //
   //
   //
   //

   if (calculateValue)
   {
      if (ArrayRange(buffer,0) != Bars) ArrayResize(buffer,Bars);
      double alphaPq = 2.0/(1.0+pq);
      double alphaPr = 2.0/(1.0+pr);
      double alphaPs = 2.0/(1.0+ps);
      double alphaTrigger = 2.0/(1.0+trigger);
   
      for(i=limit,r=Bars-limit-1; i >=0; i--,r++) 
      {
         buffer[r][mtm]    = Close[i]-Close[i+1];
         buffer[r][absmtm] = MathAbs(buffer[r][mtm]);
         buffer[r][var1]   = buffer[r-1][var1]  + alphaPq*(buffer[r][mtm]   -buffer[r-1][var1]);
         buffer[r][var2]   = buffer[r-1][var2]  + alphaPr*(buffer[r][var1]  -buffer[r-1][var2]);
         buffer[r][var2a]  = buffer[r-1][var2a] + alphaPq*(buffer[r][absmtm]-buffer[r-1][var2a]);
         buffer[r][var2b]  = buffer[r-1][var2b] + alphaPr*(buffer[r][var2a] -buffer[r-1][var2b]);
         buffer[r][var2c]  = buffer[r-1][var2c] + alphaPs*(buffer[r][var2]  -buffer[r-1][var2c]);
         buffer[r][var2d]  = buffer[r-1][var2d] + alphaPs*(buffer[r][var2b] -buffer[r-1][var2d]);
         if (buffer[r][var2d]!=0)
               valueTf1Up[i] = (500*buffer[r][var2c]/buffer[r][var2d]);
         else  valueTf1Up[i] = 0;
               valueTf1Dn[i] = valueTf1Dn[i+1] + alphaTrigger*(valueTf1Up[i]-valueTf1Dn[i+1]);
      }
      return(0);
   }      

   //
   //
   //
   //
   //
   
   limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,per2,indicatorFileName,"returnBars",0,0)*per2/Period()));
   limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,per3,indicatorFileName,"returnBars",0,0)*per3/Period()));
   limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,per4,indicatorFileName,"returnBars",0,0)*per4/Period()));
   for(i=limit; i >=0; i--) 
   {
      setValues(i,4,per1,valueTf1Up,valueTf1Dn);
      setValues(i,3,per2,valueTf2Up,valueTf2Dn);
      setValues(i,2,per3,valueTf3Up,valueTf3Dn);
      setValues(i,1,per4,valueTf4Up,valueTf4Dn);
   }

   //
   //
   //
   //
   //
   
   for (i=0; i<8; i++) 
   {
      if (MathMod(i,2)==0)
            SetIndexStyle(i,DRAW_ARROW,EMPTY,BarWidth,BarColorUp);
      else  SetIndexStyle(i,DRAW_ARROW,EMPTY,BarWidth,BarColorDown);
      SetIndexArrow(i,110);
   }         
   if (LabelsVisible)
   {
      setLabel(1,BarTextShiftRight,1.5,timeFrameToString(per4),BarTextColor);
      setLabel(2,BarTextShiftRight,2.5,timeFrameToString(per3),BarTextColor);
      setLabel(3,BarTextShiftRight,3.5,timeFrameToString(per2),BarTextColor);
      setLabel(4,BarTextShiftRight,4.5,timeFrameToString(per1),BarTextColor);
   }      

   //
   //
   //
   //
   //
   
   manageAlerts();
}


//+------------------------------------------------------------------
//|                                                                  
//+------------------------------------------------------------------
//
//
//
//
//

void setValues(int i, double value, int period, double& upArray[], double& dnArray[])
{
   int y = iBarShift(NULL,period,Time[i]);
      double main       = iCustom(NULL,period,indicatorFileName,"calculateValue",pq,pr,ps,trigger,0,y);
      double signal     = iCustom(NULL,period,indicatorFileName,"calculateValue",pq,pr,ps,trigger,1,y);
             upArray[i] = EMPTY_VALUE;
             upArray[i] = EMPTY_VALUE;
             if (main>signal) upArray[i] = value;
             if (main<signal) dnArray[i] = value;
}

//+------------------------------------------------------------------
//|                                                                  
//+------------------------------------------------------------------
//
//
//
//
//

void manageAlerts()
{
   if (!calculateValue && alertsOn)
   {
      bool trendUp   = false;
      bool trendDown = false;
      if (valueTf1Up[0]!=EMPTY_VALUE && valueTf2Up[0]!=EMPTY_VALUE && valueTf3Up[0]!=EMPTY_VALUE && valueTf4Up[0]!=EMPTY_VALUE) trendUp   = true;
      if (valueTf1Dn[0]!=EMPTY_VALUE && valueTf2Dn[0]!=EMPTY_VALUE && valueTf3Dn[0]!=EMPTY_VALUE && valueTf4Dn[0]!=EMPTY_VALUE) trendDown = true;
      if (trendUp)    doAlert("up");
      if (trendDown)  doAlert("down");
   }
}   

//
//
//
//
//

void doAlert(string doWhat)
{
   static string   previousAlert="nothing";
   string message;
   
      if (previousAlert != doWhat) {
          previousAlert  = doWhat;

          //
          //
          //
          //
          //

          message =  StringConcatenate(Symbol()," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," 4 time frame ergodic CCIs aligned ",doWhat);
             if (alertsMessage) Alert(message);
             if (alertsEmail)   SendMail(StringConcatenate(Symbol(),"4 time frame ergodic CCI"),message);
             if (alertsSound)   PlaySound("alert2.wav");
      }
}

//+------------------------------------------------------------------
//|                                                                  
//+------------------------------------------------------------------
//
//
//
//
//

//void setPeriods(int& Period_1, int& Period_2, int& Period_3, int& Period_4)
//{
//   switch(Period()) 
//   {
//      case PERIOD_M1:  Period_1=PERIOD_M1;  Period_2=PERIOD_M5;  Period_3=PERIOD_M15; Period_4=PERIOD_M30; break;
//      case PERIOD_M5:  Period_1=PERIOD_M5;  Period_2=PERIOD_M15; Period_3=PERIOD_H1; Period_4=PERIOD_H4; break;
//      case PERIOD_M15: Period_1=PERIOD_M15; Period_2=PERIOD_H1;  Period_3=PERIOD_H4;  Period_4=PERIOD_D1; break;
//      case PERIOD_M30: Period_1=PERIOD_M30; Period_2=PERIOD_H1;  Period_3=PERIOD_H4;  Period_4=PERIOD_D1;  break;
//      case PERIOD_H1:  Period_1=PERIOD_M15; Period_2=PERIOD_H1;  Period_3=PERIOD_H4;  Period_4=PERIOD_D1; break;
//      case PERIOD_H4:  Period_1=PERIOD_H1;  Period_2=PERIOD_H4;  Period_3=PERIOD_D1;  Period_4=PERIOD_W1; break;
//      case PERIOD_D1:  Period_1=PERIOD_D1;  Period_2=PERIOD_W1;  Period_3=PERIOD_MN1; Period_4=PERIOD_MN1; break;
//      case PERIOD_W1:  Period_1=PERIOD_W1;  Period_2=PERIOD_MN1; Period_3=PERIOD_MN1; Period_4=PERIOD_MN1; break;
//      case PERIOD_MN1: Period_1=PERIOD_MN1; Period_2=PERIOD_MN1; Period_3=PERIOD_MN1; Period_4=PERIOD_MN1; break;
//   }
//}

void setPeriods(int& Period_1, int& Period_2, int& Period_3, int& Period_4)
{
   switch(Period_1) 
   {
      case PERIOD_M1:  Period_2=PERIOD_M5;  Period_3=PERIOD_M15; Period_4=PERIOD_M30; break;
      case PERIOD_M5:  Period_2=PERIOD_M15; Period_3=PERIOD_H1; Period_4=PERIOD_H4; break;
      case PERIOD_M15: Period_2=PERIOD_H1;  Period_3=PERIOD_H4;  Period_4=PERIOD_D1; break;
      case PERIOD_M30: Period_2=PERIOD_H1;  Period_3=PERIOD_H4;  Period_4=PERIOD_D1;  break;
      case PERIOD_H1:  Period_2=PERIOD_H1;  Period_3=PERIOD_H4;  Period_4=PERIOD_D1; break;
      case PERIOD_H4:  Period_2=PERIOD_H4;  Period_3=PERIOD_D1;  Period_4=PERIOD_W1; break;
      case PERIOD_D1:  Period_2=PERIOD_W1;  Period_3=PERIOD_MN1; Period_4=PERIOD_MN1; break;
      case PERIOD_W1:  Period_2=PERIOD_MN1; Period_3=PERIOD_MN1; Period_4=PERIOD_MN1; break;
      case PERIOD_MN1: Period_2=PERIOD_MN1; Period_3=PERIOD_MN1; Period_4=PERIOD_MN1; break;
      default:         Period_1=PERIOD_M15; Period_2=PERIOD_H1; Period_3=PERIOD_H4; Period_4=PERIOD_D1; break;
   }
}
//+------------------------------------------------------------------
//|                                           
//+------------------------------------------------------------------
//
//
//
//
//

void setLabel(string add, int shift, double gap, string txt, color theColor, string fontName="Arial")
{
   string name = LabelsUniqueID+":"+add;
      ObjectCreate(name, OBJ_TEXT, WindowFind(shortName),0,0);
         ObjectSet(name, OBJPROP_TIME1 ,Time[0]+Period()*shift*60);
         ObjectSet(name, OBJPROP_PRICE1,gap);
         ObjectSetText(name,txt,9,fontName,theColor);
}

//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
//
//
//
//
//

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("");
}