//+------------------------------------------------------------------
//|  original version coded by Mladen for forex-tsd.com
//|  histo version mod by Brax64
//|
//+------------------------------------------------------------------

#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1  Gainsboro
#property indicator_color2  C'200,0,0'
#property indicator_color3  DimGray
#property indicator_color4  C'35,95,235'
#property indicator_width1  4
#property indicator_width2  2
#property indicator_width3  2
#property indicator_width4  2
#property indicator_minimum 0
#property indicator_levelcolor C'60,60,60'

//
//
//
//
//

extern int    CmiPeriod       = 60;
extern int    AvgPeriod       = 10;
extern int    AvgMethod       = MODE_SMA;
extern double Level1          = 40;
extern double Level2          = 50;
extern double Level3          = 60;
extern string UniqueID        = "Choppy Market Index histo 1 (";

extern bool   alertsOn        = false;
extern bool   alertsOnCurrent = true;
extern bool   alertsMessage   = true;
extern bool   alertsSound     = false;
extern bool   alertsEmail     = false;

extern bool   arrowsVisible   = false;
extern string arrowsUniqueID  = "CMIHArrows1";
extern color  arrowsUpColor   = DeepSkyBlue;
extern color  arrowsDnColor   = PaleVioletRed;
extern int    arrowsUpCode    = 241;
extern int    arrowsDownCode  = 242;
extern int    arrowsSize      = 1;

//
//
//
//
//

double CmiBuffer[];
double AvgBuffer[];
double Diff[];
double DrawRange[];
double DrawNoZone[];
double DrawTrend[];
double trend1[];
double trend2[];

int    Window;
int    dig = 4;
string Name;

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

int init()
{
   IndicatorBuffers(8);
      SetIndexBuffer(0,AvgBuffer);  SetIndexLabel(0,"SMA");
      SetIndexBuffer(1,DrawRange);  SetIndexLabel(1,"Range");  SetIndexStyle(1,DRAW_HISTOGRAM);
      SetIndexBuffer(2,DrawNoZone); SetIndexLabel(2,"NoZone"); SetIndexStyle(2,DRAW_HISTOGRAM);
      SetIndexBuffer(3,DrawTrend);  SetIndexLabel(3,"Trend");  SetIndexStyle(3,DRAW_HISTOGRAM);
      SetIndexBuffer(4,CmiBuffer);
      SetIndexBuffer(5,Diff);
      SetIndexBuffer(6,trend1);
      SetIndexBuffer(7,trend2);
   
      SetLevelValue(0,Level1); 
      SetLevelValue(1,Level2);
      SetLevelValue(2,Level3);

      //
      //
      //
      //
      //
      
      if (StringFind(Symbol(),"JPY",0) != -1) {dig = 2;}
         Name = UniqueID+CmiPeriod+","+AvgPeriod+")";
      IndicatorShortName(Name);
   return(0);
}

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

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

int start()
{
   static bool objectsInitialized = false; initObjects(objectsInitialized);
   int i,limit,countedBars = IndicatorCounted();

      if (countedBars<0) return(-1);
      if (countedBars>0) countedBars--;
         limit = MathMin(Bars-countedBars,Bars-1);
   
   //
   //
   //
   //
   //
   
   for(i = limit; i >=0; i--)
   {
      
      double hi = High[iHighest(NULL,0,MODE_HIGH,CmiPeriod,i)];
      double lo =  Low[iLowest (NULL,0,MODE_LOW ,CmiPeriod,i)];
         if (hi!=lo)
               CmiBuffer[i] = 100.0*MathAbs(Close[i]-Close[i+CmiPeriod])/(hi-lo);
         else  CmiBuffer[i] = 0;

         DrawRange[i]  = EMPTY_VALUE;
         DrawNoZone[i] = EMPTY_VALUE;
         DrawTrend[i]  = EMPTY_VALUE;
         while (true)
         {
            if (CmiBuffer[i] >= 60) { DrawTrend[i]  = CmiBuffer[i]; break; }
            if (CmiBuffer[i] >= 40) { DrawNoZone[i] = CmiBuffer[i]; break; }
                                      DrawRange[i]  = CmiBuffer[i]; break;
         }
 	}
   for(i = limit; i>=0; i--)
   {
      AvgBuffer[i] = iMAOnArray(CmiBuffer,0,AvgPeriod,0,AvgMethod,i);
      trend1[i]    = 0;
      trend2[i]    = 0;
      Diff[i]      = Close[i] - Close[i+20];
         if (AvgBuffer[i]>Level3 && Diff[i]>0) trend1[i] =  1;
         if (AvgBuffer[i]>Level3 && Diff[i]<0) trend1[i] = -1;
         if (AvgBuffer[i]<Level1 && Diff[i]>0) trend2[i] =  1;
         if (AvgBuffer[i]<Level1 && Diff[i]<0) trend2[i] = -1;
         manageArrow(i);
   }      
   
   //
   //
   //
   //
   //


   color ColorDIF = DimGray;
   color ColorAVG = Gold;

      if(Diff[1] >  0)       ColorDIF = C'35,95,235';
      if(Diff[1] <  0)       ColorDIF = C'200,0,0';
      if(AvgBuffer[1] <= 40) ColorAVG = C'200,0,0';
      if(AvgBuffer[1] >= 60) ColorAVG = C'35,95,235';
   
      string d20bars   = "20 Bars Differential : ";
      string diff      = DoubleToStr(Diff[1],dig);
      string sma       = "SMA(" + AvgPeriod + ") :";
      string sma_value = DoubleToStr(AvgBuffer[1],dig);
      string trend1    = "TREND LONG  if SMA>60 & dif positive";
      string trend2    = "TREND SHORT if SMA>60 & dif negative";
      string range1    = "RANGE LONG  if SMA<40 & dif negative";
      string range2    = "RANGE SHORT if SMA<40 & dif positive";
      
         ObjectSetText(UniqueID+"label_d20bars", d20bars, 12, "Arial Black", DimGray);
         ObjectSetText(UniqueID+"label_diff", diff, 12, "Arial Black", ColorDIF);
         ObjectSetText(UniqueID+"label_sma", sma, 12, "Arial Black", DimGray);
         ObjectSetText(UniqueID+"label_sma_value", sma_value, 12, "Arial Black", ColorAVG);
         ObjectSetText(UniqueID+"label_trend1", trend1, 9, "Courier New", C'35,95,235');
         ObjectSetText(UniqueID+"label_trend2", trend2, 9, "Courier New", C'35,95,235');
         ObjectSetText(UniqueID+"label_range1", range1, 9, "Courier New", C'200,0,0');
         ObjectSetText(UniqueID+"label_range2", range2, 9, "Courier New", C'200,0,0');
           
   manageAlerts();           
	return(0);	
}


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

