MTF_live_automarkup1.99

Author: Copyright 2011-2012, 2020-2022, x572intraday
0 Views
0 Downloads
0 Favorites
MTF_live_automarkup1.99
//+--------------------------------------------------------------------------+
//|                                              MTF_live_automarkup1.99.mq5 |
//|                             Copyright 2011-2012, 2020-2022, x572intraday |
//|                                                      http://www.mql5.com |
//+--------------------------------------------------------------------------+
#property copyright "Copyright 2011-2012, 2020-2022, x572intraday"
#property link      "https://www.mql5.com"
#property version   "1.99"

#define NUMBER 42

#property indicator_chart_window
#property indicator_buffers NUMBER
#property indicator_plots   NUMBER

struct TBuffer
  {
   double PrepsBuffer[];
   datetime PrepTimesBuffer[];
   double FractalsBuffer[];
   double PriceExtremum[4][2];
   datetime TimeExtremum[4][2];
   int handle;
   int values_to_copy;
   int calculated;
   int bars_calculated;
   int waiting_for_loading_history_msg_counter;
  };

TBuffer Buffer_Array[NUMBER];

enum FIBO_TIME_ZONES
  {
   LEVEL0=5,   // 0, 1, 2, 3, 5               
   LEVEL1=8,   // 0, 1, 2, 3, 5, 8            
   LEVEL2=13,  // 0, 1, 2, 3, 5, 8, 13        
   LEVEL3=21,  // 0, 1, 2, 3, 5, 8, 13, 21    
   LEVEL4=34,  // 0, 1, 2, 3, 5, 8, 13, 21, 34
  };

enum SHIFT
  {
   SH0=0,   // 0 TIMEFRAMES to the left
   SH1=1,   // 1 TIMEFRAME to the left
   SH2=2,   // 2 TIMEFRAMES to the left
   SH3=3,   // 3 TIMEFRAMES to the left
   SH4=4,   // 4 TIMEFRAMES to the left
   SH5=5,   // 5 TIMEFRAMES to the left
   SH6=6,   // 6 TIMEFRAMES to the left
   SH7=7,   // 7 TIMEFRAMES to the left
   SH8=8,   // 8 TIMEFRAMES to the left
  };

input string section1="—————————————————————";
input bool TIMEFRAME_01=false; // 15 Minutes
input bool TIMEFRAME_02=false; // 20 Minutes
input bool TIMEFRAME_03=false; // 30 Minutes
input bool TIMEFRAME_04=false; // Hourly
input bool TIMEFRAME_05=true;  // 2 Hours
input bool TIMEFRAME_06=true;  // 3 Hours
input bool TIMEFRAME_07=true;  // 4 Hours
input bool TIMEFRAME_08=true;  // 6 Hours
input bool TIMEFRAME_09=true;  // 8 Hours
input bool TIMEFRAME_10=true;  // 12 Hours
input bool TIMEFRAME_11=true;  // Daily
input bool TIMEFRAME_12=true;  // Weekly
input bool TIMEFRAME_13=true;  // Monthly
input bool TIMEFRAME_14=true;  // 2 Months
input bool TIMEFRAME_15=true;  // 3 Months
input bool TIMEFRAME_16=true;  // 4 Months
input bool TIMEFRAME_17=true;  // 6 Months
input bool TIMEFRAME_18=true;  // Yearly
input bool TIMEFRAME_19=true;  // 2 Years
input bool TIMEFRAME_20=true;  // 4 Years
input bool TIMEFRAME_21=true;  // 5 Years
input string section2="—————————————————————";
input ushort BarsCount=120;
input bool RenderFractals=true;
input bool EachOtherArrows=false;
input bool MinorTFsFractalFilter=true;
input bool BuildMinorTFsMarkup=true;
input bool BuildMajorTFsMarkup=true;
input bool MarkingUpOnlyTheCurrentTF=false;
input bool Build_FiboTimeZones=true;
input bool Build_AndrewsPitchforks=true;
input bool Build_EquidistantChannels=false;
input bool Build_FiboChannels=false;
input bool RayRight=true;
input bool Restrict_FiboTimeZones=false;
input FIBO_TIME_ZONES NumberOfFiboTimeZonesLevels=LEVEL4;
input double ChannelAndPitchforkTopicality=9.6;
input SHIFT NativeTFVisibilityShift=SH6;
input bool RemoveOutdatedObjects=true;
input bool EraseTheMarkupAtRemovingTheIndicator=true;
input string section3="—————————————————————";
input bool EventLogging=true;
bool AccuracyOfCalculations=true;

//+------------------------------------------------------------------+
//| Initialization of global arrays and variables                    |
//+------------------------------------------------------------------+
ENUM_TIMEFRAMES GraphObjTFsVisibility[];
ENUM_TIMEFRAMES IncludedTFs[NUMBER/2];
ENUM_TIMEFRAMES ExcludedTFs[];
string IncludedVHTFs[8]={"PERIOD_MN2","PERIOD_MN3", // Virtual hypertimeframes
                         "PERIOD_MN4","PERIOD_MN6",
                         "PERIOD_Y1","PERIOD_Y2",
                         "PERIOD_Y4","PERIOD_Y5"};
uchar VHPERIODS[8]={2,3,4,6,12,24,48,60};
int tf_delta=ArraySize(IncludedTFs)-ArraySize(IncludedVHTFs);
ENUM_OBJECT ObjectsId[4]={OBJ_FIBOTIMES,OBJ_PITCHFORK,OBJ_CHANNEL,OBJ_FIBOCHANNEL};
string obj_short_names[4]={"F TZ","A Pf","Eq Ch","F Ch"};
string obj_full_names[4]={"Fibo TimeZone","Andrew's Pitchfork",
                          "Equidistant Channel","Fibo Channel"};

color ClrArray1[NUMBER/2]={0x444444,0x616161,0x485147,
                           0x334432,0x3c5c3b,0x3f683d,
                           0x41733f,0x418e3e,0x379f33,
                           0x31ab2b,0x30a774,0x24bd96,
                           0x18d3b8,0x00d1ff,0x23d9fe,
                           0x4fe3fc,0x3deefc,0x1efffd,
                           0x66fcfb,0xbefefd,0xffffff};

color ClrArray2[NUMBER/2]={0x590304,0x622a04,0x783c00,
                           0x8b5100,0xaa6f00,0xb07801,
                           0xb47e01,0xbd8d02,0xc58b02,
                           0xcd8801,0xda8300,0xe77800,
                           0xf46c00,0xff6b59,0xff7165,
                           0xff7874,0xff848c,0xff9db6,
                           0xffd8e2,0xfff5f8,0xffffff};

color ClrArray3[NUMBER/2]={0x4c586c,0x576983,0x5c718f,
                           0x637c9f,0x6784a9,0x6c97aa,
                           0x70a3ab,0x75b5ac,0x78c1ad,
                           0x87cab9,0x96d2c4,0xa5dbcf,
                           0xb6e5dd,0xbce6e1,0xc4e8e7,
                           0xcae9eb,0xd2eaf0,0xdaeef3,
                           0xe6f3f7,0xf0f8fa,0xffffff};

color ClrAuxArray[NUMBER/2]={0x030359,0x040462,0x000078,
                             0x000084,0x00008b,0x0000aa,
                             0x0000bc,0x0000c8,0x0000d2,
                             0x0000da,0x0000e7,0x0000f4,
                             0x432ffa,0x7855ff,0x9462ff,
                             0xaf6eff,0xc86cff,0xe469ff,
                             0xfb7bd6,0xff69ab,0xff368e};

bool Buildings[4]={Build_FiboTimeZones,Build_AndrewsPitchforks,
                   Build_EquidistantChannels,Build_FiboChannels};
double Topicality[2]={NumberOfFiboTimeZonesLevels,ChannelAndPitchforkTopicality};
uchar DefaultFTZLevels[9]={0,1,2,3,5,8,13,21,34};
double exact_extremum[];
double SAGvar;
uint obj_counter=0;
uint additional_history_loading_msg_counter=0;
bool areBuiltFTZ;
bool isBuiltAPfOrEqChOrFCh;
int SymbolLength=StringLen(_Symbol);
uchar MaxSymbLength=14;
string unique_sign="A";
uchar start='A';
uchar end='G';

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   for(uchar iGvarName=0; iGvarName<GlobalVariablesTotal(); iGvarName++)
   {
      string GvarName=GlobalVariableName(iGvarName);

      if(GvarName==_Symbol+" "+unique_sign+": SingleActuation")
      {
         for(uchar letter=start; letter<=end+1; letter++)
         {
            if(unique_sign!=CharToString(letter))
            {
               unique_sign=CharToString(letter);
               start++;

               if(GlobalVariableCheck(_Symbol+" "+CharToString((uchar)(letter-1))+": "+(string)ChartID()))
                  unique_sign=CharToString(--letter);
               break;
            }
         }
      }
      else
         if(StringSubstr(GvarName,0,SymbolLength+1)==_Symbol+" " &&
            StringSubstr(GvarName,SymbolLength+4,18)==(string)ChartID())
         {
            unique_sign=CharToString(++start);

            if(StringSubstr(GvarName,SymbolLength+1,1)!=unique_sign)
               unique_sign=StringSubstr(GvarName,SymbolLength+1,1);
            break;
         }
   }

   if(unique_sign!=CharToString(start) || (start>=end+1 && unique_sign==CharToString(start) &&
                                           GlobalVariableCheck(_Symbol+" "+unique_sign+": "+(string)ChartID())))
      start--;

   Comment("{",unique_sign,"}");
