//+------------------------------------------------------------------+
//|                                  BEMAC'S ICCE GRID 2012 v1-5.mq4 |
//|                                                           Oneday |
//|                                                                  |
//+------------------------------------------------------------------+
/*
   This indicator is a reworking of Bemac's original indicator, which is based on his original concept.
   You can find out more about ICCE by viewing his thread at Forex Factory: 
   
   http://www.forexfactory.com/showthread.php?t=162886
 
*/
#property copyright "Oneday"
#property link      ""
#property strict


#property indicator_chart_window

#define  fntFont        "Consolas"
#define  strFibPrefix   "IFL:"      // IFL = ICCE fib level
#define  strVersion     "-v1.5"
//=============================================================================================================|
extern   bool     blnDelete_ICCE_box      =  false;   // Delete the primary box objects if user sets to true                                                                                                              //|
extern   bool     blnClassicColours       =  true;    // Set to false to change to alternative object colours
extern   int      intTextOffset           =  20;      // The number of bars from right of chart to offset fib text
extern   int      intFontSize             =  9;       // Allow user to set font size
extern   int      intNumberOfDiagonals    =  20;      // Set the number of diagonals to draw
extern   bool     blnShowRisingDiagonals  =  true;    // change to false to remove rising diagonals
extern   bool     blnShowFallingDiagonals =  true;    // change to false to remove falling diagonals
extern   bool     blnShowMidDiagonals     =  false;   // change to false to remove mid diagonals
extern   bool     blnDrawRaysOnDiagonals  =  true;    // Set to false to switch off rays
extern   bool     blnSendEmailAlert       =  false;   // Set to true to receive alerts
extern   string   strObjectToMonitor;
extern   double   dblBuffer               =  10.0;    // Default pip buffer for alert zone
extern   color    clrAlertColour          =  OrangeRed; // Default colour for the text displaying the counts
extern   int      intTextCorner           =  2;       // Default corner to display the current count - 0=top-left, 1=top-right, 2=bottom-left & 3=bottom-right
extern   color    clrTextColour           =  MidnightBlue;  // Default colour for the text displaying the counts
extern   int      intTextX_coord          =  30;      // Default X coordinate for the labels
extern   int      intTextY_coord          =  30;      // Default Y coordinate for the first label
extern   int      intTextSpacing          =  12;      // Default spacing in pixels between the labels
extern   int      intTextFontSize         =  10;      // Default font size for the labels

// List of arrays
//=============================================================================================================|
string   A_strBoxObjects[6]      =  {"LeftBox","RightBox","UpperBox","LowerBox","MidBox","BoxFill"};
string   A_strPDobjNames[4]      =  {"PRD:F","PFD:F","PRD:B","PFD:B"};     // array of primary diagonal names
string   A_strInfoBoxObjects[6]  =  {"InfBoxLn:1","InfBoxLn:2","InfBoxLn:3","InfBoxLn:4","InfBoxLn:5","InfBoxLn:6"};
int      A_intBoxObjWidths[6]    =  {2,2,2,2,1, };
color    A_clrClassicSet[6]      =  {Navy,Green,Navy,Green,DarkViolet,Orange};   // Bemac's colour scheme   
color    A_clrAlternateSet[6]    =  {MidnightBlue,MidnightBlue,MidnightBlue,MidnightBlue,DarkSlateGray,Gray};
color    A_clrClassicTextSet[3]  =  {Navy,Green,DarkViolet};
color    A_clrAlternateTextSet[3]=  {MidnightBlue,MidnightBlue,DarkSlateGray};

color    A_clrClassicFibs[19]     = {Red,Sienna,DarkViolet,Sienna,Black,Red,Black,Black,Sienna,Sienna,Black,
                                    Black,Red,Black,Black,Sienna,DarkViolet,Sienna,Red};// fib colours
color    A_clrAlternateFibs[19]   = {Black,Black,Black,Black,Black,Black,Black,Black,Black,Black,
                                    Black,Black,Black,Black,Black,Black,Black,Black,Black};// alt' fib colours
                                    
color    A_clrColourArray[];        // empty array to store users selected object colour values
color    A_clrTextColourArray[];    // empty array to store users selected text colour values
color    A_clrFibsColourArray[];    // empty array to store users selected fib level colour values
double   A_dblICCEfibLevels[19]  =  {200.000,161.803,150.000,138.197,123.607,100.000,85.410,76.393,61.803,
                                    38.197,23.607,14.590,0.000,-14.590,-23.607,-38.197,-50.000,-61.803,-100.000};
double   A_dblICCEfibValues[19];

//=============================================================================================================|
color    clr52,clr50,clr47,clrPrimDiag,clrSecRiseDiag,clrSecFallDiag,clrMidRiseDiag,clrMidFallDiag;    
          
int      intBoxColourArraySize;     // Store the number of elements within the array
int      intTextColourArraySize;
int      intFibColourArraySize;
int      intSecDiagLineStyle;
int      intMidDiagLineStyle;
string   strMonitoring           =  "";  // set the variable to empty before init
string   strLeftICCEMarker       =  "LeftBox";  // These seven variables are the names of the ICCE box objects     
string   strRightICCEMarker      =  "RightBox";
string   strUpperICCEMarker      =  "UpperBox";
string   strLowerICCEMarker      =  "LowerBox";
string   strMidICCEMarker        =  "MidBox";
string   strBoxFill              =  "BoxFill"; 
string   strCreatedName          =  "DO NOT DELETE THIS OBJECT!!";// store the time that the box is created

// Prefixes added to the name of secondary rising diagonals."SRD:F:"= SecondaryRisingDiagonal:above(ray)Forward
string   strSRDaF                =  "SRD:aF:";    
string   strSRDaB                =  "SRD:aB:";
string   strSRDbF                =  "SRD:bF:";
string   strSRDbB                =  "SRD:bB:";
// Prefixes added to the name of secondary falling diagonals."SFD:F:"= SecondaryFallingDiagonal:below(ray)Forward
string   strSFDaF                =  "SFD:aF:";
string   strSFDaB                =  "SFD:aB:";
string   strSFDbB                =  "SFD:bB:";
string   strSFDbF                =  "SFD:bF:";

// Prefixes added to the name of mid rising diagonals."MRD:F:"= MidRisingDiagonal:above(ray)Forward
string   strMRDaF                =  "MRD:aF:";    
string   strMRDaB                =  "MRD:aB:";
string   strMRDbF                =  "MRD:bF:";
string   strMRDbB                =  "MRD:bB:";
// Prefixes added to the name of mid falling diagonals."MFD:F:"= SecondaryFallingDiagonal:below(ray)Forward
string   strMFDaF                =  "MFD:aF:";
string   strMFDaB                =  "MFD:aB:";
string   strMFDbB                =  "MFD:bB:";
string   strMFDbF                =  "MFD:bF:";

int      intLeftBarIndex;           // Store the index of the bar on far left of screen
int      intMidBarIndex = 0;        // Store the index position of the mid bar
int      intBarIncrementsOnChart;   // Store the total number of bar increments on the screen (scale dependent!) 
int      intRightBarIndex;          // Store the index of the bar on far right of screen
int      intFibTextAnchor;          // Store the bar index number to use for time coordinate of fib text labels
int      intFirstVisibleBar;        // An index ref' to the first visible bar relative to the right of chart
datetime dteLastTextAnchor;   
int      intNewLeftBarIndex;
int      intNewRightBarIndex;
int      intNewBarIncrementsOnChart;

datetime dteLeftMarkerTime;
datetime dteRightMarkerTime;

datetime dteLeftRefTime;            // added to improve diagonals in v1.5
datetime dteRightRefTime;           // added to improve diagonals in v1.5

double   dblHighestPrice;
double   dblLowestPrice;
int      intRange;
double   dblUpperMarkerPrice;
double   dblLowerMarkerPrice;
double   dblMidPrice;
double   dblCreationMarkerPrice;    // Stores a price coordinate for the ICCE box creation object
double   dblBemacConstant        =  17.94688; // total range(100) divided by box range(52.786-47.214)=100/5.572
double   dblBoxRange;               // The range of the box in pips
double   dblMultiplier;

datetime dteNewLeftMarkerTime;
datetime dteNewRightMarkerTime;
double   dblNewUpperMarkerPrice;
double   dblNewLowerMarkerPrice;
double   dblNewMidPrice;