void manageArrow(int i)
{
   if (arrowsVisible)
   {
      deleteArrow(Time[i]); 
      if (trend1[i]!=trend1[i+1])
      {
         if (trend1[i] == 1) drawArrow(i,arrowsUpColor,arrowsUpCode  ,false);
         if (trend1[i] ==-1) drawArrow(i,arrowsUpColor,arrowsDownCode,true);
      }
      if (trend2[i]!=trend2[i+1])
      {
         if (trend2[i] == 1) drawArrow(i,arrowsDnColor,arrowsDownCode,true);
         if (trend2[i] ==-1) drawArrow(i,arrowsDnColor,arrowsUpCode  ,false);
      }
   }
}               

//
//
//
//
//

void drawArrow(int i,color theColor,int theCode,bool up)
{
   string name = arrowsUniqueID+":"+Time[i];
   double gap  = 3.0*iATR(NULL,0,20,i)/4.0;   
   
      //
      //
      //
      //
      //
      
      ObjectCreate(name,OBJ_ARROW,0,Time[i],0);
         ObjectSet(name,OBJPROP_ARROWCODE,theCode);
         ObjectSet(name,OBJPROP_COLOR,theColor);
         ObjectSet(name,OBJPROP_WIDTH,arrowsSize);
         if (up)
               ObjectSet(name,OBJPROP_PRICE1,High[i]+gap);
         else  ObjectSet(name,OBJPROP_PRICE1,Low[i] -gap);
}

//
//
//
//
//

void deleteArrow(datetime time)
{
   string lookFor = arrowsUniqueID+":"+time; ObjectDelete(lookFor);
}


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

void manageAlerts()
{
   if (alertsOn)
   {
      if (alertsOnCurrent)
           int whichBar = 0;
      else     whichBar = 1;
      
      
      static datetime time1=0;
      static string   mess1=""; 
         if (trend1[whichBar] != trend1[whichBar+1])
         {
            if (trend1[whichBar] ==  1) doAlert(whichBar,time1,mess1,"average is over "+DoubleToStr(Level3,2)+" and diff became positive");
            if (trend1[whichBar] == -1) doAlert(whichBar,time1,mess1,"average is over "+DoubleToStr(Level3,2)+" and diff became negative");
         }
      static datetime time2=0;
      static string   mess2=""; 
         if (trend2[whichBar] != trend2[whichBar+1])
         {
            if (trend2[whichBar] ==  1) doAlert(whichBar,time2,mess2,"average is bellow "+DoubleToStr(Level1,2)+" and diff became positive");
            if (trend2[whichBar] == -1) doAlert(whichBar,time2,mess2,"average is bellow "+DoubleToStr(Level1,2)+" and diff became negative");
         }
   }
}

//
//
//
//
//

void doAlert(int forBar, datetime& previousTime, string& previousAlert,  string doWhat)
{
   string message;
   
   if (previousAlert != doWhat || previousTime != Time[forBar]) {
       previousAlert  = doWhat;
       previousTime   = Time[forBar];

       //
       //
       //
       //
       //

       message =  StringConcatenate(Symbol()," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," CMI histo ",doWhat);
          if (alertsMessage) Alert(message);
          if (alertsEmail)   SendMail(StringConcatenate(Symbol(),"CMI histo"),message);
          if (alertsSound)   PlaySound("alert2.wav");
   }
}


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

int xDistance = 90;
int yDistance = 10;
void initObjects(bool& initialized)
{
   Window = WindowFind(Name);
   if (initialized) return; initialized = true;
      createLabel("label_d20bars"  ,xDistance   ,yDistance);
      createLabel("label_diff"     ,xDistance-80,yDistance);
      createLabel("label_sma"      ,xDistance+5 ,yDistance+20);
      createLabel("label_sma_value",xDistance-80,yDistance+20);
      createLabel("label_trend1"   ,xDistance-80,yDistance-5 ,3);
      createLabel("label_trend2"   ,xDistance-80,yDistance+10,3);
      createLabel("label_range1"   ,xDistance-80,yDistance+25,3);
      createLabel("label_range2"   ,xDistance-80,yDistance+40,3);
}
void createLabel(string objName, int xpos, int ypos, int corner=1)
{
   objName = UniqueID+objName;
   
     if(ObjectFind(objName) == -1)
         ObjectCreate(objName, OBJ_LABEL, Window, 0, 0);
            ObjectSet(objName, OBJPROP_CORNER, corner);
            ObjectSet(objName, OBJPROP_XDISTANCE, xpos);
            ObjectSet(objName, OBJPROP_YDISTANCE, ypos);
}