// --------------------------------------------------------------------------------------------------------------
   for(ushort i=1, c=0; i<=PERIOD_MN1; i++)
      if(StringFind(EnumToString((ENUM_TIMEFRAMES)i),"PERIOD_",0)==0)
      {
         ArrayResize(GraphObjTFsVisibility,c+1);
         GraphObjTFsVisibility[c++]=(ENUM_TIMEFRAMES)i;
      }

   int orig_GraphObjTFsVisibility_size=ArraySize(GraphObjTFsVisibility);
   for(uchar vhi=0; vhi<ArraySize(IncludedVHTFs); vhi++)
   {
      ArrayResize(GraphObjTFsVisibility,orig_GraphObjTFsVisibility_size+vhi+1);
      GraphObjTFsVisibility[orig_GraphObjTFsVisibility_size+vhi]=PERIOD_MN1;
   }
   int skipped_tfs=ArraySize(GraphObjTFsVisibility)-ArraySize(IncludedTFs);
// --------------------------------------------------------------------------------------------------------------
   if(MarkingUpOnlyTheCurrentTF)
   {
      for(uchar p=0; p<ArraySize(IncludedTFs); p++)
         if(IncludedTFs[p])
         {
            string tf_type=p<tf_delta ? StringSubstr(EnumToString(IncludedTFs[p]),7) :
                                        StringSubstr(IncludedVHTFs[p-tf_delta],7);
            ObjectsDeleteAll(0,tf_type+": ",0,-1);
         }

      for(uchar p=0; p<ArraySize(GraphObjTFsVisibility); p++)
      {
         if(NativeTFVisibilityShift<=skipped_tfs &&
            _Period==GraphObjTFsVisibility[p] &&
            _Period>=GraphObjTFsVisibility[skipped_tfs-NativeTFVisibilityShift] &&
            _Period<=GraphObjTFsVisibility[ArraySize(GraphObjTFsVisibility)-1-NativeTFVisibilityShift])
         {
            IncludedTFs[p-skipped_tfs+NativeTFVisibilityShift]=GraphObjTFsVisibility[p+NativeTFVisibilityShift];
            break;
         }
         else
            if(_Period<GraphObjTFsVisibility[skipped_tfs-NativeTFVisibilityShift] ||
               _Period>GraphObjTFsVisibility[ArraySize(GraphObjTFsVisibility)-1-NativeTFVisibilityShift] ||
               (!Build_FiboTimeZones && !Build_AndrewsPitchforks &&
                !Build_EquidistantChannels && !Build_FiboChannels))
            {
               if(EventLogging)
                  Print("{",unique_sign,"} ",StringSubstr(EnumToString(_Period),7)+": nothing to display.");
               break;
            }
      }
   }
   else
   {
      IncludedTFs[0]= (ENUM_TIMEFRAMES)TIMEFRAME_01;
      IncludedTFs[1]= (ENUM_TIMEFRAMES)TIMEFRAME_02;
      IncludedTFs[2]= (ENUM_TIMEFRAMES)TIMEFRAME_03;
      IncludedTFs[3]= (ENUM_TIMEFRAMES)TIMEFRAME_04;
      IncludedTFs[4]= (ENUM_TIMEFRAMES)TIMEFRAME_05;
      IncludedTFs[5]= (ENUM_TIMEFRAMES)TIMEFRAME_06;
      IncludedTFs[6]= (ENUM_TIMEFRAMES)TIMEFRAME_07;
      IncludedTFs[7]= (ENUM_TIMEFRAMES)TIMEFRAME_08;
      IncludedTFs[8]= (ENUM_TIMEFRAMES)TIMEFRAME_09;
      IncludedTFs[9]= (ENUM_TIMEFRAMES)TIMEFRAME_10;
      IncludedTFs[10]=(ENUM_TIMEFRAMES)TIMEFRAME_11;
      IncludedTFs[11]=(ENUM_TIMEFRAMES)TIMEFRAME_12;
      IncludedTFs[12]=(ENUM_TIMEFRAMES)TIMEFRAME_13;
      IncludedTFs[13]=(ENUM_TIMEFRAMES)TIMEFRAME_14;
      IncludedTFs[14]=(ENUM_TIMEFRAMES)TIMEFRAME_15;
      IncludedTFs[15]=(ENUM_TIMEFRAMES)TIMEFRAME_16;
      IncludedTFs[16]=(ENUM_TIMEFRAMES)TIMEFRAME_17;
      IncludedTFs[17]=(ENUM_TIMEFRAMES)TIMEFRAME_18;
      IncludedTFs[18]=(ENUM_TIMEFRAMES)TIMEFRAME_19;
      IncludedTFs[19]=(ENUM_TIMEFRAMES)TIMEFRAME_20;
      IncludedTFs[20]=(ENUM_TIMEFRAMES)TIMEFRAME_21;

      for(uchar i=0; i<ArraySize(IncludedTFs); i++)
         if(IncludedTFs[i])
            IncludedTFs[i]=GraphObjTFsVisibility[i+skipped_tfs];

      if(EventLogging)
      {
         int p;
         string sum_of_excluded_tfs;
         string sum_of_excluded_vhtfs;

         for(p=ArraySize(IncludedTFs)-1; p>=0; p--)
            if(IncludedTFs[p])
               break;

         for(uchar iGvarName=0; iGvarName<GlobalVariablesTotal(); iGvarName++)
            if(StringSubstr(GlobalVariableName(iGvarName),0,SymbolLength+6)==_Symbol+" "+unique_sign+": E ")
            {
               sum_of_excluded_tfs=StringSubstr(GlobalVariableName(iGvarName),SymbolLength+6);
               break;
            }
         for(uchar iGvarName=0; iGvarName<GlobalVariablesTotal(); iGvarName++)
            if(StringSubstr(GlobalVariableName(iGvarName),0,SymbolLength+10)==_Symbol+" "+unique_sign+": EVHTF ")
            {
               sum_of_excluded_vhtfs=StringSubstr(GlobalVariableName(iGvarName),SymbolLength+10);
               break;
            }

         if(_Period>GraphObjTFsVisibility[p+skipped_tfs-NativeTFVisibilityShift] ||
            (StringLen(sum_of_excluded_tfs)==43 && StringLen(sum_of_excluded_vhtfs)==27) ||
            SymbolLength>MaxSymbLength || start>=end+1 ||
            (!Build_FiboTimeZones && !Build_AndrewsPitchforks && !Build_EquidistantChannels && !Build_FiboChannels))
            Print("{",unique_sign,"} ",StringSubstr(EnumToString(_Period),7)+": nothing to display.");
      }
   }
// --------------------------------------------------------------------------------------------------------------
   string BrokerName=AccountInfoString(ACCOUNT_COMPANY);

   if(!GlobalVariableCheck(_Symbol+" "+unique_sign+": PrevBrokerName: "+BrokerName))
   {
      for(uchar p=0; p<ArraySize(IncludedTFs); p++)
         if(IncludedTFs[p])
         {
            string tf_type=p<tf_delta ? StringSubstr(EnumToString(IncludedTFs[p]),7) :
                                        StringSubstr(IncludedVHTFs[p-tf_delta],7);
            ObjectsDeleteAll(0,tf_type+": ",0,-1);
         }
      ChartRedraw(0);

      string PrevBrokerName="";

      if(EventLogging)
      {
         for(uchar iGvarName=0; iGvarName<GlobalVariablesTotal(); iGvarName++)
         {
            string GvarName=GlobalVariableName(iGvarName);

            if(StringSubstr(GvarName,0,SymbolLength+18)==_Symbol+" "+unique_sign+": PrevBrokerName")
               PrevBrokerName=StringSubstr(GvarName,SymbolLength+20);
         }

         if(PrevBrokerName!="" && PrevBrokerName!=BrokerName)
         {
            string negation="";

            if(SymbolLength>MaxSymbLength || start>=end+1)
               negation="not ";
            Print("{",unique_sign,"} ",PrevBrokerName," broker has been changed to ",
                  BrokerName," broker. The ",_Symbol," {",unique_sign,"}"," chart will ",negation,"be re-marked.");
         }
      }

      GlobalVariablesDeleteAll(_Symbol+" "+unique_sign+": ",0);
      GlobalVariableSet(_Symbol+" "+unique_sign+": SingleActuation",0);
      GlobalVariableSet(_Symbol+" "+unique_sign+": PrevBrokerName: "+BrokerName,0);
   }
// --------------------------------------------------------------------------------------------------------------
   for(uchar iGvarName=0; iGvarName<GlobalVariablesTotal(); iGvarName++)
   {
      string FullPrevGVName=GlobalVariableName(iGvarName);
      int PrevGVSymbLength=StringFind(FullPrevGVName,":",0)-2;
      string PrevSymbol=StringSubstr(FullPrevGVName,0,PrevGVSymbLength);

      if(StringSubstr(FullPrevGVName,PrevGVSymbLength+4,18)==(string)ChartID() && PrevSymbol!=_Symbol)
      {
         string PrevUniqueSign=StringSubstr(FullPrevGVName,PrevGVSymbLength+1,1);

         for(uchar p=0; p<ArraySize(IncludedTFs); p++)
            if(IncludedTFs[p]>0 && Buffer_Array[p].handle!=INVALID_HANDLE)
            {
               string tf_type=p<tf_delta ? StringSubstr(EnumToString(IncludedTFs[p]),7) :
                                           StringSubstr(IncludedVHTFs[p-tf_delta],7);
               ObjectsDeleteAll(0,tf_type+": ",0,-1);
               IndicatorRelease(Buffer_Array[p].handle);
            }
         if(Buffer_Array[NUMBER/2].handle!=INVALID_HANDLE)
            IndicatorRelease(Buffer_Array[NUMBER/2].handle);

         ChartRedraw(0);
         GlobalVariablesDeleteAll(PrevSymbol+" "+PrevUniqueSign+": ",0);

         if(EventLogging)
            Print("{",PrevUniqueSign,"——>",unique_sign,"} ","The ",PrevSymbol," {",PrevUniqueSign,"} ",
                  "chart has been changed to the ",_Symbol," {",unique_sign,"} ","chart.");

         if(!GlobalVariableCheck(_Symbol+" "+unique_sign+": "+(string)ChartID()))
         {
            if(SymbolLength>MaxSymbLength)
               Print("{",unique_sign,"} ","Unable to markup this chart because the symbol name ",
                     _Symbol," is too long.");

            if(start>=end+1)
               Print("{",unique_sign,"} ","Unable to mark up another one ",_Symbol,
                     " chart: there are too many instances of the same indicator for this currency.");

            GlobalVariableSet(_Symbol+" "+unique_sign+": "+(string)ChartID(),0);
         }

         break;
      }
   }

   Comment("{",unique_sign,"}");