int      i;
int      intObjTotal             =  0; // Used in object deletion loops
string   strObjRef;
int      intAlertSent;                 // Alert function sets value to 1 after sending mail alert
datetime dteOld_AlertT1;               // Used alert rectangle
datetime dteOld_AlertT2;               // Used alert rectangle
datetime dteNew_AlertT1;               // Used to check for new bar in email alert
datetime dteNew_AlertT2;               // Used to check for new bar in email alert
double   dblOld_MidPrice;
double   dblNew_MidPrice;
double   dblOld_AlertPrice;
double   dblNew_AlertPrice;
double   dblNew_Buffer;
int      intCheckMonitorLen;           // used to check the length of the string name of monitor object

int      intT1Marker;                  // index value of the left ICCE box vertical line
int      intNewT1Marker;
int      intT2Marker;                  // index value of the right ICCE box vertical line
int      intNewT2Marker;
int      intTimeRange;                 // the width of the box
int      intAccuracyFactor;        // used to store the time range multiplier to improve accuracy of trendlines
int      intAftAccuracyFactor; 
int      intSymbolType;                // used to check if forex or...
string   strMasterTimeFrame;

//=============================================================================================================|

int init(){
   
   dblOld_MidPrice      =  ((Ask + Bid) / 2.0);                            // current mid price @ initiation
   intCheckMonitorLen   =  StringLen(strObjectToMonitor);                  // check length of string
   dteOld_AlertT1       =  Time[10];
   dteOld_AlertT2       =  Time[0];
   intSymbolType        =  int(MarketInfo(Symbol(),MODE_PROFITCALCMODE));
   
   if(blnSendEmailAlert && intCheckMonitorLen != 0){ // check set to true & check name has been entered
      strMonitoring  = strObjectToMonitor;
      //Print("strObjectToMonitor is ", strMonitoring);
      if(ObjectFind(strMonitoring) == 0 && ObjectType(strMonitoring) == 1){// check object exists on main chart
         dblOld_AlertPrice =  ObjectGet(strMonitoring,OBJPROP_PRICE1);
         //Print("OBJECT TYPE IS HORIZONTAL LINE @ ",DoubleToStr(dblOld_AlertPrice,Digits));
      }
      if(ObjectFind(strMonitoring) == 0 && ObjectType(strMonitoring) == 2){// check if object is trend line
         dblOld_AlertPrice =  ObjectGetValueByShift(strMonitoring,0);
         //Print("OBJECT TYPE IS TREND LINE @ ",DoubleToStr(dblOld_AlertPrice,Digits));
      }
   } 
                                         
   if(Digits == 4 || Digits == 5){
      dblMultiplier  =  10000;   
   }else{
      dblMultiplier  =  100;
   }  
   
   intLeftBarIndex         =  WindowFirstVisibleBar();
      //Print("intLeftBarIndex = ",intLeftBarIndex);
   intBarIncrementsOnChart =  WindowBarsPerChart();
      //Print("intBarIncrementsOnChart = ",intBarIncrementsOnChart);
   
   UDF_SetupColourSchemeArrays();
   
   if(UDF_FindICCEBox() == 3){            // Returned if box has not been found
      UDF_FindMidBar(intLeftBarIndex,intBarIncrementsOnChart);
      UDF_PrimaryObjectCoordinates(intMidBarIndex);
      UDF_DrawPrimaryICCEobjects(true);
      UDF_DrawICCE_FibLevelobjects();
      UDF_DrawFibLabels();
      UDF_DrawPrimaryDiagonals();
      
      if(blnShowRisingDiagonals){
         UDF_DrawBullishDiagonals();
         if(blnShowMidDiagonals){
            UDF_DrawBullishMidDiagonals();
         }                      
      } 
      if(blnShowFallingDiagonals){ 
         UDF_DrawBearishDiagonals();
         if(blnShowMidDiagonals){
            UDF_DrawBearishMidDiagonals();
         }                   
      }
                    
   }else if(UDF_FindICCEBox() == 2){      // Returned if some of box has been found - objects missing!
      UDF_ClearICCEobjects();             // Clear up before creating new box
      UDF_DeleteTimeStamp();
      UDF_FindMidBar(intLeftBarIndex,intBarIncrementsOnChart);
      UDF_PrimaryObjectCoordinates(intMidBarIndex);
      UDF_DrawPrimaryICCEobjects(true);
      UDF_DrawICCE_FibLevelobjects();
      UDF_DrawFibLabels();
      UDF_DrawPrimaryDiagonals();
      
      if(blnShowRisingDiagonals){
         UDF_DrawBullishDiagonals(); 
         if(blnShowMidDiagonals){
            UDF_DrawBullishMidDiagonals();
         }                     
      } 
      if(blnShowFallingDiagonals){ 
         UDF_DrawBearishDiagonals(); 
         if(blnShowMidDiagonals){
            UDF_DrawBearishMidDiagonals();
         }                    
      }
      Print("some of ICCE Box found!");
   }else if(UDF_FindICCEBox() == 1){      // Returned if box has been found
      Print("ICCE Box found!");
      //Print("created on: ",TimeToStr(ObjectGet(strCreatedName,OBJPROP_TIME1),TIME_DATE|TIME_MINUTES));
      UDF_UpdatePrimaryCoords();
      UDF_ClearICCEobjects();
      UDF_FindMidBar(intLeftBarIndex,intBarIncrementsOnChart);
      UDF_DrawPrimaryICCEobjects(false);
      
      intT1Marker             =  iBarShift(NULL,0,dteLeftMarkerTime,true);    //<<<<<<<<<<<<
      intT2Marker             =  iBarShift(NULL,0,dteRightMarkerTime,true);   //<<<<<<<<<<<<
      intTimeRange            =  (intT1Marker - intT2Marker);                 //<<<<<<<<<<<<
      /*Print("intT1Marker @ init = ",intT1Marker);
      Print("intT2Marker @ init = ",intT2Marker);
      Print("intTimeRange @ init = ",intTimeRange);*/

      UDF_TimeCoordAccuracy(intTimeRange);  //<<<<<<<<<<<<<<<<<<<<<<<<<added
      UDF_AftTimeCoordAccuracy(intTimeRange);
      
      UDF_DrawICCE_FibLevelobjects();
      UDF_DrawFibLabels();
      //Print("init: call UDF_DrawPrimaryDiagonals()");
      UDF_DrawPrimaryDiagonals();
      //Print("UDF_DrawPrimaryDiagonals() done");
      if(blnShowRisingDiagonals){
         UDF_DrawBullishDiagonals();
         if(blnShowMidDiagonals){
            UDF_DrawBullishMidDiagonals();
         }                       
      } 
      if(blnShowFallingDiagonals){
         UDF_DrawBearishDiagonals();
         if(blnShowMidDiagonals){
            UDF_DrawBearishMidDiagonals();
         }                     
      }
   }
   
   UDF_DisplayText(clrTextColour,intTextCorner,intTextX_coord,intTextY_coord,intTextSpacing,intTextFontSize);
   UDF_ICCEinfoBox(); 
   strMasterTimeFrame   =  ObjectDescription(strCreatedName);
   
   Print("intAftAccuracyFactor = ",intAftAccuracyFactor);
   return(0);
}

//=============================================================================================================|
int deinit(){
   
   UDF_DeleteICCEfibLabels();
   ObjectDelete("AlertZone");
   
   if(blnDelete_ICCE_box){
      UDF_ClearICCEobjects();
      UDF_DeleteTimeStamp();
      UDF_DeleteICCEBoxInfoLabels();
   }
   return(0);
}

//=============================================================================================================|
int start(){
   
   int      intNewLeftShift;
   int      intNewRightShift;
   datetime dteNewLeftRefTime;
   datetime dteNewRightRefTime;
   
   if(UDF_FindICCEBox() == 2){
      UDF_DeleteICCEBox();
      UDF_DrawPrimaryICCEobjects(false);
   }
   
   dteNewLeftRefTime    =  datetime(ObjectGet(strLeftICCEMarker,OBJPROP_TIME1));
   intNewLeftShift      =  iBarShift(NULL,0,dteNewLeftRefTime,true);
   if(intNewLeftShift < 0){
      intNewLeftShift  =  iBarShift(NULL,0,dteLeftRefTime,false);
   }
   dteNewLeftMarkerTime =  Time[intNewLeftShift];
   
   dteNewRightRefTime   =  datetime(ObjectGet(strRightICCEMarker,OBJPROP_TIME1));
   intNewRightShift     =  iBarShift(NULL,0,dteNewRightRefTime,true);
   if(intNewRightShift < 0){
      intNewRightShift  =  iBarShift(NULL,0,dteNewRightRefTime,false);
   }
   dteNewRightMarkerTime =  Time[intNewRightShift];
   
   dblNewUpperMarkerPrice     =  ObjectGet(strUpperICCEMarker,OBJPROP_PRICE1);
   dblNewLowerMarkerPrice     =  ObjectGet(strLowerICCEMarker,OBJPROP_PRICE1);
   
   intNewT1Marker             =  iBarShift(NULL,0,dteNewLeftMarkerTime,true); //<<<<<<<<
   intNewT2Marker             =  iBarShift(NULL,0,dteNewRightMarkerTime,true);//<<<<<<<<
   
   intNewLeftBarIndex         =  WindowFirstVisibleBar();
   intNewBarIncrementsOnChart =  WindowBarsPerChart();  
   
   if(dteLeftRefTime != dteNewLeftRefTime || dteRightRefTime != dteNewRightRefTime ||
      dblUpperMarkerPrice  != dblNewUpperMarkerPrice || dblLowerMarkerPrice  != dblNewLowerMarkerPrice ||
      intT1Marker != intNewT1Marker || intT2Marker != intNewT2Marker){   //<<<<added t1 & t2
      
      intT1Marker    =  intNewT1Marker;   //<<<<added t1 & t2
      intT2Marker    =  intNewT2Marker;
      intTimeRange   =  (intT1Marker - intT2Marker);
      
      if(intTimeRange == 0){
         Print("Zero divide error at line 341!");
      } 
      
      UDF_UpdatePrimaryCoords();
      UDF_ClearICCEobjects();
      UDF_DeleteTimeStamp();
      UDF_DrawPrimaryICCEobjects(true);
      UDF_TimeCoordAccuracy(intTimeRange);  //<<<<<<<<<<<<<<<<<<<<<<<<<added
      UDF_AftTimeCoordAccuracy(intTimeRange);
      UDF_DrawICCE_FibLevelobjects();
      UDF_FindMidBar(intLeftBarIndex,intBarIncrementsOnChart);
      UDF_DrawFibLabels();
      //Print("start: call UDF_DrawPrimaryDiagonals()");
      UDF_DrawPrimaryDiagonals();
      //Print("start: UDF_DrawPrimaryDiagonals() done");

      if(blnShowRisingDiagonals){
         UDF_DrawBullishDiagonals();
         if(blnShowMidDiagonals){
            UDF_DrawBullishMidDiagonals();
         }                      
      } 
      if(blnShowFallingDiagonals){
         UDF_DrawBearishDiagonals(); 
         if(blnShowMidDiagonals){
            UDF_DrawBearishMidDiagonals();
         }                
      }
      UDF_ICCEinfoBox(); //***************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!<<<<
   }
   
   if(intNewLeftBarIndex != intLeftBarIndex || intNewBarIncrementsOnChart != intBarIncrementsOnChart){
      intLeftBarIndex         =  intNewLeftBarIndex;
      intBarIncrementsOnChart =  intNewBarIncrementsOnChart;
      UDF_DeleteICCEfibLabels();
      UDF_DeleteICCEBoxLabels();
      UDF_FindMidBar(intLeftBarIndex,intBarIncrementsOnChart);
      UDF_DrawFibLabels();
   }
   
   // email alert check
   dblNew_MidPrice      =  ((Ask + Bid) / 2.0);                            // current mid price @ initiation
   intCheckMonitorLen   =  StringLen(strObjectToMonitor);                  // check length of string
   if(dteOld_AlertT1 != Time[10] || dteOld_AlertT2 != Time[0]){
      dteOld_AlertT1 = Time[10];
      dteOld_AlertT2 = Time[0];
      ObjectDelete("AlertZone");
   }
   
   if(blnSendEmailAlert && intCheckMonitorLen != 0){                       // check set to true 
      strMonitoring  = strObjectToMonitor;
      //Print("start: strObjectToMonitor is ", strMonitoring);
      if(dblNew_MidPrice != dblOld_MidPrice){
         dblOld_MidPrice   =  dblNew_MidPrice;                             // reset mid price
         //Print("start: mid price is different");
      }
      
      if(ObjectFind(strMonitoring) == 0 && ObjectType(strMonitoring) == 1){// check object exists on main chart
         dblNew_AlertPrice =  ObjectGet(strMonitoring,OBJPROP_PRICE1);
         //Print("start: OBJECT TYPE IS HORIZONTAL LINE @ ",DoubleToStr(dblNew_AlertPrice,Digits));
      }
      if(ObjectFind(strMonitoring) == 0 && ObjectType(strMonitoring) == 2){ // check if object is trend line
         dblNew_AlertPrice =  ObjectGetValueByShift(strMonitoring,0);
         //Print("start: OBJECT TYPE IS TREND LINE @ ",DoubleToStr(dblNew_AlertPrice,Digits));
      }      
      if(dblNew_AlertPrice != dblOld_AlertPrice){
         
         dblOld_AlertPrice   =  dblNew_AlertPrice;                   // reset alert price and time coords
         Print("Email alert reset!");
         intAlertSent   =  0;                                        // reset alert sent to zero
         ObjectDelete("AlertZone");
      }
      
      double   dblUpperLimit;
      double   dblLowerLimit;
      if(dblMultiplier == 0) Print("Zero divide error at line 374!");
      dblUpperLimit  =  (dblOld_AlertPrice + (dblBuffer / dblMultiplier));
      dblLowerLimit  =  (dblOld_AlertPrice - (dblBuffer / dblMultiplier));
      
      UDF_DrawAlertBox(dteOld_AlertT1, dblUpperLimit, dteOld_AlertT2, dblLowerLimit);
      
      if(dblOld_MidPrice >= dblLowerLimit && dblOld_MidPrice <= dblUpperLimit && intAlertSent == 0){     
         UDF_ProcessAlerts();
         Print("Email alert sent!");
         intAlertSent   =  1;
      }
   } 
   if(!blnSendEmailAlert && ObjectFind("AlertZone") == 0){
      ObjectDelete("AlertZone");
   }
   
   return(0);
}

//*************************************************************************************************************|
//*************************************************************************************************************|
// Collection of user defined functions
//*************************************************************************************************************|
//*************************************************************************************************************|

//=============================================================================================================|
// UDF to set-up colour arrays 
//=============================================================================================================|
void  UDF_SetupColourSchemeArrays(){

   if(blnClassicColours == true){   // Check user input
      intBoxColourArraySize   =  ArraySize(A_clrClassicSet);           // check number of elements in the array
      intTextColourArraySize  =  ArraySize(A_clrClassicTextSet);  
      intFibColourArraySize   =  ArraySize(A_clrClassicFibs);                        
      //Print("Array size is: ",intArraySize);
      ArrayResize (A_clrColourArray,intBoxColourArraySize);
      ArrayResize (A_clrTextColourArray,intTextColourArraySize);
      ArrayResize (A_clrFibsColourArray,intFibColourArraySize);
      
      ArrayCopy   (A_clrColourArray,A_clrClassicSet,0,0,WHOLE_ARRAY); // Copy elements into empty array
      ArrayCopy   (A_clrTextColourArray,A_clrClassicTextSet,0,0,WHOLE_ARRAY);
      ArrayCopy   (A_clrFibsColourArray,A_clrClassicFibs,0,0,WHOLE_ARRAY);
      
      intSecDiagLineStyle  =  0;       // default line style for mid diagonals is dotted
      intMidDiagLineStyle  =  2;       // default line style for secondary diagonals is solid
      
      clr52          =  Navy; 
      clr50          =  DarkViolet;
      clr47          =  Green;
      clrPrimDiag    =  Goldenrod;
      clrSecRiseDiag =  SteelBlue;
      clrSecFallDiag =  Violet;
      clrMidRiseDiag =  Black;
      clrMidFallDiag =  Goldenrod;
 
   }else{
      if(blnClassicColours == false){
         intBoxColourArraySize   =  ArraySize(A_clrAlternateSet);     // check number of elements in the array
         intTextColourArraySize  =  ArraySize(A_clrAlternateTextSet);  
         intFibColourArraySize   =  ArraySize(A_clrAlternateFibs);                        
         //Print("Array size is: ",intArraySize);
         ArrayResize (A_clrColourArray,intBoxColourArraySize);
         ArrayResize (A_clrTextColourArray,intTextColourArraySize);
         ArrayResize (A_clrFibsColourArray,intFibColourArraySize);
         
         ArrayCopy   (A_clrColourArray,A_clrAlternateSet,0,0,WHOLE_ARRAY);
         ArrayCopy   (A_clrTextColourArray,A_clrAlternateSet,0,0,WHOLE_ARRAY);
         ArrayCopy   (A_clrFibsColourArray,A_clrAlternateFibs,0,0,WHOLE_ARRAY);
         
         intSecDiagLineStyle  =  0;       // default line style for secondary diagonals is solid
         intMidDiagLineStyle  =  2;       // default line style for mid diagonals is dotted
         
         clr52          =  MidnightBlue; 
         clr50          =  DarkSlateGray;
         clr47          =  MidnightBlue;
         clrPrimDiag    =  DarkSlateGray;
         clrSecRiseDiag =  Gray;
         clrSecFallDiag =  Gray;
         clrMidRiseDiag =  Gray;
         clrMidFallDiag =  Gray;
      }
   }  
}