// --------------------------------------------------------------------------------------------------------------
   if(!GlobalVariableCheck(_Symbol+" "+unique_sign+": "+(string)ChartID()))
   {
      if(SymbolLength>MaxSymbLength)
         Print("{",unique_sign,"} ","Unable to markup this chart because the symbol name ",
               _Symbol," is too long.");

      if(start>=end+1)
         Print("{",unique_sign,"} ","Unable to mark up another one ",_Symbol,
               " chart: there are too many instances of the same indicator for this currency.");

      GlobalVariableSet(_Symbol+" "+unique_sign+": "+(string)ChartID(),0);
   }
// --------------------------------------------------------------------------------------------------------------
   if(start>=end+1)
   {
      uchar beginning='A';

      for(uchar iGvarName=0; iGvarName<GlobalVariablesTotal(); iGvarName++)
      {
         string GvarName=GlobalVariableName(iGvarName);

         if(StringSubstr(GvarName,0,SymbolLength+1)==_Symbol+" " &&
            StringSubstr(GvarName,SymbolLength+4)=="SingleActuation")
         {
            string GVNameUniqueSign=StringSubstr(GvarName,SymbolLength+1,1);

            for(uchar letter=beginning; letter<=end+1; letter++)
            {
               if(GVNameUniqueSign!=CharToString(letter))
               {
                  unique_sign=CharToString(letter);
                  beginning++;
                  break;
               }
            }
         }
      }
   }
   else
      if(unique_sign!=CharToString(start))
      {
         if(EventLogging)
            Print("{",unique_sign,"——>",CharToString(start),"} ",
                  "Excessive indicator of ",_Symbol," {",unique_sign,"} ",
                  "chart became available as indicator of ",_Symbol,
                  " {",CharToString(start),"} ","chart.");

         GlobalVariableDel(_Symbol+" "+unique_sign+": "+(string)ChartID());
         GlobalVariableDel(_Symbol+" "+unique_sign+": PrevBrokerName: "+BrokerName);
         GlobalVariableDel(_Symbol+" "+unique_sign+": SingleActuation");
         GlobalVariableDel(_Symbol+" "+unique_sign+": WeekendsSA");
         unique_sign=CharToString(start);
         GlobalVariableSet(_Symbol+" "+unique_sign+": "+(string)ChartID(),0);
         GlobalVariableSet(_Symbol+" "+unique_sign+": PrevBrokerName: "+BrokerName,0);

         Comment("{",unique_sign,"}");
      }
// --------------------------------------------------------------------------------------------------------------
   if(SymbolLength>MaxSymbLength || (start>=end+1 && unique_sign==CharToString(start)))
   {
      GlobalVariableSet(_Symbol+" "+unique_sign+": SingleActuation",0);

      return(INIT_SUCCEEDED);
   }
// --------------------------------------------------------------------------------------------------------------
   int amount;

   if(BarsCount<GlobalVariableGet(_Symbol+" "+unique_sign+": PrevBarsCount"))
      for(uchar p=0; p<ArraySize(IncludedTFs); p++)
         if(IncludedTFs[p])
         {
            string s="";
            string h="has";
            string tf_type=p<tf_delta ? StringSubstr(EnumToString(IncludedTFs[p]),7) :
                                        StringSubstr(IncludedVHTFs[p-tf_delta],7);

            for(int o=0; o<ArraySize(ObjectsId); o++)
            {
               amount=ObjectsDeleteAll(0,tf_type+": ",0,ObjectsId[o]);
               if(ObjectsId[o]==OBJ_FIBOTIMES || amount>1) {s="s"; h="have";}

               if(EventLogging && amount)
                  Print("{",unique_sign,"} ",amount," ",obj_full_names[o],s," from ",tf_type," ",h," been removed.");
            }
         }
// --------------------------------------------------------------------------------------------------------------
   if(NumberOfFiboTimeZonesLevels<GlobalVariableGet(_Symbol+" "+unique_sign+": PrevNumberOfFiboTimeZonesLevels"))
      for(uchar p=0; p<ArraySize(IncludedTFs); p++)
         if(IncludedTFs[p])
         {
            string tf_type=p<tf_delta ? StringSubstr(EnumToString(IncludedTFs[p]),7) :
                                        StringSubstr(IncludedVHTFs[p-tf_delta],7);

            amount=ObjectsDeleteAll(0,tf_type+": ",0,OBJ_FIBOTIMES);
            if(EventLogging && amount)
               Print("{",unique_sign,"} ",amount," Fibo TimeZones from ",tf_type," have been removed.");
         }
// --------------------------------------------------------------------------------------------------------------
   if(ChannelAndPitchforkTopicality<GlobalVariableGet(_Symbol+" "+unique_sign+": PrevChannelAndPitchforkTopicality"))
      for(uchar p=0; p<ArraySize(IncludedTFs); p++)
         if(IncludedTFs[p])
         {
            string s="";
            string h="has";
            string tf_type=p<tf_delta ? StringSubstr(EnumToString(IncludedTFs[p]),7) :
                                        StringSubstr(IncludedVHTFs[p-tf_delta],7);

            for(uchar o=1; o<ArraySize(ObjectsId); o++)
            {
               amount=ObjectsDeleteAll(0,tf_type+": ",0,ObjectsId[o]);
               if(amount>1) {s="s"; h="have";}

               if(EventLogging && amount)
                  Print("{",unique_sign,"} ",amount," ",obj_full_names[o],s," from ",tf_type," ",h," been removed.");
            }
         }
// --------------------------------------------------------------------------------------------------------------
   for(uchar p_=0; p_<ArraySize(IncludedTFs); p_++)
   {
      ArrayResize(ExcludedTFs,p_+1);
      ExcludedTFs[p_]=GraphObjTFsVisibility[p_+skipped_tfs];
   }

   for(int p=ArraySize(IncludedTFs)-1; p>=0; p--)
      if(IncludedTFs[p]>0 && IncludedTFs[p]==ExcludedTFs[p])
         ExcludedTFs[p]=0;
// --------------------------------------------------------------------------------------------------------------
   string sum_of_excluded_tfs="";
   string sum_of_excluded_vhtfs="";

   for(uchar p_=0; p_<ArraySize(ExcludedTFs); p_++)
   {
      if(ExcludedTFs[p_])
      {
         string s="";
         string h="has";
         string tf_type=p_<tf_delta ? StringSubstr(EnumToString(ExcludedTFs[p_]),7) :
                                      StringSubstr(IncludedVHTFs[p_-tf_delta],7);

         for(uchar o=0; o<ArraySize(ObjectsId); o++)
         {
            amount=ObjectsDeleteAll(0,tf_type+": ",0,ObjectsId[o]);
            if(ObjectsId[o]==OBJ_FIBOTIMES || amount>1) {s="s"; h="have";}

            if(EventLogging && amount)
               Print("{",unique_sign,"} ",amount," ",obj_full_names[o],s," from ",tf_type," ",h," been removed.");
         }

         if(p_<tf_delta)
            sum_of_excluded_tfs+=" "+tf_type;
         else
            sum_of_excluded_vhtfs+=" "+tf_type;
      }
   }
// --------------------------------------------------------------------------------------------------------------
   for(uchar b=0; b<ArraySize(Buildings); b++)
      if(!Buildings[b])
         for(uchar p=0; p<ArraySize(IncludedTFs); p++)
            if(IncludedTFs[p])
            {
               string s="";
               string h="has";
               string tf_type=p<tf_delta ? StringSubstr(EnumToString(IncludedTFs[p]),7) :
                                           StringSubstr(IncludedVHTFs[p-tf_delta],7);
   
               amount=ObjectsDeleteAll(0,tf_type+": ",0,ObjectsId[b]);
               if(ObjectsId[b]==OBJ_FIBOTIMES || amount>1) {s="s"; h="have";}

               if(EventLogging && amount)
                  Print("{",unique_sign,"} ",amount," ",obj_full_names[b],s," from ",tf_type," ",h," been removed.");
            }