//=============================================================================================================|
   /* UDF to check for the primary ICCE box objects - the left, right, upper and lower box line objects
   
      Returns: 1 if all of the 4 objects are found, otherwise...
               2 if some of the 4 objects are found but not all, else...
               3 if none of the objects are found 
   */
//=============================================================================================================|

int  UDF_FindICCEBox(){
   int  intFindBoxResult;
   if(ObjectFind(strLeftICCEMarker)  > -1 && ObjectFind(strRightICCEMarker) > -1 &&       
      ObjectFind(strUpperICCEMarker) > -1 && ObjectFind(strLowerICCEMarker) > -1){
      intFindBoxResult = 1;
   }else if(ObjectFind(strLeftICCEMarker)  > -1 || ObjectFind(strRightICCEMarker) > -1 || 
      ObjectFind(strUpperICCEMarker) > -1 || ObjectFind(strLowerICCEMarker) > -1){
      intFindBoxResult = 2;
   }else{
      Print("none of ICCE Box found!");                                                  
      intFindBoxResult = 3;
   }
   return(intFindBoxResult);  
}

//=============================================================================================================|
// UDF to find the middle bar of those displayed on the current chart 
//=============================================================================================================|
void UDF_FindMidBar(int intLBI, int intBIOC){
  
   intFirstVisibleBar      =  intLeftBarIndex - (intBarIncrementsOnChart -1);
      //Print("intFirstVisibleBar = ",intFirstVisibleBar);
      
   if(intFirstVisibleBar < 0){
      intRightBarIndex     =  ((intBarIncrementsOnChart + intFirstVisibleBar) - intLeftBarIndex) - 1;
      intMidBarIndex       =  (intLeftBarIndex - intRightBarIndex)/2;
   }else{
      intRightBarIndex     =  intFirstVisibleBar - 1;
      intMidBarIndex       =  intLeftBarIndex - (intBarIncrementsOnChart / 2);
   }
   
   intFibTextAnchor        =  intRightBarIndex +  intTextOffset; 
   dteLastTextAnchor       =  Time[intFibTextAnchor];
   
}

//=============================================================================================================|
// UDF to setup initial coordinates for primary ICCE objects 
/*
   Arguements: int intMidRef is the index number of the bar
   approximately in the middle of those displayed on the chart
*/
//=============================================================================================================|
void UDF_PrimaryObjectCoordinates(int intMidRef){
   int   intLeftMarker;
   int   intRightMarker;
   intLeftMarker           =  intMidRef + 4;
   intRightMarker          =  intMidRef - 4;
   
   dteLeftRefTime          =  Time[intLeftMarker];    //<<<<<<<<<<<<<<<
   dteRightRefTime         =  Time[intRightMarker];   //<<<<<<<<<<<<<<<
   dteLeftMarkerTime       =  dteLeftRefTime;    
   dteRightMarkerTime      =  dteRightRefTime;   
   intRange                =  (intLeftMarker - intRightMarker) + 1;
 
   dblHighestPrice         =  High[iHighest(NULL,0,MODE_HIGH,intRange,intRightMarker)];
   dblUpperMarkerPrice     =  dblHighestPrice;  //<<<<<<
   
   dblLowestPrice          =  Low[iLowest(NULL,0,MODE_LOW,intRange,intRightMarker)]; 
   dblLowerMarkerPrice     =  dblLowestPrice;   //<<<<<<
   dblMidPrice             =  ((dblLowerMarkerPrice + dblUpperMarkerPrice) / 2.0);  //<<<<
   dblCreationMarkerPrice  =  (dblMidPrice * 5); // Multiply to make marker out of view!  

}

//=============================================================================================================|
// UDF to update the primary ICCE box object coordinates
//=============================================================================================================|
void  UDF_UpdatePrimaryCoords(){
   
   int intLeftShift;
   int intRightShift;
   
   dteLeftRefTime    =  datetime(ObjectGet(strLeftICCEMarker,OBJPROP_TIME1));
   intLeftShift      =  iBarShift(NULL,0,dteLeftRefTime,true);
   if(intLeftShift < 0){
      intLeftShift  =  iBarShift(NULL,0,dteLeftRefTime,false);
   }
   dteLeftMarkerTime =  Time[intLeftShift];
   //Print("dteLeftMarkerTime @ init = ",TimeToStr(dteLeftMarkerTime,TIME_DATE|TIME_MINUTES));
   
   dteRightRefTime   =  datetime(ObjectGet(strRightICCEMarker,OBJPROP_TIME1));
   intRightShift     =  iBarShift(NULL,0,dteRightRefTime,true);
   if(intRightShift < 0){
      intRightShift  =  iBarShift(NULL,0,dteRightRefTime,false);
   }
   dteRightMarkerTime =  Time[intRightShift];
   //Print("dteRightMarkerTime @ init = ",TimeToStr(dteRightMarkerTime,TIME_DATE|TIME_MINUTES));
   
   dblUpperMarkerPrice  =  ObjectGet(strUpperICCEMarker,OBJPROP_PRICE1);
   dblLowerMarkerPrice  =  ObjectGet(strLowerICCEMarker,OBJPROP_PRICE1);
   dblMidPrice          =  ((dblLowerMarkerPrice + dblUpperMarkerPrice) / 2);
}

//=============================================================================================================|
// UDF to draw the primary ICCE box objects
//=============================================================================================================|
void  UDF_DrawPrimaryICCEobjects(bool blnStamp){

   ObjectCreate   (strLeftICCEMarker,  OBJ_VLINE, 0, dteLeftRefTime,0);                    // Create objects
   ObjectCreate   (strRightICCEMarker, OBJ_VLINE, 0, dteRightRefTime,0);
   ObjectCreate   (strUpperICCEMarker, OBJ_HLINE, 0, 0,dblUpperMarkerPrice);   
   ObjectCreate   (strLowerICCEMarker, OBJ_HLINE, 0, 0,dblLowerMarkerPrice); 
   ObjectCreate   (strMidICCEMarker,   OBJ_HLINE, 0, 0,dblMidPrice); 
   ObjectCreate   (strBoxFill,         OBJ_RECTANGLE, 0, dteLeftRefTime,
                  dblLowerMarkerPrice,dteRightRefTime,dblUpperMarkerPrice);
                 
   /* When the box is created an arrow type object will be created to store the time that the box is created.
      The name of the object in the object list is:- "DO NOT DELETE THIS OBJECT!!" It is located out of sight
      on the chart to help prevent accidental selection and deletion. If the box is moved, then a new object
      will be created with the new time stamp.
   */ 
   if(blnStamp){              
      datetime dteCreatedTime =  TimeLocal();
      int      intTF          =  Period(); 
      string   strTimeFrame;
      switch   (intTF){
         case  1     :  strTimeFrame   =  "1 minute"  ; break;
         case  5     :  strTimeFrame   =  "5 minute"  ; break;
         case  15    :  strTimeFrame   =  "15 minute" ; break;
         case  30    :  strTimeFrame   =  "30 minute" ; break;
         case  60    :  strTimeFrame   =  "1 hour"    ; break;
         case  240   :  strTimeFrame   =  "4 hour"    ; break;
         case  1440  :  strTimeFrame   =  "Daily"     ; break;
         case  10080 :  strTimeFrame   =  "Weekly"    ; break;
         case  43200 :  strTimeFrame   =  "Monthly"   ; break;
         default     :  Print("error in UDF_DrawPrimaryICCEobjects()"); break;
      }
         
      ObjectCreate   (strCreatedName,OBJ_ARROW,0,dteCreatedTime,dblCreationMarkerPrice);
      ObjectSet      (strCreatedName,OBJPROP_ARROWCODE,116);
      ObjectSet      (strCreatedName,OBJPROP_COLOR,clr50);
      ObjectSet      (strCreatedName,OBJPROP_BACK,true);
      ObjectSetText  (strCreatedName,strTimeFrame,8,fntFont,Red);
   }
  
   for(i=0; i<6; i++){
      ObjectSet      (A_strBoxObjects[i],OBJPROP_COLOR,A_clrColourArray[i]);  // Set the colour of the line...
      ObjectSet      (A_strBoxObjects[i],OBJPROP_WIDTH,A_intBoxObjWidths[i]); // Set the thickness of the line
      ObjectSet      (A_strBoxObjects[i],OBJPROP_BACK,true);                  // Send to back
   }                         
   WindowRedraw();
                   
}

//=============================================================================================================|
// UDF to draw the ICCE fib levels
//=============================================================================================================|
void  UDF_DrawICCE_FibLevelobjects(){
   
            dblBoxRange    =  (dblUpperMarkerPrice - dblLowerMarkerPrice);
   double   dblTotalRange  =  (dblBoxRange * dblBemacConstant);
   double   dblOnePercent  =  (dblTotalRange / 100.0);
   double   dblZeroPrice   =  (dblMidPrice - (50.0 * dblOnePercent));
   double   dblFibPrice    =  0.0;
   string   strFibName;
   color    clrFibColour;
   
   for(i = 0; i < intFibColourArraySize; i++){
      dblFibPrice    =  (dblZeroPrice + (A_dblICCEfibLevels[i] * dblOnePercent));
      strFibName     =  StringConcatenate(strFibPrefix,i);
      clrFibColour   =  A_clrFibsColourArray[i];
      
      ObjectCreate  (strFibName,OBJ_HLINE,0,0,dblFibPrice);
      ObjectSet     (strFibName,OBJPROP_COLOR,clrFibColour);
      ObjectSet     (strFibName,OBJPROP_WIDTH,1);
      
      A_dblICCEfibValues[i]   =  dblFibPrice;   // load prices into array for use later in creating lables  
   }
   WindowRedraw();

}

//=============================================================================================================|
// UDF to draw the ICCE fib level labels
//=============================================================================================================|

void  UDF_DrawFibLabels(){
   
   string   strLabelName;
   string   strLabelText;
   
   for(int j = 0; j < intFibColourArraySize; j++){
   
      strLabelName   =  StringConcatenate("IFLN:",j); // IFLN = ICCE fib level name - iterated names of labels
      strLabelText   =  StringConcatenate(DoubleToStr(A_dblICCEfibLevels[j],3),
                        "%  :  ",DoubleToStr(A_dblICCEfibValues[j],Digits));
                        
      ObjectCreate   (strLabelName,OBJ_TEXT,0,dteLastTextAnchor,A_dblICCEfibValues[j]);
      ObjectSetText  (strLabelName,strLabelText,intFontSize,fntFont,A_clrFibsColourArray[j]);
   } 
   
   ObjectCreate   ("UpperText",OBJ_TEXT,0,dteLastTextAnchor,dblUpperMarkerPrice);
   ObjectSetText  ("UpperText","TOP 52.79% " + DoubleToStr(dblUpperMarkerPrice,Digits),intFontSize,fntFont,clr52);
   
   ObjectCreate   ("LowerText",OBJ_TEXT,0,dteLastTextAnchor,dblLowerMarkerPrice);
   ObjectSetText  ("LowerText","BOT 47.21% " + DoubleToStr(dblLowerMarkerPrice,Digits),intFontSize,fntFont,clr47);
   
   ObjectCreate   ("MidText",OBJ_TEXT,0,dteLastTextAnchor,dblMidPrice);
   ObjectSetText  ("MidText","MID 50.00% " + DoubleToStr(dblMidPrice,Digits),intFontSize,fntFont,clr50);  
   WindowRedraw();
}

//=============================================================================================================|
// UDF to draw the primary diagonals
//=============================================================================================================|

void  UDF_DrawPrimaryDiagonals(){
   
   datetime dtePD_T1 = 0;
   datetime dtePD_T2 = 0;
   double   dblPD_P1 = 0.0;
   double   dblPD_P2 = 0.0;
   
   for(int x = 0; x < 4; x++){
      // setup the time coordinates for primary diagonals
      if(x == 0){
         dtePD_T1 =  dteLeftMarkerTime;   
         dtePD_T2 =  Time[intT2Marker - (intAccuracyFactor * intTimeRange)]; //<<<<<altered  
         dblPD_P1 =  dblLowerMarkerPrice;   
         dblPD_P2 =  (dblLowerMarkerPrice + ((intAccuracyFactor + 1) * dblBoxRange)); //<<<<<altered
      }
      if(x == 1){
         dtePD_T1 =  dteLeftMarkerTime;  
         dtePD_T2 =  Time[intT2Marker - (intAccuracyFactor * intTimeRange)]; //<<<<<altered 
         dblPD_P1 =  dblUpperMarkerPrice;   
         dblPD_P2 =  (dblUpperMarkerPrice - ((intAccuracyFactor + 1) * dblBoxRange)); //<<<<<altered
      }
      if(x == 2){
         dtePD_T1 =  dteRightMarkerTime;   
         dtePD_T2 =  Time[intT1Marker + (intAftAccuracyFactor * intTimeRange)]; //<<<<<altered 
         dblPD_P1 =  dblUpperMarkerPrice;   
         dblPD_P2 =  (dblUpperMarkerPrice - ((intAftAccuracyFactor + 1) * dblBoxRange)); //<<<<<altered
      }
      if(x == 3){
         dtePD_T1 =  dteRightMarkerTime;   
         dtePD_T2 =  Time[intT1Marker + (intAftAccuracyFactor * intTimeRange)]; //<<<<<altered  
         dblPD_P1 =  dblLowerMarkerPrice;   
         dblPD_P2 =  (dblLowerMarkerPrice + ((intAftAccuracyFactor + 1) * dblBoxRange)); //<<<<<altered
      }
      
      ObjectCreate(A_strPDobjNames[x],OBJ_TREND,0,dtePD_T1,dblPD_P1,dtePD_T2,dblPD_P2);
      ObjectSet   (A_strPDobjNames[x],OBJPROP_RAY,true);
      ObjectSet   (A_strPDobjNames[x],OBJPROP_COLOR,clrPrimDiag);
      ObjectSet   (A_strPDobjNames[x],OBJPROP_STYLE,STYLE_SOLID);
      ObjectSet   (A_strPDobjNames[x],OBJPROP_WIDTH,2);
      ObjectSet   (A_strPDobjNames[x],OBJPROP_BACK,true);
   }
   WindowRedraw();
}
//***************************************************************************************************************replacement



//***************************************************************************************************************replacement
//=============================================================================================================|
/* UDF to draw the secondary diagonals above the box
   
   Arguements:
   strNamePrefix  =  prefix to identify object group
   dteTime1       =  the first time coordidinate used for diagonals
   dblBasePrice1  =  the reference price level used for calculations of P1 coordinate
   dteTime2       =  the second time coordidinate used for diagonals
   dblBasePrice2  =  the reference price level used for calculations of P2 coordinate
   intLstyle      =  int value used to determine which linestyle to use
   intLwidth      =  int value used to determine which line width to use
   clrLcolour     =  name of colour to use
*/
//=============================================================================================================|
void  UDF_IncrementingLoop(string strNamePrefix,datetime dteTime1,double dblBasePrice1,datetime dteTime2,
                           double dblBasePrice2,int intLstyle,int intLwidth,color clrLcolour){
   
   for(int y = 0; y < intNumberOfDiagonals; y++){
      string   strDobjName =  StringConcatenate(strNamePrefix,y);
      ObjectCreate(strDobjName,OBJ_TREND,0,dteTime1,dblBasePrice1,dteTime2,dblBasePrice2);
      if(!blnDrawRaysOnDiagonals)ObjectSet(strDobjName,OBJPROP_RAY,false);
      ObjectSet   (strDobjName,OBJPROP_COLOR,clrLcolour);
      ObjectSet   (strDobjName,OBJPROP_STYLE,intLstyle);
      ObjectSet   (strDobjName,OBJPROP_WIDTH,intLwidth);
      ObjectSet   (strDobjName,OBJPROP_BACK,true); 
      
      dblBasePrice1 +=  dblBoxRange; 
      dblBasePrice2 +=  dblBoxRange;     
   }
   WindowRedraw();                        
}