// --------------------------------------------------------------------------------------------------------------
   if(EventLogging)
   {
      string GvarName;

      for(uchar tf_type=0; tf_type<2; tf_type++)
      {
         uchar plus_len=tf_type==0 ? 5 : 9;
         string excl=tf_type==0 ? "" : "VHTF";
         string excl_tf_type=tf_type==0 ? "" : "virtual hyper";
         string sum=tf_type<1 ? sum_of_excluded_tfs : sum_of_excluded_vhtfs;

         for(uchar iGvarName=0; iGvarName<GlobalVariablesTotal(); iGvarName++)
            if(StringSubstr(GlobalVariableName(iGvarName),0,SymbolLength+plus_len)==_Symbol+" "+unique_sign+": E"+excl)
            {
               GvarName=GlobalVariableName(iGvarName);
               break;
            }

         if(_Symbol+" "+unique_sign+": E"+excl+sum!=GvarName)
         {
            if(sum!="")
               if(StringLen(sum)>4)
                  Print("{",unique_sign,"} ","Reserved ",excl_tf_type,"timeframes:",sum," are excluded from the marking-up.");
               else
                  Print("{",unique_sign,"} ","Reserved ",excl_tf_type,"timeframe",sum," is excluded from the marking-up.");
            else
               Print("{",unique_sign,"} ","All reserved ",excl_tf_type,"timeframes are included in the marking-up.");

            GlobalVariableDel(GvarName);
            GlobalVariableSet(_Symbol+" "+unique_sign+": E"+excl+sum,0);
         }
      }
   }
// --------------------------------------------------------------------------------------------------------------
   int Ar_shift;
   char ArrowShift=-10;
   string Label;
   string UD[2]={"Up","Down"};

   if(RenderFractals)
      for(uchar i=0; i<NUMBER/2; i++)
      {
         if(IncludedTFs[i])
            Label=i<tf_delta ?
                  StringSubstr(EnumToString(IncludedTFs[i]),7) :
                  StringSubstr(IncludedVHTFs[i-tf_delta],7);

         for(uchar UpOrDown=0; UpOrDown<=1; UpOrDown++)
         {
            int c=i*2+UpOrDown;

            SetIndexBuffer(c,Buffer_Array[c].FractalsBuffer,INDICATOR_DATA);
            if(IncludedTFs[i])
            {
               Ar_shift=EachOtherArrows ? ArrowShift*(1-2*(c%2))-i*(1-2*(c%2)) : ArrowShift*(1-2*(c%2));

               PlotIndexSetInteger(c,PLOT_DRAW_TYPE,DRAW_ARROW);
               PlotIndexSetInteger(c,PLOT_ARROW,217+c%2);
               PlotIndexSetInteger(c,PLOT_ARROW_SHIFT,Ar_shift);
               PlotIndexSetInteger(c,PLOT_LINE_COLOR,ClrArray1[i]);
               PlotIndexSetInteger(c,PLOT_LINE_WIDTH,(int)ceil(((double)(c+c%2+1)/2-c%2)/((double)NUMBER/(2*5)))); // (NUMBER-1)
               PlotIndexSetDouble(c,PLOT_EMPTY_VALUE,EMPTY_VALUE);
               PlotIndexSetString(c,PLOT_LABEL,"Fractal "+UD[UpOrDown]+" for "+Label);
               ArraySetAsSeries(Buffer_Array[c].FractalsBuffer,true);
            }
         }
      }
   else
      for(uchar i=0; i<NUMBER/2; i++)
         if(IncludedTFs[i])
            for(uchar UpOrDown=0; UpOrDown<=1; UpOrDown++)
            {
               uchar c=i*2+UpOrDown;

               PlotIndexSetInteger(c,PLOT_DRAW_TYPE,DRAW_NONE);
               ArrayInitialize(Buffer_Array[c].PrepsBuffer,EMPTY_VALUE);
               ArrayInitialize(Buffer_Array[c].FractalsBuffer,EMPTY_VALUE);
            }

   for(uchar i=0; i<NUMBER/2; i++)
      if(IncludedTFs[i])
      {
         ArrayInitialize(Buffer_Array[i].PriceExtremum,EMPTY_VALUE);
         ArrayInitialize(Buffer_Array[i].TimeExtremum,EMPTY_VALUE);

         uchar iParam=i<tf_delta ? 0 : VHPERIODS[i-tf_delta];
         Buffer_Array[i].bars_calculated=0;
         Buffer_Array[i].waiting_for_loading_history_msg_counter=0;
         Buffer_Array[i].handle=iCustom(_Symbol,IncludedTFs[i],"Examples\\iCFractals",iParam);
         if(Buffer_Array[i].handle==INVALID_HANDLE) return(-1);
      }

   Buffer_Array[NUMBER/2].handle=iCustom(_Symbol,0,"Examples\\iCFractals");
   if(Buffer_Array[NUMBER/2].handle==INVALID_HANDLE) return(-1);
// --------------------------------------------------------------------------------------------------------------
   for(uchar p=0; p<ArraySize(IncludedTFs); p++)
      if(!IncludedTFs[p] && Buffer_Array[p].handle!=INVALID_HANDLE)
         IndicatorRelease(Buffer_Array[p].handle);
// --------------------------------------------------------------------------------------------------------------
   if(!GlobalVariableGet(_Symbol+" "+unique_sign+": SingleActuation"))
   {
      datetime PreloadingArr[];
      string sum_of_successful_tfs="";
      string sum_of_unsuccessful_tfs="";

      for(uchar p=0; p<ArraySize(GraphObjTFsVisibility); p++)
      {
         int ct=CopyTime(_Symbol,GraphObjTFsVisibility[p],0,1,PreloadingArr);
         string tf_type=p<tf_delta+skipped_tfs ? StringSubstr(EnumToString(GraphObjTFsVisibility[p]),7) :
                                                 StringSubstr(IncludedVHTFs[p-skipped_tfs-tf_delta],7);

         if(ct<1)
         {
            sum_of_unsuccessful_tfs+=tf_type+" ";
            //Print("{",unique_sign,"} ","OnInit(): ArraySize(PreloadingArr)=",ArraySize(PreloadingArr),
            //      "; copied=",ct,
            //      "; TF=",EnumToString(GraphObjTFsVisibility[p])
            //     );
            //Print("{",unique_sign,"} ","Error Code = ",GetLastError());
            //ResetLastError();
         }
         else
            sum_of_successful_tfs+=tf_type+" ";
      }
      ArrayFree(PreloadingArr);

      if(EventLogging)
         if(sum_of_unsuccessful_tfs!="")
         {
            Print("{",unique_sign,"} ","Unsuccessful preloading of the history of quotes and building of timeseries for: ",
                  sum_of_unsuccessful_tfs,"period(s).");
            if(sum_of_successful_tfs!="")
               Print("{",unique_sign,"} ","The history of quotes has been successfully preloaded and timeseries have been built for: ",
                     sum_of_successful_tfs,"period(s).");
         }
   }