//=============================================================================================================|
/* UDF to draw the secondary diagonals above the box
   
   Arguements:
   strNamePrefix  =  prefix to identify object group
   dteTime1       =  the first time coordidinate used for diagonals
   dblBasePrice1  =  the reference price level used for calculations of P1 coordinate
   dteTime2       =  the second time coordidinate used for diagonals
   dblBasePrice2  =  the reference price level used for calculations of P2 coordinate
   intLstyle      =  int value used to determine which linestyle to use
   intLwidth      =  int value used to determine which line width to use
   clrLcolour     =  name of colour to use
*/
//=============================================================================================================|
void  UDF_DecrementingLoop(string strNamePrefix,datetime dteTime1,double dblBasePrice1,datetime dteTime2,
                           double dblBasePrice2,int intLstyle,int intLwidth,color clrLcolour){
   
   for(int y = 0; y < intNumberOfDiagonals; y++){
      string   strDobjName =  StringConcatenate(strNamePrefix,y);
      ObjectCreate(strDobjName,OBJ_TREND,0,dteTime1,dblBasePrice1,dteTime2,dblBasePrice2);
      if(!blnDrawRaysOnDiagonals)ObjectSet(strDobjName,OBJPROP_RAY,false);
      ObjectSet   (strDobjName,OBJPROP_COLOR,clrLcolour);
      ObjectSet   (strDobjName,OBJPROP_STYLE,intLstyle);
      ObjectSet   (strDobjName,OBJPROP_WIDTH,intLwidth);
      ObjectSet   (strDobjName,OBJPROP_BACK,true); 
      
      dblBasePrice1 -=  dblBoxRange; 
      dblBasePrice2 -=  dblBoxRange;     
   }
   WindowRedraw();                        
}

//=============================================================================================================|
// use below to replace: UDF_DrawAllRisingSecondaryDiags()
//=============================================================================================================|

void  UDF_DrawBullishDiagonals(){
   
   datetime dteX1;   // first time coordinate
   datetime dteX2;   // second time coordinate
   double   dblY1;   // first price coordinate
   double   dblY2;   // second price coordinate
   int      intYindex;
   
   dteX1 =  dteLeftMarkerTime;
   intYindex   = (intT2Marker - (intAccuracyFactor * intTimeRange)); //<<<<<<<<<
   dteX2 =  Time[intYindex];
   dblY1 =  dblUpperMarkerPrice;
   dblY2 =  (dblY1 + ((intAccuracyFactor + 1) * dblBoxRange));
   UDF_IncrementingLoop(strSRDaF,dteX1,dblY1,dteX2,dblY2,intSecDiagLineStyle,1,clrSecRiseDiag); // "SRD:aF:"
   
   dteX1 =  dteRightMarkerTime;
   intYindex   = (intT1Marker + (intAftAccuracyFactor * intTimeRange));
   dteX2 =  Time[intYindex];
   dblY1 =  dblUpperMarkerPrice + dblBoxRange;
   dblY2 =  (dblY1 - ((intAftAccuracyFactor + 1) * dblBoxRange)); //**
   UDF_IncrementingLoop(strSRDaB,dteX1,dblY1,dteX2,dblY2,intSecDiagLineStyle,1,clrSecRiseDiag); // "SRD:aB:"
   
   dteX1 =  dteLeftMarkerTime;
   intYindex   = (intT2Marker - (intAccuracyFactor * intTimeRange));
   dteX2 =  Time[intYindex];
   dblY1 =  dblLowerMarkerPrice - dblBoxRange;
   dblY2 =  (dblY1 + ((intAccuracyFactor + 1) * dblBoxRange));
   UDF_DecrementingLoop(strSRDbF,dteX1,dblY1,dteX2,dblY2,intSecDiagLineStyle,1,clrSecRiseDiag); // "SRD:bF:"
   
   dteX1 =  dteRightMarkerTime;
   intYindex   = (intT1Marker + (intAftAccuracyFactor * intTimeRange));
   dteX2 =  Time[intT1Marker + (intAftAccuracyFactor * intTimeRange)];
   dblY1 =  dblLowerMarkerPrice;
   dblY2 =  (dblY1 - ((intAftAccuracyFactor + 1) * dblBoxRange)); //**
   UDF_DecrementingLoop(strSRDbB,dteX1,dblY1,dteX2,dblY2,intSecDiagLineStyle,1,clrSecRiseDiag); // "SRD:bB:" 
}

//=============================================================================================================|
// use below to replace: UDF_DrawAllRisingMidDiags()
//=============================================================================================================|
void  UDF_DrawBullishMidDiagonals(){
   
   datetime dteX1;   // first time coordinate
   datetime dteX2;   // second time coordinate
   double   dblY1;   // first price coordinate
   double   dblY2;   // second price coordinate
   int      intYindex;
   
   dteX1 =  dteLeftMarkerTime;
   intYindex   =  (intT2Marker - (intAccuracyFactor * intTimeRange));
   dteX2 =  Time[intYindex];
   dblY1 =  dblMidPrice;
   dblY2 =  (dblY1 + ((intAccuracyFactor + 1) * dblBoxRange));
   UDF_IncrementingLoop(strMRDaF,dteX1,dblY1,dteX2,dblY2,intMidDiagLineStyle,1,clrMidRiseDiag); // "MRD:aF:"
   
   dteX1 =  dteRightMarkerTime;
   intYindex   =  (intT1Marker + (intAftAccuracyFactor * intTimeRange));
   dteX2 =  Time[intYindex];
   dblY1 =  dblMidPrice + dblBoxRange;
   dblY2 =  (dblY1 - ((intAftAccuracyFactor + 1) * dblBoxRange)); //**
   UDF_IncrementingLoop(strMRDaB,dteX1,dblY1,dteX2,dblY2,intMidDiagLineStyle,1,clrMidRiseDiag); // "MRD:aB:"
   
   dteX1 =  dteLeftMarkerTime;
   intYindex   =  (intT2Marker - (intAccuracyFactor * intTimeRange));
   dteX2 =  Time[intYindex];
   dblY1 =  dblMidPrice - dblBoxRange;
   dblY2 =  (dblY1 + ((intAccuracyFactor + 1) * dblBoxRange));
   UDF_DecrementingLoop(strMRDbF,dteX1,dblY1,dteX2,dblY2,intMidDiagLineStyle,1,clrMidRiseDiag); // "MRD:bF:"
   
   dteX1 =  dteRightMarkerTime;
   intYindex   =  (intT1Marker + (intAftAccuracyFactor * intTimeRange));
   dteX2 =  Time[intYindex];
   dblY1 =  dblMidPrice;
   dblY2 =  (dblY1 - ((intAftAccuracyFactor + 1) * dblBoxRange)); //**
   UDF_DecrementingLoop(strMRDbB,dteX1,dblY1,dteX2,dblY2,intMidDiagLineStyle,1,clrMidRiseDiag); // "MRD:bB:"
   
}

//=============================================================================================================|
// use below to replace: UDF_DrawAllFallingSecondaryDiag()
//=============================================================================================================|
void  UDF_DrawBearishDiagonals(){
   
   datetime dteX1;   // first time coordinate
   datetime dteX2;   // second time coordinate
   double   dblY1;   // first price coordinate
   double   dblY2;   // second price coordinate
   
   dteX1 =  dteRightMarkerTime;
   dteX2 =  Time[intT1Marker + (intAftAccuracyFactor * intTimeRange)];
   dblY1 =  dblUpperMarkerPrice;
   dblY2 =  (dblY1 + ((intAftAccuracyFactor + 1) * dblBoxRange));//**
   UDF_IncrementingLoop(strSFDaB,dteX1,dblY1,dteX2,dblY2,intSecDiagLineStyle,1,clrSecFallDiag); // "SFD:aB:"
   
   dteX1 =  dteLeftMarkerTime;
   dteX2 =  Time[intT2Marker - (intAccuracyFactor * intTimeRange)];
   dblY1 =  dblUpperMarkerPrice + dblBoxRange;
   dblY2 =  (dblY1 - ((intAccuracyFactor + 1) * dblBoxRange));
   UDF_IncrementingLoop(strSFDaF,dteX1,dblY1,dteX2,dblY2,intSecDiagLineStyle,1,clrSecFallDiag); // "SFD:aF:"
   
   dteX1 =  dteRightMarkerTime;
   dteX2 =  Time[intT1Marker + (intAftAccuracyFactor * intTimeRange)];
   dblY1 =  dblLowerMarkerPrice - dblBoxRange;
   dblY2 =  (dblY1 + ((intAftAccuracyFactor + 1) * dblBoxRange));
   UDF_DecrementingLoop(strSFDbB,dteX1,dblY1,dteX2,dblY2,intSecDiagLineStyle,1,clrSecFallDiag); // "SFD:bB:"
   
   dteX1 =  dteLeftMarkerTime;
   dteX2 =  Time[intT2Marker - (intAccuracyFactor * intTimeRange)];
   dblY1 =  dblLowerMarkerPrice;
   dblY2 =  (dblY1 - ((intAccuracyFactor + 1) * dblBoxRange));
   UDF_DecrementingLoop(strSFDbF,dteX1,dblY1,dteX2,dblY2,intSecDiagLineStyle,1,clrSecFallDiag); // "SFD:bF:" 
}

//=============================================================================================================|
// use below to replace: UDF_DrawAllFallingMidDiag()
//=============================================================================================================|
void  UDF_DrawBearishMidDiagonals(){
   
   datetime dteX1;   // first time coordinate
   datetime dteX2;   // second time coordinate
   double   dblY1;   // first price coordinate
   double   dblY2;   // second price coordinate
   
   dteX1 =  dteRightMarkerTime;
   dteX2 =  Time[intT1Marker + (intAftAccuracyFactor * intTimeRange)];
   dblY1 =  dblMidPrice;
   dblY2 =  (dblY1 + ((intAftAccuracyFactor + 1) * dblBoxRange)); //**
   UDF_IncrementingLoop(strMFDaB,dteX1,dblY1,dteX2,dblY2,intMidDiagLineStyle,1,clrMidFallDiag); // "MFD:aB:"
   
   dteX1 =  dteLeftMarkerTime;
   dteX2 =  Time[intT2Marker - (intAccuracyFactor * intTimeRange)];
   dblY1 =  dblMidPrice + dblBoxRange;
   dblY2 =  (dblY1 - ((intAccuracyFactor + 1) * dblBoxRange));
   UDF_IncrementingLoop(strMFDaF,dteX1,dblY1,dteX2,dblY2,intMidDiagLineStyle,1,clrMidFallDiag); // "MFD:aF:"
   
   dteX1 =  dteRightMarkerTime;
   dteX2 =  Time[intT1Marker + (intAftAccuracyFactor * intTimeRange)];
   dblY1 =  dblMidPrice - dblBoxRange;
   dblY2 =  (dblY1 + ((intAftAccuracyFactor + 1) * dblBoxRange)); //**
   UDF_DecrementingLoop(strMFDbB,dteX1,dblY1,dteX2,dblY2,intMidDiagLineStyle,1,clrMidFallDiag); // "MFD:bB:"
   
   dteX1 =  dteLeftMarkerTime;
   dteX2 =  Time[intT2Marker - (intAccuracyFactor * intTimeRange)];
   dblY1 =  dblMidPrice;
   dblY2 =  (dblY1 - ((intAccuracyFactor + 1) * dblBoxRange)); //**
   UDF_DecrementingLoop(strMFDbF,dteX1,dblY1,dteX2,dblY2,intMidDiagLineStyle,1,clrMidFallDiag); // "MFD:bF:"
  
}

//================================================================================================================================================
   /* UDF to create label objects for the ICCE info
   
      Arguements:
      clrText_Colour    =  the colour selected by user
      intText_Corner    =  the corner to display the text
      intText_X         =  the X coordinate of the label
      intText_Y         =  the Y coordinate of the label
      intText_Space     =  an integer value to set the spacing between labels
      intText_Size      =  an integer value to set the font size
   */
//================================================================================================================================================

void  UDF_DisplayText(color clrText_Colour, int intText_Corner,
                      int intText_X,int intText_Y,
                      int intText_Space, int intText_Size){
                      
   for(int a = 0; a < ArraySize(A_strInfoBoxObjects); a++){
      //Print("name = ",A_strInfoBoxObjects[a]);
      ObjectCreate(A_strInfoBoxObjects[a],OBJ_LABEL,0,0,0);
      ObjectSet   (A_strInfoBoxObjects[a],OBJPROP_XDISTANCE, intText_X);
      ObjectSet   (A_strInfoBoxObjects[a],OBJPROP_YDISTANCE, (intText_Y +(intText_Space * a)));
      ObjectSet   (A_strInfoBoxObjects[a],OBJPROP_CORNER, intText_Corner);
      ObjectSet   (A_strInfoBoxObjects[a],OBJPROP_COLOR, clrText_Colour);
   }                   
   
   WindowRedraw();
}
//=============================================================================================================|
// UDF to set-up information box
//=============================================================================================================|
void  UDF_ICCEinfoBox(){
   string   strCreatedDate;
   string   strPTR;        // Price time ratio
   string   strEmailStatus;
   string   strWatchObject;
   string   strMasterTime;
   int      intRightShift; 
   int      intLeftShift;  
   int      intShiftResult;
   
   intRightShift  =  iBarShift(NULL,0,dteRightMarkerTime,true);
   intLeftShift   =  iBarShift(NULL,0,dteLeftMarkerTime,true);
   intShiftResult =  intLeftShift - intRightShift;
   if(intShiftResult == 0) Print("Zero divide error at line 1025!");
   strCreatedDate =  StringConcatenate("Box created at : ",
                                       TimeToStr(datetime(ObjectGet(strCreatedName,OBJPROP_TIME1)),
                                       TIME_DATE|TIME_MINUTES));
   if(intShiftResult == 0){
      strPTR   =  "Pips/time      : Unable to process!";
   }
   if(intShiftResult != 0){                               
      strPTR   =  StringConcatenate("Pips/time      : ",
                  DoubleToStr((dblMultiplier * (dblBoxRange /intShiftResult)),2));
   }
   if(blnSendEmailAlert){
      strEmailStatus =  "Email alert is : On";
      strWatchObject =  StringConcatenate("Monitor object : ",strObjectToMonitor);
   }else{
      strEmailStatus       =  "Email alert is : Off";
      strWatchObject       =  "+--------------------+";
   }
   strMasterTime  =  StringConcatenate("Master chart   : ",ObjectDescription(strCreatedName));
   ObjectSetText(A_strInfoBoxObjects[0],"ICCE BOX INFORMATION"+strVersion,intTextFontSize,fntFont,clrTextColour); 
   ObjectSetText(A_strInfoBoxObjects[1],strMasterTime,intTextFontSize,fntFont,clrTextColour);                                                          
   ObjectSetText(A_strInfoBoxObjects[2],strCreatedDate,intTextFontSize,fntFont,clrTextColour);
   ObjectSetText(A_strInfoBoxObjects[3],strPTR,intTextFontSize,fntFont,clrTextColour);
   ObjectSetText(A_strInfoBoxObjects[4],strEmailStatus,intTextFontSize,fntFont,clrTextColour);
   ObjectSetText(A_strInfoBoxObjects[5],strWatchObject,intTextFontSize,fntFont,clrTextColour);
   //Print("strCreatedDate: ",strCreatedDate); 
}

//=============================================================================================================|
// UDF to deal with email alerts
//=============================================================================================================|
void  UDF_ProcessAlerts(){
   string   strSubject;
   string   strBody;
   string   strChart;
   int      intChartPeriod;
   intChartPeriod =  Period();
   
   switch   (intChartPeriod){
      case  1     :  strChart   =  "1 minute"  ; break;
      case  5     :  strChart   =  "5 minute"  ; break;
      case  15    :  strChart   =  "15 minute" ; break;
      case  30    :  strChart   =  "30 minute" ; break;
      case  60    :  strChart   =  "1 hour"    ; break;
      case  240   :  strChart   =  "4 hour"    ; break;
      case  1440  :  strChart   =  "Daily"     ; break;
      case  10080 :  strChart   =  "Weekly"    ; break;
      case  43200 :  strChart   =  "Monthly"   ; break;
      default     :  Print("error in UDF_ProcessAlerts()"); break;
   }
   
   string   strAlertTime   =  TimeToStr(TimeLocal(),TIME_DATE|TIME_MINUTES);
   string   strYear        =  StringSubstr(strAlertTime,0,4);
   string   strDay         =  StringSubstr(strAlertTime,5,2);
   string   strMonth       =  StringSubstr(strAlertTime,8,2);
   string   strHour        =  StringSubstr(strAlertTime,11,2);
   string   strMinute      =  StringSubstr(strAlertTime,14,2);
   
   strSubject  =  "Alert from ICCE indicator";
   strBody     =  StringConcatenate("Symbol : ",Symbol(),"\r\n\r\n",
                                    "Chart  : ",strChart,"\r\n\r\n",
                                    "Price has entered your monitoring zone at ",
                                    strYear,":",strDay,":",strMonth,"_",strHour,":",strMinute);
   SendMail(strSubject,strBody);
}