// --------------------------------------------------------------------------------------------------------------
   ArraySetAsSeries(exact_extremum,true);

   SAGvar=GlobalVariableGet(_Symbol+" "+unique_sign+": SingleActuation");

   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[])
  {
// --------------------------------------------------------------------------------------------------------------
   datetime LoadingArr[];

   for(uchar p=0; p<ArraySize(GraphObjTFsVisibility); p++)
   {
      int ct=CopyTime(_Symbol,GraphObjTFsVisibility[p],0,1,LoadingArr);
      if(ct<1)
      {
         //Print("{",unique_sign,"} ","OnCalculate(): ArraySize(LoadingArr)=",ArraySize(LoadingArr),
         //      "; copied=",ct,
         //      "; TF=",EnumToString(GraphObjTFsVisibility[p])
         //     );
         //Print("{",unique_sign,"} ","Error Code = ",GetLastError());
         //ResetLastError();
         return(0);
      }
   }
   ArrayFree(LoadingArr);

   if(EventLogging && !GlobalVariableGet(_Symbol+" "+unique_sign+": WeekendsSA") && !additional_history_loading_msg_counter && start<end+1)
   {
      Print("{",unique_sign,"} ","The history of quotes has been successfully loaded and timeseries have been built for all existing periods.");
      additional_history_loading_msg_counter++;
   }

   GlobalVariableSet(_Symbol+" "+unique_sign+": WeekendsSA",1);
// ---
   for(uchar bi=0; bi<ArraySize(IncludedTFs)*2 && !IsStopped(); bi+=2) // buffer index
   {
      if(Buffer_Array[bi/2].bars_calculated<7)
      {
         ArrayInitialize(Buffer_Array[bi].PrepsBuffer,EMPTY_VALUE);
         ArrayInitialize(Buffer_Array[bi+1].PrepsBuffer,EMPTY_VALUE);

         ArrayInitialize(Buffer_Array[bi].FractalsBuffer,EMPTY_VALUE);
         ArrayInitialize(Buffer_Array[bi+1].FractalsBuffer,EMPTY_VALUE);
      }

      if(IncludedTFs[bi/2])
      {
         Buffer_Array[bi/2].calculated=BarsCalculated(Buffer_Array[bi/2].handle);

         if(Buffer_Array[bi/2].calculated<=0) return(0);

         uchar BC_VHTF_multiplier=1;
         string tf_type=StringSubstr(EnumToString(IncludedTFs[bi/2]),7);
         if(bi/2>=tf_delta)
         {
            BC_VHTF_multiplier=VHPERIODS[bi/2-tf_delta];
            tf_type=StringSubstr(IncludedVHTFs[bi/2-tf_delta],7);
         }

         if(Buffer_Array[bi/2].bars_calculated==0 ||
            Buffer_Array[bi/2].calculated>Buffer_Array[bi/2].bars_calculated+1)
            if(BarsCount*BC_VHTF_multiplier<=Buffer_Array[bi/2].calculated)
               Buffer_Array[bi/2].values_to_copy=BarsCount*BC_VHTF_multiplier;
            else Buffer_Array[bi/2].values_to_copy=Buffer_Array[bi/2].calculated;
         else Buffer_Array[bi/2].values_to_copy=(Buffer_Array[bi/2].calculated-Buffer_Array[bi/2].bars_calculated)+3;

         if(!FillArraysFromBuffers(Buffer_Array[bi].PrepsBuffer,
                                   Buffer_Array[bi+1].PrepsBuffer,
                                   Buffer_Array[bi].PrepTimesBuffer,
                                   Buffer_Array[bi+1].PrepTimesBuffer,
                                   Buffer_Array[bi/2].handle,
                                   IncludedTFs[bi/2],
                                   Buffer_Array[bi/2].values_to_copy)) return(0);
         else
         {
            for(int shift=0; shift<Buffer_Array[bi/2].values_to_copy-3 && !IsStopped(); shift++)
            {
               for(char UpOrDown=1; UpOrDown>=-1; UpOrDown-=2)
               {
                  if(!SetFractalToExactPosition(Buffer_Array[bi-(UpOrDown-1)/2].PrepsBuffer[shift],
                                                shift,
                                                IncludedTFs[bi/2],
                                                bi-(UpOrDown-1)/2))
                  {
                     if(!Buffer_Array[bi/2].waiting_for_loading_history_msg_counter)
                     {
                        Print("{",unique_sign,"} ","Please wait for loading the quotes history of the ",tf_type," timeframe...");
                        Buffer_Array[bi/2].waiting_for_loading_history_msg_counter++;
                     }
                     return(0);
                  }
               }
            }
            Buffer_Array[bi/2].waiting_for_loading_history_msg_counter=0;
         }
      }
   }
// ---
// ---
   if(Build_FiboTimeZones || Build_AndrewsPitchforks || Build_EquidistantChannels || Build_FiboChannels)
   {
      int lbound=0;
      int rbound=ArraySize(IncludedTFs)*2;

      if(BuildMinorTFsMarkup!=BuildMajorTFsMarkup)
      {
         int iCurTF=0;

         for(uchar itf=0; itf<ArraySize(IncludedTFs) && !IsStopped(); itf++)
         {
            if(IncludedTFs[itf])
            {
               if(_Period==IncludedTFs[itf])
               {
                  iCurTF=itf;
                  break;
               }
               else
               {
                  if(_Period<IncludedTFs[itf])
                  {
                     if(BuildMinorTFsMarkup)
                        iCurTF=itf-1;
                     else
                        iCurTF=itf;
                     break;
                  }
               }
            }
         }

         if(BuildMinorTFsMarkup) rbound=(iCurTF+1)*2;
         else lbound=iCurTF*2;
      }

      for(int bi=lbound; bi<rbound && !IsStopped(); bi+=2)
      {
         if(IncludedTFs[bi/2]>0 && Buffer_Array[bi/2].calculated>Buffer_Array[bi/2].bars_calculated)
         {
            string tf_type=bi/2<tf_delta ? StringSubstr(EnumToString(IncludedTFs[bi/2]),7) :
                                           StringSubstr(IncludedVHTFs[bi/2-tf_delta],7);
            uchar NVHTFVS=0; // native virtual hypertimeframe's visibility shift
            int TFsSumVFlag=0; // timeframe's sum visibility flag

            for(int vtf=0; vtf<ArraySize(GraphObjTFsVisibility); vtf++)
            {
               if(bi/2>=tf_delta+vtf)
                  NVHTFVS++;

               TFsSumVFlag|=((int)1)<<(vtf-NativeTFVisibilityShift+NVHTFVS);

               if(IncludedTFs[bi/2]==GraphObjTFsVisibility[vtf])
                  break;
            }
// ---
            if(Build_FiboTimeZones)
            {
               for(int shift=0; shift<Buffer_Array[bi/2].values_to_copy-3 && !IsStopped(); shift++)
                  for(char UpOrDown=1; UpOrDown>=-1; UpOrDown-=2)
                     FindNearbyFractalsForFTZ(Buffer_Array[bi/2].PriceExtremum,
                                              Buffer_Array[bi-(UpOrDown-1)/2].PrepsBuffer[shift],
                                              Buffer_Array[bi/2].TimeExtremum,
                                              Buffer_Array[bi-(UpOrDown-1)/2].PrepTimesBuffer[shift],
                                              Buffer_Array[bi/2].bars_calculated,
                                              tf_type,
                                              TFsSumVFlag,
                                              IncludedTFs[bi/2],
                                              ClrArray1[bi/2],
                                              ClrAuxArray[bi/2],
                                              UpOrDown);
               if(EventLogging)
                  logging(Buffer_Array[bi/2].bars_calculated,
                          OBJ_FIBOTIMES,
                          "Fibo TimeZone",
                          IncludedTFs[bi/2],
                          tf_type);

               if(Restrict_FiboTimeZones)
                  RestrictFiboTimeZones(Buffer_Array[bi/2].bars_calculated,
                                        tf_type,
                                        IncludedTFs[bi/2],
                                        ClrArray1[bi/2],
                                        ClrAuxArray[bi/2]);
            }
// ---
// ---
            for(uchar b=1; b<ArraySize(Buildings); b++)
               if(Buildings[b])
               {
                  color this_obj_type_color=clrNONE;
                  if(ObjectsId[b]==OBJ_PITCHFORK) this_obj_type_color=ClrArray1[bi/2];
                  if(ObjectsId[b]==OBJ_CHANNEL) this_obj_type_color=ClrArray2[bi/2];
                  if(ObjectsId[b]==OBJ_FIBOCHANNEL) this_obj_type_color=ClrArray3[bi/2];

                  for(int shift=0; shift<Buffer_Array[bi/2].values_to_copy-3 && !IsStopped(); shift++)
                     for(char UpOrDown=1; UpOrDown>=-1; UpOrDown-=2)
                        FindNearbyFractalsForAPitchforkOrChannel(Buffer_Array[bi/2].PriceExtremum,
                                                                 Buffer_Array[bi-(UpOrDown-1)/2].PrepsBuffer[shift],
                                                                 Buffer_Array[bi/2].TimeExtremum,
                                                                 Buffer_Array[bi-(UpOrDown-1)/2].PrepTimesBuffer[shift],
                                                                 Buffer_Array[bi/2].bars_calculated,
                                                                 b,
                                                                 tf_type,
                                                                 TFsSumVFlag,
                                                                 IncludedTFs[bi/2],
                                                                 ObjectsId[b],
                                                                 obj_short_names[b],
                                                                 obj_full_names[b],
                                                                 this_obj_type_color,
                                                                 UpOrDown);
                  if(EventLogging)
                     logging(Buffer_Array[bi/2].bars_calculated,
                             ObjectsId[b],
                             obj_full_names[b],
                             IncludedTFs[bi/2],
                             tf_type);
               }
         }
      }

      if(EventLogging && !SAGvar)
         for(uchar b=0; b<ArraySize(Buildings); b++)
            if(Buildings[b] && ObjectsTotal(0,0,ObjectsId[b])>0)
            {
               double T=ObjectsId[b]==OBJ_FIBOTIMES ? Topicality[0] : Topicality[1];
               bool iB=ObjectsId[b]==OBJ_FIBOTIMES ? areBuiltFTZ : isBuiltAPfOrEqChOrFCh;

               if(T!=GlobalVariableGet(_Symbol+" "+unique_sign+": Prev"+(string)T) ||
                  BarsCount!=GlobalVariableGet(_Symbol+" "+unique_sign+": PrevBarsCount") || !iB)
                  Print("{",unique_sign,"} ","Total ",ObjectsTotal(0,0,ObjectsId[b]),
                        " history-based ",obj_full_names[b],"s from all selected timeframes have been built.");
               else
                  Print("{",unique_sign,"} ","The ",_Symbol," chart is already marked up with Fibo Channels earlier.");
            }

      SAGvar=1;
      GlobalVariableSet(_Symbol+" "+unique_sign+": SingleActuation",SAGvar);
      GlobalVariableSet(_Symbol+" "+unique_sign+": PrevBarsCount",BarsCount);
      GlobalVariableSet(_Symbol+" "+unique_sign+": PrevNumberOfFiboTimeZonesLevels",NumberOfFiboTimeZonesLevels);
      GlobalVariableSet(_Symbol+" "+unique_sign+": PrevChannelAndPitchforkTopicality",ChannelAndPitchforkTopicality);
   }
// ---
// ---
   if(RemoveOutdatedObjects)
   {
      for(uchar tf=0; tf<ArraySize(IncludedTFs) && !IsStopped(); tf++)
      {
         if(IncludedTFs[tf]>0 &&
            Buffer_Array[tf].calculated>Buffer_Array[tf].bars_calculated &&
            Buffer_Array[tf].values_to_copy-3==1)
         {
            if(Build_FiboTimeZones)
               GarbageCollectorFTZ(IncludedTFs[tf]);

            for(uchar b=1; b<ArraySize(Buildings); b++)
               if(Buildings[b])
                  GarbageCollectorForAPfOrEqChOrFCh(IncludedTFs[tf],
                                                    ObjectsId[b],
                                                    obj_full_names[b]
                                                   );
         }
      }
   }
// ---
   for(uchar tf=0; tf<ArraySize(IncludedTFs) && !IsStopped(); tf++)
      if(IncludedTFs[tf])
         Buffer_Array[tf].bars_calculated=Buffer_Array[tf].calculated;
// ---
// --------------------------------------------------------------------------------------------------------------

   return(rates_total);
  }

//+------------------------------------------------------------------+
//| Custom indicator logging function                                |
//+------------------------------------------------------------------+
void logging(int bars_calculated,
             ENUM_OBJECT enum_obj_type,
             string object_type,
             ENUM_TIMEFRAMES tf,
             string tf_name_
            )
  {
   string ending="";
   string plural_or_singular;

   if(!bars_calculated && !SAGvar)
   {
      int this_tf_obj_amount=0;
      for(int objN=0; objN<ObjectsTotal(0,0,enum_obj_type) && !IsStopped(); objN++)
      {
         string objname=ObjectName(0,objN,0,enum_obj_type);
         string tf_name=StringSubstr(objname,0,4);
         if(StringTrimRight(tf_name)==1) StringSetLength(tf_name,3);
         if(tf_name==tf_name_+":")
            this_tf_obj_amount++;
      }
      if(this_tf_obj_amount)
      {
         if(this_tf_obj_amount>1 || enum_obj_type==OBJ_FIBOTIMES)
         {
            ending="s";
            plural_or_singular="have";
         }
         else
            plural_or_singular="has";
         if(BarsCount!=GlobalVariableGet(_Symbol+" "+unique_sign+": PrevBarsCount") ||
            (NumberOfFiboTimeZonesLevels!=GlobalVariableGet(_Symbol+" "+unique_sign+": PrevNumberOfFiboTimeZonesLevels") &&
            enum_obj_type==OBJ_FIBOTIMES) ||
            (ChannelAndPitchforkTopicality!=GlobalVariableGet(_Symbol+" "+unique_sign+": PrevChannelAndPitchforkTopicality") &&
            (enum_obj_type==OBJ_PITCHFORK || enum_obj_type==OBJ_CHANNEL || enum_obj_type==OBJ_FIBOCHANNEL)))
            Print("{",unique_sign,"} ",this_tf_obj_amount," history-based ",object_type,ending," from ",
                  tf_name_," ",plural_or_singular," been built.");
      }
   }
   else
      if(obj_counter && !bars_calculated && SAGvar)
      {
         if(obj_counter>1 || enum_obj_type==OBJ_FIBOTIMES)
         {
            ending="s";
            plural_or_singular="have";
         }
         else
            plural_or_singular="has";
         Print("{",unique_sign,"} ",obj_counter," history-based ",object_type,ending," from ",
               tf_name_," ",plural_or_singular," been built or restored.");
      }
   obj_counter=0;
  }

//+------------------------------------------------------------------+
//| Custom indicator's function of filling arrays from buffers       |
//+------------------------------------------------------------------+
bool FillArraysFromBuffers(double &up_arrows[],
                           double &down_arrows[],
                           datetime &up_times[],
                           datetime &down_times[],
                           int ind_handle,
                           ENUM_TIMEFRAMES tf,
                           int amount
                          )
  {
   if(CopyBuffer(ind_handle,0,0,amount,up_arrows)<0) return(false);
   else CopyTime(_Symbol,tf,0,amount,up_times);

   if(CopyBuffer(ind_handle,1,0,amount,down_arrows)<0) return(false);
   else CopyTime(_Symbol,tf,0,amount,down_times);

   return(true);
  }

//+------------------------------------------------------------------------+
//| Custom indicator's function for setting a fractal to an exact position |
//+------------------------------------------------------------------------+
bool SetFractalToExactPosition(double PriceCur,
                               uint shift,
                               ENUM_TIMEFRAMES tf,
                               int bi
                              )
  {
   int array_extremum;
   datetime exact_extremum_time[];

   if(PriceCur!=EMPTY_VALUE)
   {
      if(bi%2==0)
      {
         if(CopyHigh(_Symbol,PERIOD_M1,Buffer_Array[bi].PrepTimesBuffer[shift+1],
                                       Buffer_Array[bi].PrepTimesBuffer[shift],
                                       exact_extremum)<0) return(false);
         array_extremum=ArrayMaximum(exact_extremum,0,WHOLE_ARRAY);
      }
      else
      {
         if(CopyLow(_Symbol,PERIOD_M1,Buffer_Array[bi].PrepTimesBuffer[shift+1],
                                      Buffer_Array[bi].PrepTimesBuffer[shift],
                                      exact_extremum)<0) return(false);
         array_extremum=ArrayMinimum(exact_extremum,0,WHOLE_ARRAY);
      }

      if(CopyTime(_Symbol,PERIOD_M1,Buffer_Array[bi].PrepTimesBuffer[shift+1],
                                    array_extremum+1,
                                    exact_extremum_time)<0) return(false);

      int iBSh=iBarShift(_Symbol,_Period,exact_extremum_time[0],true);
      if(iBSh<0) return(false);

      if(RenderFractals)
         if(MinorTFsFractalFilter)
         {
            if(tf>=_Period)
               Buffer_Array[bi].FractalsBuffer[iBSh]=PriceCur;
         }
         else Buffer_Array[bi].FractalsBuffer[iBSh]=PriceCur;

      if(Build_FiboTimeZones || Build_AndrewsPitchforks ||
         Build_EquidistantChannels || Build_FiboChannels)
         Buffer_Array[bi].PrepTimesBuffer[shift]=exact_extremum_time[0];
   }

   return(true);
  }
// --------------------------------------------------------------------------------------------------------------
//+------------------------------------------------------------------------+
//| Custom indicator's function for building Fibo TimeZones                |
//+------------------------------------------------------------------------+
void BuildFiboTimeZones(double PriceExtr,
                        double PriceCur,
                        datetime TimeExtr,
                        datetime TimeCur,
                        int bars_calculated,
                        string tf_type,
                        ENUM_TIMEFRAMES tf,
                        ENUM_LINE_STYLE LStyle,
                        color clr,
                        color clr_aux,
                        int visibility
                       )
  {
   ENUM_TIMEFRAMES source_tf=tf;
   string objname;
   datetime Arr[];
   int pos1,BaseBandwidth;
   if(AccuracyOfCalculations)
      tf=PERIOD_M1;

   if(TimeExtr>TimeCur)
   {
      datetime TimeInterm=TimeCur;
      double PriceInterm=PriceCur;

      TimeCur=TimeExtr;
      TimeExtr=TimeInterm;
      PriceCur=PriceExtr;
      PriceExtr=PriceInterm;
   }

   pos1=iBarShift(_Symbol,tf,TimeExtr,true)+1;
   BaseBandwidth=CopyTime(_Symbol,tf,TimeCur,TimeExtr,Arr);

   if(BaseBandwidth*(NumberOfFiboTimeZonesLevels+2)>=pos1)
   {
      int FiboArray[];

      ArrayCopy(FiboArray,DefaultFTZLevels,0,0,WHOLE_ARRAY);

      for(int l=ArraySize(FiboArray)-1; l>=0; l--)
         if(FiboArray[l]!=NumberOfFiboTimeZonesLevels)
            ArrayRemove(FiboArray,l,1);
         else
            break;

      StringConcatenate(objname,tf_type,": F TZ ",
                        TimeToString(TimeExtr,TIME_DATE|TIME_MINUTES),"—",
                        TimeToString(TimeCur,TIME_DATE|TIME_MINUTES)
                       );

      if(!ObjectFind(0,objname) &&
         (ObjectGetInteger(0,objname,OBJPROP_TIME,0)!=TimeExtr ||
          ObjectGetInteger(0,objname,OBJPROP_TIME,1)!=TimeCur ||
          ObjectGetDouble(0,objname,OBJPROP_PRICE,0)!=fabs(PriceExtr) ||
          ObjectGetDouble(0,objname,OBJPROP_PRICE,1)!=PriceCur))
         ObjectDelete(0,objname);

      if(ObjectFind(0,objname)<0)
      {
         areBuiltFTZ=false;

         if(EventLogging && !bars_calculated && SAGvar)
            obj_counter++;

         ObjectCreate(0,objname,OBJ_FIBOTIMES,0,
                      TimeExtr,fabs(PriceExtr),
                      TimeCur,PriceCur
                     );
      }
      else
         areBuiltFTZ=true;

      ObjectSetInteger(0,objname,OBJPROP_STYLE,STYLE_DOT);
      ObjectSetInteger(0,objname,OBJPROP_WIDTH,1);
      ObjectSetInteger(0,objname,OBJPROP_COLOR,0x444444);
      ObjectSetInteger(0,objname,OBJPROP_LEVELS,ArraySize(FiboArray));
      for(uchar n=0; n<ArraySize(FiboArray) && !IsStopped(); n++)
      {
         ObjectSetDouble(0,objname,OBJPROP_LEVELVALUE,n,FiboArray[n]);
         ObjectSetString(0,objname,OBJPROP_LEVELTEXT,n,(string)FiboArray[n]);
      }
      ObjectSetInteger(0,objname,OBJPROP_LEVELCOLOR,WHOLE_ARRAY,clr);
      ObjectSetInteger(0,objname,OBJPROP_LEVELCOLOR,0,clrNONE);
      ObjectSetInteger(0,objname,OBJPROP_LEVELCOLOR,1,clrNONE);
      ObjectSetInteger(0,objname,OBJPROP_LEVELCOLOR,2,clr_aux);
      ObjectSetInteger(0,objname,OBJPROP_LEVELSTYLE,WHOLE_ARRAY,LStyle);
      ObjectSetInteger(0,objname,OBJPROP_LEVELWIDTH,WHOLE_ARRAY,1);
      ObjectSetInteger(0,objname,OBJPROP_TIMEFRAMES,visibility);
      ObjectSetInteger(0,objname,OBJPROP_SELECTABLE,true);

      if(EventLogging && SAGvar && bars_calculated)
         if(Restrict_FiboTimeZones)
            Print("{",unique_sign,"} ","1 new restricted Fibo TimeZones '",objname,"' have been built.");
         else
            Print("{",unique_sign,"} ","1 new Fibo TimeZones '",objname,"' have been built.");
   }
  }