//=============================================================================================================|
/* UDF to draw alert box 
   
      Arguements:
      datetime    dteAT1    =  time 1 coordinate
      datetime    dteAT2    =  time 2 coordinate
      double      dblAP1    =  price 1 coordinate
      double      dblAP2    =  price 2 coordinate
*/
//=============================================================================================================|
void  UDF_DrawAlertBox(datetime  dteAT1, double dblAP1, datetime  dteAT2, double dblAP2){

   string   strAlertName   = "AlertZone"; 
   
   ObjectCreate(strAlertName,OBJ_RECTANGLE,0,dteAT1,dblAP1,dteAT2,dblAP2);
   ObjectSet   (strAlertName,OBJPROP_COLOR,clrAlertColour);
   ObjectSet   (strAlertName,OBJPROP_BACK,true);
   ObjectSetText(strAlertName,"EAZ");
   WindowRedraw();
}

//=============================================================================================================|
// UDF to clear up ICCE objects 
//=============================================================================================================|
void  UDF_ClearICCEobjects(){
   UDF_DeleteICCEfibs();
   UDF_DeleteICCEfibLabels();
   UDF_DeleteICCEBox();
   UDF_DeleteICCEBoxLabels();
   UDF_DeletePrimaryDiag();
   UDF_DeleteSecondaryRisingDiag();
   UDF_DeleteSecondaryFallingDiag();
   UDF_DeleteMidRisingDiag();
   UDF_DeleteMidFallingDiag();
}

//=============================================================================================================|
// UDF to delete the ICCE fib levels
//=============================================================================================================|
void  UDF_DeleteICCEfibs(){

   intObjTotal =  ObjectsTotal() ;                       // Find all objects

   for(int k = intObjTotal; k >=0; k--){                 // Start for loop
      strObjRef   =  ObjectName(k);                      // Define object
      if(StringSubstr(strObjRef,0,4) == "IFL:"){         // If it contains: "IFL:" characters then...
         ObjectDelete(strObjRef);                        // Delete it         
      }                                                  // end if
   }  
   WindowRedraw();
}

//=============================================================================================================|
// UDF to delete the ICCE fib labels
//=============================================================================================================|

void  UDF_DeleteICCEfibLabels(){

   intObjTotal =  ObjectsTotal();                        // Find all objects

   for(int l = intObjTotal; l >=0; l--){                 // Start for loop
      strObjRef   =  ObjectName(l);                      // Define object
      if(StringSubstr(strObjRef,0,5) == "IFLN:"){        // If it contains: "IFLN:" characters then...
         ObjectDelete(strObjRef);                        // Delete it         
      }                                                  // end if
   }  
   WindowRedraw();
}

//=============================================================================================================|
// UDF to delete the primary ICCE box objects
//=============================================================================================================|

void  UDF_DeleteICCEBox(){

   ObjectDelete(strLeftICCEMarker);
   ObjectDelete(strRightICCEMarker);
   ObjectDelete(strUpperICCEMarker);
   ObjectDelete(strLowerICCEMarker);
   ObjectDelete(strMidICCEMarker);
   ObjectDelete(strBoxFill );  
}

//=============================================================================================================|
// UDF to delete the primary ICCE box labels
//=============================================================================================================|

void  UDF_DeleteICCEBoxLabels(){

   ObjectDelete("UpperText");
   ObjectDelete("LowerText");
   ObjectDelete("MidText");   
}

//=============================================================================================================|
// UDF to delete the ICCE time stamp object
//=============================================================================================================|
void  UDF_DeleteTimeStamp(){
   ObjectDelete(strCreatedName);
}

//=============================================================================================================|
// UDF to delete the ICCE primary diagonal objects
//=============================================================================================================|
void  UDF_DeletePrimaryDiag(){
   for(int y = 0; y < 4; y++){
      ObjectDelete(A_strPDobjNames[y]);
   } 
}

//=============================================================================================================|
// UDF to delete the secondary rising diagonal objects
//=============================================================================================================|
void  UDF_DeleteSecondaryRisingDiag(){
   intObjTotal =  ObjectsTotal() ;                       // Find all objects
   
   for(int j = intObjTotal; j >=0; j--){                 // Start for loop
      strObjRef   =  ObjectName(j);                      // Define object
      if(StringSubstr(strObjRef,0,3) == "SRD"){          // If it contains: "SRD" characters then...
         ObjectDelete(strObjRef);                        // Delete it         
      }                                                  // end if
   }  
   WindowRedraw(); 
}

//=============================================================================================================|
// UDF to delete the secondary falling diagonal objects
//=============================================================================================================|
void  UDF_DeleteSecondaryFallingDiag(){
   intObjTotal =  ObjectsTotal() ;                       // Find all objects
   
   for(int j = intObjTotal; j >=0; j--){                 // Start for loop
      strObjRef   =  ObjectName(j);                      // Define object
      if(StringSubstr(strObjRef,0,3) == "SFD"){          // If it contains: "SFD" characters then...
         ObjectDelete(strObjRef);                        // Delete it         
      }                                                  // end if
   }  
   WindowRedraw(); 
}

//=============================================================================================================|
// UDF to delete the mid rising diagonal objects
//=============================================================================================================|
void  UDF_DeleteMidRisingDiag(){
   intObjTotal =  ObjectsTotal() ;                       // Find all objects
                                                         // Store object name

   for(int j = intObjTotal; j >=0; j--){                 // Start for loop
      strObjRef   =  ObjectName(j);                      // Define object
      if(StringSubstr(strObjRef,0,3) == "MRD"){          // If it contains: "MRD" characters then...
         ObjectDelete(strObjRef);                        // Delete it         
      }                                                  // end if
   }  
   WindowRedraw(); 
}

//=============================================================================================================|
// UDF to delete the MID falling diagonal objects
//=============================================================================================================|
void  UDF_DeleteMidFallingDiag(){
   intObjTotal =  ObjectsTotal() ;                       // Find all objects
   
   for(int j = intObjTotal; j >=0; j--){                 // Start for loop
      strObjRef   =  ObjectName(j);                      // Define object
      if(StringSubstr(strObjRef,0,3) == "MFD"){          // If it contains: "SFD" characters then...
         ObjectDelete(strObjRef);                        // Delete it         
      }                                                  // end if
   }  
   WindowRedraw(); 
}

//=============================================================================================================|
// UDF to delete the ICCE box info' labels
//=============================================================================================================|

void  UDF_DeleteICCEBoxInfoLabels(){

   ObjectDelete(A_strInfoBoxObjects[0]);
   ObjectDelete(A_strInfoBoxObjects[1]);
   ObjectDelete(A_strInfoBoxObjects[2]);   
   ObjectDelete(A_strInfoBoxObjects[3]);  
   ObjectDelete(A_strInfoBoxObjects[4]);
   ObjectDelete(A_strInfoBoxObjects[5]);    
}

//=============================================================================================================|
// UDF to adjust the time coordinate accuracy of trendlines to the right of the box
//=============================================================================================================|

void  UDF_TimeCoordAccuracy(int intBoxTimeRange){
   int intBoxRight   =  iBarShift(NULL,0,dteRightMarkerTime,true);
   intAccuracyFactor =  int(MathFloor(Divide(intBoxRight, intBoxTimeRange)));
}

//=============================================================================================================|
// UDF to adjust the time coordinate accuracy of trendlines to the left of the box
//=============================================================================================================|

void  UDF_AftTimeCoordAccuracy(int intBoxTimeRange){
   int intBoxLeft       =  iBarShift(NULL,0,dteLeftMarkerTime,true);
   intAftAccuracyFactor =  int(MathFloor(Divide(((Bars - 1) - intBoxLeft), intBoxTimeRange)));
   // place a limit on how far back to adjust, as the value is used for price levels also
   if(intAftAccuracyFactor > 10) intAftAccuracyFactor =  10;  
}
//=============================================================================================================|
// Zero divide issue quick and dirty workaround
//=============================================================================================================|

double Divide(double n, double d) {
	if(d == 0.0) return 0.0;
	return n / d;
}
//=============================================================================================================|