//+--------------------------------------------------------------------------------------+
//| Custom indicator's function of searching nearby fractals for building Fibo TimeZones |
//+--------------------------------------------------------------------------------------+
void FindNearbyFractalsForFTZ(double &PriceExtr[][],
                              double PriceCur,
                              datetime &TimeExtr[][],
                              datetime TimeCur,
                              int bars_calculated,
                              string tf_type,
                              int visibility,
                              ENUM_TIMEFRAMES tf,
                              color clr,
                              color clr_aux,
                              char sign
                             )
  {
   uchar el;
   ENUM_LINE_STYLE LStyle;

   if(PriceCur!=EMPTY_VALUE)
   {
      if(PriceExtr[0][0]==EMPTY_VALUE) el=0;
      else
      {
         LStyle=STYLE_DASH;

         if(PriceExtr[0][1]==EMPTY_VALUE)
         {
            el=0;

            if(PriceExtr[0][el]*PriceCur*sign<0) LStyle=STYLE_DASHDOT;
         }
         else
         {
            el=1;

            if(PriceExtr[0][el]*PriceCur*sign<0)
            {
               LStyle=STYLE_DASHDOT;

               BuildFiboTimeZones(PriceExtr[0][0],PriceCur,
                                  TimeExtr[0][0],TimeCur,
                                  bars_calculated,
                                  tf_type,
                                  tf,STYLE_DASH,
                                  clr,clr_aux,visibility);
            }
         }

         BuildFiboTimeZones(PriceExtr[0][el],PriceCur,
                            TimeExtr[0][el],TimeCur,
                            bars_calculated,
                            tf_type,
                            tf,LStyle,
                            clr,clr_aux,visibility);

         if(PriceExtr[0][1]==EMPTY_VALUE)
         {
            if(PriceExtr[0][0]*PriceCur*sign<0) el=1;
            else el=0;
         }
         else
         {
            if(PriceExtr[0][1]*PriceCur*sign<0)
            {
               el=1;

               PriceExtr[0][0]=PriceExtr[0][1];
               TimeExtr[0][0]=TimeExtr[0][1];
            }
            else
            {
               el=0;

               PriceExtr[0][1]=EMPTY_VALUE;
               TimeExtr[0][1]=0;
            }
         }
      }
      PriceExtr[0][el]=PriceCur*sign;
      TimeExtr[0][el]=TimeCur;
   }
  }

//+------------------------------------------------------------------+
//| Custom indicator's function for Fibo TimeZones restriction       |
//+------------------------------------------------------------------+
void RestrictFiboTimeZones(int bars_calculated,
                           string tf_type,
                           ENUM_TIMEFRAMES tf,
                           color clr,
                           color clr_aux
                          )
  {
   ENUM_TIMEFRAMES source_tf=tf;
   datetime Arr[];
   int pos1,BaseBandwidth;
   if(AccuracyOfCalculations)
      tf=PERIOD_M1;

   for(int objN=0; objN<ObjectsTotal(0,0,OBJ_FIBOTIMES) && !IsStopped(); objN++)
   {
      string objname=ObjectName(0,objN,0,OBJ_FIBOTIMES);
      string tf_name=StringSubstr(objname,0,4);
      if(StringTrimRight(tf_name)==1) StringSetLength(tf_name,3);
      if(tf_name==StringSubstr(EnumToString(source_tf),7)+":")
      {
         datetime TimeExtr1=(datetime)ObjectGetInteger(0,objname,OBJPROP_TIME,0);
         datetime TimeExtr2=(datetime)ObjectGetInteger(0,objname,OBJPROP_TIME,1);
         long LStyle=ObjectGetInteger(0,objname,OBJPROP_LEVELSTYLE,0);

         pos1=iBarShift(_Symbol,tf,TimeExtr1,true)+1;
         BaseBandwidth=CopyTime(_Symbol,tf,TimeExtr2,TimeExtr1,Arr);

         if(BaseBandwidth*(NumberOfFiboTimeZonesLevels+2)>=pos1)
         {
            StringConcatenate(objname,tf_type,": F TZ ",
                              TimeToString(TimeExtr1,TIME_DATE|TIME_MINUTES),"—",
                              TimeToString(TimeExtr2,TIME_DATE|TIME_MINUTES)
                             );

            bool IsRebuilt=RestrictionCore(objname,pos1,BaseBandwidth,clr,clr_aux,LStyle);

            if(EventLogging && IsRebuilt && SAGvar && bars_calculated)
               Print("{",unique_sign,"} ","1 useless restricted history-based Fibo TimeZones '",objname,"' have been usefully rebuilt.");
         }
      }
   }
  }

//+------------------------------------------------------------------+
//| Custom indicator's core function for Fibo TimeZones restriction  |
//+------------------------------------------------------------------+
bool RestrictionCore(string objname,
                     int pos1,
                     int BaseBandwidth,
                     color clr,
                     color clr_aux,
                     long LStyle
                    )
  {
   int FTZPreviousLevel=NULL;
   int FTZNextLevel=NULL;
   int FiboArray[];
   bool bool_flag=false;

   ArrayCopy(FiboArray,DefaultFTZLevels,0,2,WHOLE_ARRAY);

   for(int l=ArraySize(FiboArray)-1; l>=0; l--)
      if(FiboArray[l]!=NumberOfFiboTimeZonesLevels)
         ArrayRemove(FiboArray,l,1);
      else
         break;

   ArrayResize(FiboArray,ArraySize(FiboArray)+1);
   FiboArray[ArraySize(FiboArray)-1]=FiboArray[ArraySize(FiboArray)-1]+2;

   double OldValueFTZPreviousLevel=ObjectGetDouble(0,objname,OBJPROP_LEVELVALUE,0);

   ObjectSetInteger(0,objname,OBJPROP_LEVELCOLOR,WHOLE_ARRAY,clr);

   if((int)floor((double)pos1/(double)BaseBandwidth)>=FiboArray[0])
   {
      for(int n=0; n<ArraySize(FiboArray) && !IsStopped(); n++)
      {
         if((int)ceil((double)pos1/(double)BaseBandwidth)>=FiboArray[n])
         {
            FTZPreviousLevel=FiboArray[n];

            if(n<ArraySize(FiboArray)-2)
            {
               FTZNextLevel=FiboArray[n+1];
               ObjectSetInteger(0,objname,OBJPROP_LEVELS,2);
               ObjectSetDouble(0,objname,OBJPROP_LEVELVALUE,1,FTZNextLevel);
               ObjectSetString(0,objname,OBJPROP_LEVELTEXT,1,(string)FTZNextLevel);
               ObjectSetInteger(0,objname,OBJPROP_LEVELCOLOR,3,clr);
            }
            else
               if(n==ArraySize(FiboArray)-2)
                  ObjectSetInteger(0,objname,OBJPROP_LEVELS,1);
               else
                  ObjectSetInteger(0,objname,OBJPROP_LEVELS,0);
         }
         else break;
      }
      ObjectSetDouble(0,objname,OBJPROP_LEVELVALUE,0,FTZPreviousLevel);
      ObjectSetString(0,objname,OBJPROP_LEVELTEXT,0,(string)FTZPreviousLevel);
      if(FTZPreviousLevel==2)
         ObjectSetInteger(0,objname,OBJPROP_LEVELCOLOR,0,clr_aux);

      if(FTZPreviousLevel!=OldValueFTZPreviousLevel)
         bool_flag=true;
   }
   else
   {
      ObjectSetInteger(0,objname,OBJPROP_LEVELS,1);
      ObjectSetDouble(0,objname,OBJPROP_LEVELVALUE,0,FiboArray[0]);
      ObjectSetString(0,objname,OBJPROP_LEVELTEXT,0,(string)FiboArray[0]);
      ObjectSetInteger(0,objname,OBJPROP_LEVELCOLOR,0,clr_aux);

      if(FiboArray[0]!=OldValueFTZPreviousLevel)
         bool_flag=true;
   }
   ObjectSetInteger(0,objname,OBJPROP_LEVELSTYLE,WHOLE_ARRAY,LStyle);

   return(bool_flag);
  }

//+---------------------------------------------------------------------+
//| Custom indicator's function for removing of outdated Fibo TimeZones |
//+---------------------------------------------------------------------+
void GarbageCollectorFTZ(ENUM_TIMEFRAMES tf)
  {
   ENUM_TIMEFRAMES source_tf=tf;
   datetime Arr[];
   int pos1,BaseBandwidth;
   if(AccuracyOfCalculations)
      tf=PERIOD_M1;

   for(int objN=0; objN<ObjectsTotal(0,0,OBJ_FIBOTIMES) && !IsStopped(); objN++)
   {
      string objname=ObjectName(0,objN,0,OBJ_FIBOTIMES);
      string tf_name=StringSubstr(objname,0,4);
      if(StringTrimRight(tf_name)==1) StringSetLength(tf_name,3);
      if(tf_name==StringSubstr(EnumToString(source_tf),7)+":")
      {
         datetime TimeExtr1=(datetime)ObjectGetInteger(0,objname,OBJPROP_TIME,0);
         datetime TimeExtr2=(datetime)ObjectGetInteger(0,objname,OBJPROP_TIME,1);

         pos1=iBarShift(_Symbol,tf,TimeExtr1,true)+1;
         BaseBandwidth=CopyTime(_Symbol,tf,TimeExtr2,TimeExtr1,Arr);

         if(BaseBandwidth*(NumberOfFiboTimeZonesLevels+2)<pos1)
         {
            ObjectDelete(0,objname);
            if(EventLogging)
               Print("{",unique_sign,"} ","Expired Fibo TimeZones '",objname,"' have been removed.");
         }
      }
   }
  }
// --------------------------------------------------------------------------------------------------------------
//+--------------------------------------------------------------+
//| Custom indicator's function for building Andrew's Pitchforks |
//| or Equidistant Channels or Fibo Channels                     |
//+--------------------------------------------------------------+
void BuildAndrewsPitchforkOrChannel(double PriceExtr0,
                                    double PriceExtr1,
                                    double PriceCur,
                                    datetime TimeExtr0,
                                    datetime TimeExtr1,
                                    datetime TimeCur,
                                    int bars_calculated,
                                    string tf_type,
                                    ENUM_TIMEFRAMES tf,
                                    ENUM_OBJECT enum_obj_type,
                                    string obj_short_name,
                                    string obj_full_name,
                                    color clr,
                                    int visibility
                                   )
  {
   color c;
   string objname;
   bool RayLeft=false;

   if(enum_obj_type==OBJ_FIBOCHANNEL)
   {
      datetime TimeInterm=TimeCur;
      double PriceInterm=PriceCur;

      TimeCur=TimeExtr1;
      TimeExtr1=TimeInterm;
      PriceCur=PriceExtr1;
      PriceExtr1=PriceInterm;

      RayLeft=true;
      c=clrNONE;
   }
   else
      c=clr;

   int pos1=iBarShift(_Symbol,tf,TimeExtr0,true)+1;
   int pos2=iBarShift(_Symbol,tf,TimeCur,true)+1;
   int bandwidth=(int)((pos1-pos2)*ChannelAndPitchforkTopicality);

   if(bandwidth>=pos1)
   {
      StringConcatenate(objname,tf_type,": ",obj_short_name," ",
                        TimeToString(TimeExtr0,TIME_DATE|TIME_MINUTES),"—",
                        TimeToString(TimeCur,TIME_DATE|TIME_MINUTES),"—",
                        TimeToString(TimeExtr1,TIME_DATE|TIME_MINUTES)
                       );

      if(!ObjectFind(0,objname) &&
         (ObjectGetInteger(0,objname,OBJPROP_TIME,0)!=TimeExtr0 ||
          ObjectGetInteger(0,objname,OBJPROP_TIME,1)!=TimeCur ||
          ObjectGetInteger(0,objname,OBJPROP_TIME,2)!=TimeExtr1 ||
          ObjectGetDouble(0,objname,OBJPROP_PRICE,0)!=fabs(PriceExtr0) ||
          ObjectGetDouble(0,objname,OBJPROP_PRICE,1)!=fabs(PriceCur) ||
          ObjectGetDouble(0,objname,OBJPROP_PRICE,2)!=fabs(PriceExtr1)))
         ObjectDelete(0,objname);

      if(ObjectFind(0,objname)<0)
      {
         isBuiltAPfOrEqChOrFCh=false;

         if(EventLogging && !bars_calculated && SAGvar)
            obj_counter++;

         ObjectCreate(0,objname,enum_obj_type,0,
                      TimeExtr0,fabs(PriceExtr0),
                      TimeCur,fabs(PriceCur),
                      TimeExtr1,fabs(PriceExtr1)
                     );
      }
      else
         isBuiltAPfOrEqChOrFCh=true;

      ObjectSetInteger(0,objname,OBJPROP_STYLE,STYLE_SOLID);
      ObjectSetInteger(0,objname,OBJPROP_RAY_LEFT,RayLeft);
      ObjectSetInteger(0,objname,OBJPROP_RAY_RIGHT,RayRight);
      ObjectSetInteger(0,objname,OBJPROP_WIDTH,1);
      ObjectSetInteger(0,objname,OBJPROP_COLOR,c);
      ObjectSetInteger(0,objname,OBJPROP_LEVELSTYLE,WHOLE_ARRAY,STYLE_DOT);
      ObjectSetInteger(0,objname,OBJPROP_LEVELWIDTH,WHOLE_ARRAY,1);
      ObjectSetInteger(0,objname,OBJPROP_LEVELCOLOR,WHOLE_ARRAY,clr);
      ObjectSetInteger(0,objname,OBJPROP_TIMEFRAMES,visibility);
      ObjectSetInteger(0,objname,OBJPROP_SELECTABLE,true);

      if(EventLogging && SAGvar && bars_calculated)
         Print("{",unique_sign,"} ","1 new ",obj_full_name," '",objname,"' has been built.");
   }
  }

//+-----------------------------------------------------------------------+
//| Custom indicator's function of searching nearby fractals for building |
//| Andrew's Pitchforks or Equidistant Channels or Fibo Channels          |
//+-----------------------------------------------------------------------+
void FindNearbyFractalsForAPitchforkOrChannel(double &PriceExtr[][],
                                              double PriceCur,
                                              datetime &TimeExtr[][],
                                              datetime TimeCur,
                                              int bars_calculated,
                                              int b,
                                              string tf_type,
                                              int visibility,
                                              ENUM_TIMEFRAMES tf,
                                              ENUM_OBJECT enum_obj_type,
                                              string obj_short_name,
                                              string obj_full_name,
                                              color clr,
                                              char sign
                                             )
  {
   uchar el;

   if(PriceCur!=EMPTY_VALUE)
   {
      if(PriceExtr[b][0]==EMPTY_VALUE) el=0;
      else
      {
         if(PriceExtr[b][1]==EMPTY_VALUE)
         {
            if(PriceExtr[b][0]*PriceCur*sign<0) el=1;
            else el=0;
         }
         else
         {
            if(PriceExtr[b][1]*PriceCur*sign<0)
            {
               BuildAndrewsPitchforkOrChannel(
                  PriceExtr[b][0],PriceExtr[b][1],PriceCur,
                  TimeExtr[b][0],TimeExtr[b][1],TimeCur,
                  bars_calculated,tf_type,tf,enum_obj_type,
                  obj_short_name,obj_full_name,clr,visibility
               );

               el=1;
               PriceExtr[b][0]=PriceExtr[b][1];
               TimeExtr[b][0]=TimeExtr[b][1];
            }
            else
            {
               el=0;
               PriceExtr[b][1]=EMPTY_VALUE;
               TimeExtr[b][1]=0;
            }
         }
      }
      PriceExtr[b][el]=PriceCur*sign;
      TimeExtr[b][el]=TimeCur;
   }
  }

//+--------------------------------------------------------------+
//| Custom indicator's function for removing of outdated         |
//| Andrew's Pitchforks or Equidistant Channels or Fibo Channels |
//+--------------------------------------------------------------+
void GarbageCollectorForAPfOrEqChOrFCh(ENUM_TIMEFRAMES tf,
                                       ENUM_OBJECT enum_obj_type,
                                       string object_type
                                      )
  {
   for(int objN=0; objN<ObjectsTotal(0,0,enum_obj_type) && !IsStopped(); objN++)
   {
      string objname=ObjectName(0,objN,0,enum_obj_type);
      string tf_name=StringSubstr(objname,0,4);
      if(StringTrimRight(tf_name)==1) StringSetLength(tf_name,3);
      if(tf_name==StringSubstr(EnumToString(tf),7)+":")
      {
         datetime TimeExtr1=(datetime)ObjectGetInteger(0,objname,OBJPROP_TIME,0);
         datetime TimeExtr2=(datetime)ObjectGetInteger(0,objname,OBJPROP_TIME,1);

         int pos1=iBarShift(_Symbol,tf,TimeExtr1,true)+1;
         int pos2=iBarShift(_Symbol,tf,TimeExtr2,true)+1;
         int bandwidth=(int)((pos1-pos2)*ChannelAndPitchforkTopicality);

         if(bandwidth<pos1)
         {
            ObjectDelete(0,objname);
            if(EventLogging)
               Print("{",unique_sign,"} ","Expired ",object_type," '",objname,"' has been removed.");
         }
      }
   }
  }
// --------------------------------------------------------------------------------------------------------------
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(_UninitReason==REASON_REMOVE)
      if(EraseTheMarkupAtRemovingTheIndicator)
      {
         for(uchar p=0; p<ArraySize(IncludedTFs); p++)
            if(IncludedTFs[p]>0 && Buffer_Array[p].handle!=INVALID_HANDLE)
            {
               string tf_type=p<tf_delta ? StringSubstr(EnumToString(IncludedTFs[p]),7) :
                                           StringSubstr(IncludedVHTFs[p-tf_delta],7);

               ObjectsDeleteAll(0,tf_type+": ",0,-1);
               IndicatorRelease(Buffer_Array[p].handle);
            }
         if(Buffer_Array[NUMBER/2].handle!=INVALID_HANDLE)
            IndicatorRelease(Buffer_Array[NUMBER/2].handle);

         ChartRedraw(0);
         GlobalVariablesDeleteAll(_Symbol+" "+unique_sign+": ",0);
         Comment("");
      }
      else
         GlobalVariableSet(_Symbol+" "+unique_sign+": SingleActuation",0);

   if(_UninitReason==REASON_CHARTCLOSE)
   {
      for(uchar p=0; p<ArraySize(IncludedTFs); p++)
         if(IncludedTFs[p]>0 && Buffer_Array[p].handle!=INVALID_HANDLE)
            IndicatorRelease(Buffer_Array[p].handle);
      if(Buffer_Array[NUMBER/2].handle!=INVALID_HANDLE)
         IndicatorRelease(Buffer_Array[NUMBER/2].handle);

      GlobalVariablesDeleteAll(_Symbol+" "+unique_sign+": ",0);
   }

   if(_UninitReason==REASON_CLOSE)
   {
      for(uchar iGvarName=0; iGvarName<GlobalVariablesTotal(); iGvarName++)
      {
         string GvarName=GlobalVariableName(iGvarName);
         if(GvarName==_Symbol+" "+unique_sign+": SingleActuation")
         {
            GlobalVariableSet(GvarName,0);
            break;
         }
      }

      if(SymbolLength>MaxSymbLength || start>=end+1)
         GlobalVariablesDeleteAll(_Symbol+" "+unique_sign+": ",0);
   }

   return;
  }

Comments