//+------------------------------------------------------------------+
//|                                    smLondonCloseFiboZones_v5.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright 20.07.2016, SwingMan"
#property link      ""
#property strict
#property indicator_chart_window
//
/*--------------------------------------------------------------------
16.07.2016  v1 -  
18.07.2016  v3 -  Corrections
18.07.2016  v4 -  bug: freezing for broker with sunday prices
20.07.2016  v5 -  GMT Offset as string "5:30" for India / @ramzam
--------------------------------------------------------------------*/

//---- extern inputs
//+------------------------------------------------------------------+
input string GMT_FirstTime ="21:00";
input string GMT_SecondTime="20:45";
input string GMT_Offset_ServerHours="04:00";
input bool Draw_First_VerticalLine =false;
input bool Draw_Second_VerticalLine=false;
input color Color_VerticalLine=clrBlue;
input string ___Fibo_Levels="--------------------------------------------";
input int FiboLevels_Number=5;
input string Fibo_Levels_1="0.000,0.236,0.764,1.000";
input string Fibo_Levels_2="-0.236,0.000,0.236,0.764,1.000,1.236";
input string Fibo_Levels_3="-0.382,-0.236,0.000,0.236,0.764,1.000,1.236,1.382";
input string Fibo_Levels_4="-0.500,-0.382,-0.236,0.000,0.236,0.382,0.618,0.764,1.000,1.236,1.382,1.500";
input string Fibo_Levels_5="-4.232,-2.618,-1.618,-1.000,-0.618,-0.500,-0.382,-0.236,0.000,0.236,0.382,0.500,0.618,0.764,1.000,1.236,1.382,1.500,1.618,2.618,4.232";
//
input string ___Fibo_Retracements="--------------------------------------------";
input int Daily_Back_Drawing           =3;
input color            FiboLine_Color  =clrDarkViolet;
input ENUM_LINE_STYLE  FiboLine_Style  =STYLE_SOLID;
input int              FiboLine_Width  =2;
//
input color            FiboLevels_Color=C'42,42,42';
input ENUM_LINE_STYLE  FiboLevels_Style=STYLE_DOT;
input int              FiboLevels_Width=1;
//
input color            FiboText_Color   =C'42,42,42';
input string           FiboText_Font    ="Century Gothic";
input int              FiboText_FontSize=7;
//
input color            FiboAreaBuy_Color =C'17,72,17';  // clrDarkGreen;
input color            FiboAreaSell_Color= C'100,0,0' ; //clrMaroon;
//+------------------------------------------------------------------+

//---- constants
#define sep ","
ushort  u_sep=StringGetCharacter(sep,0);
string CR="\n";
bool Draw_OnlyOnNewBars=true;

//---- level values
string sFiboLevels[];
double arrLevels[];
int numLevels;
//double arrLevels[]={-0.382,-0.236,0.000,0.236,0.382,0.500,0.618,0.764,1.000,1.236,1.382};
//---- variables
datetime oldTime1,oldTime2,oldBarTime;
double oldPrice1,oldPrice2;
string sName="Fibo_";
bool bCalculateBarsBack=true;

//---- fibo parameters
datetime timeBegin,timeEnd;
int barBegin,barEnd;
double priceBegin,priceEnd;
//
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   switch(FiboLevels_Number)
     {
      case 1: numLevels=StringSplit(Fibo_Levels_1,u_sep,sFiboLevels); break;
      case 2: numLevels=StringSplit(Fibo_Levels_2,u_sep,sFiboLevels); break;
      case 3: numLevels=StringSplit(Fibo_Levels_3,u_sep,sFiboLevels); break;
      case 4: numLevels=StringSplit(Fibo_Levels_4,u_sep,sFiboLevels); break;
      case 5: numLevels=StringSplit(Fibo_Levels_5,u_sep,sFiboLevels); break;
     }
   ArrayResize(arrLevels,numLevels);

   for(int i=0;i<numLevels;i++)
     {
      arrLevels[i]=StringToDouble(sFiboLevels[i]);
     }

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int deinit()
  {
   ObjectsDeleteAll(0,sName);
   Comment("");
   return(0);
  }
//+------------------------------------------------------------------+
//| 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 thisBarTime;
   bool calculationOK=true;
   int ib=1;

//-- draw fibo lines for X daily back ---------------------
   if(Daily_Back_Drawing>0 && bCalculateBarsBack==true && Volume[0]>0)
     {
      while(ib<=Daily_Back_Drawing)
        {
         datetime dailyTime=iTime(Symbol(),PERIOD_D1,ib);
         if(TimeDayOfWeek(dailyTime)!=SATURDAY && TimeDayOfWeek(dailyTime)!=SUNDAY)
           {
            Draw_DailyFiboLines(dailyTime);
           }
         ib++;
        }
      bCalculateBarsBack=false;
     }

//---- main loop 
   int limit;
   int counted_bars=IndicatorCounted();
   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;

   int i=0;
   thisBarTime=Time[i];
//thisBarTime=D'2016.07.15 00:00';
//for(int i=0; i<limit; i++)
     {
      if(Draw_OnlyOnNewBars==true)
        {
         //thisBarTime=Time[i];
         if(thisBarTime!=oldBarTime)
           {
            oldBarTime=thisBarTime;
            calculationOK=true;
           }
         else
            calculationOK=false;
        }
      else
         calculationOK=true;

      //-- draw fibo lines for the current day ------------------
      if(calculationOK==true && Volume[i]>0)
        {
         Draw_DailyFiboLines(thisBarTime);
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Draw_DailyFiboLines(datetime timeD)
  {
   double price1,price2;

   Get_CurrentTime(timeD);
   Get_FiboData(timeBegin,timeEnd,barBegin,barEnd,price1,price2);

   Comment(
           WindowExpertName(),CR,
           "==================",CR,
           "GMT_Offset_ServerHours= ",GMT_Offset_ServerHours,CR,
           "GMT     Time= ",TimeToString(TimeGMT()),CR,
           "Server  Time= ",TimeToString(TimeCurrent()),CR,
           "Local     Time= ",TimeToString(TimeLocal()),CR,
           //"Current Time= ",TimeToString(timeD),CR,
           "FiboTimeBegin= ",TimeToString(timeBegin),CR,
           "FiboTimeEnd  = ",TimeToString(timeEnd)
           //"barBegin= ",DoubleToString(barBegin,0),CR,
           //"barEnd  = ",DoubleToString(barEnd,0),CR,
           //"price1  = ",DoubleToString(price1,Digits),CR,
           //"price2  = ",DoubleToString(price2,Digits)
           );

   Set_FiboRetracement(timeBegin,price1,timeEnd,price2);

   Set_FiboAreas(timeBegin,price1,timeEnd,price2);
   
   color dColor=clrBlue;
   int iStyle=STYLE_SOLID;
   int iWidth=1;
   string objName;
   
   if(Draw_First_VerticalLine)
   {
      objName=sName+"VertLine"+"_"+TimeToString(timeBegin);
      Draw_VerticalLine(objName,timeBegin,dColor,iStyle,iWidth);
   }
   
   if(Draw_Second_VerticalLine)
  {
      objName=sName+"VertLine"+"_"+TimeToString(timeEnd);
      Draw_VerticalLine(objName,timeEnd,dColor,iStyle,iWidth);
  }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Get_CurrentTime(datetime time2)
  {
   string sCurrentDay;

//-- time difference for server/GMT
   datetime timeGMT       =TimeGMT();
   datetime timeServer    =TimeCurrent();

   datetime timeGmtOffset =StringToTime(GMT_Offset_ServerHours);
   int timeHour  =TimeHour(timeGmtOffset);
   int timeMinute=TimeMinute(timeGmtOffset);
   
   datetime timeDifference=timeHour*60*60+timeMinute*60;
   
//-- 1. get last bar -----------------------------------------
   datetime timeCheck=time2;

   sCurrentDay=TimeToString(timeCheck); //#2016.06.19 #
   sCurrentDay=StringSubstr(sCurrentDay,0,11);

   datetime timeEnd0=StringToTime(sCurrentDay+GMT_SecondTime); //-- 16:00
   int      barEnd0 =iBarShift(Symbol(),Period(),timeEnd0,false);

   //timeEnd=timeEnd0+timeDifference-Period()*60;               //-- 18:45
   timeEnd=timeEnd0+timeDifference;                             //-- 18:45
   barEnd=iBarShift(Symbol(),Period(),timeEnd,false);

//-- 2. get first bar ----------------------------------------
   bool firstTimeOK=false;
   datetime limitTime;
   datetime timeBegin0=0;

   int iBar=barEnd0;

   while(firstTimeOK==false)
     {
      iBar++;
      timeCheck=iTime(Symbol(),Period(),iBar);           //-- 17:45, 17:30, 17:15 etc.

      sCurrentDay=TimeToString(timeCheck);
      sCurrentDay=StringSubstr(sCurrentDay,0,11);
      limitTime=StringToTime(sCurrentDay+GMT_FirstTime); //... 01:30, 01:15, 01:00

      if(limitTime<timeEnd0)
        {
         if(timeCheck>=limitTime)
           {
            timeBegin0=timeCheck;
           }
         else
            firstTimeOK=true;
        }
     }
   if(TimeDayOfWeek(timeCheck)==FRIDAY)
      timeBegin=timeBegin0+timeDifference+2*24*60*60;
   else
      timeBegin=timeBegin0+timeDifference;
   barBegin=iBarShift(Symbol(),Period(),timeBegin,false);

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Get_FiboData(datetime time1,datetime time2,int bar1,int bar2,double &price1,double &price2)
  {
   int barLow,barHigh;
   double minLow,maxHigh;
   double dLow,dHigh;

//---- find lower low / higher high ---------------------------------
   barLow =bar1;
   barHigh=bar1;
   minLow =iLow(Symbol(),Period(),bar1);
   maxHigh=iHigh(Symbol(),Period(),bar1);
   for(int iBar=bar1;iBar>=bar2;iBar--)
     {
      dLow =iLow(Symbol(),Period(),iBar);
      dHigh=iHigh(Symbol(),Period(),iBar);
      if(dLow<minLow)
        {
         minLow=dLow;
         barLow=iBar;
        }
      if(dHigh>maxHigh)
        {
         maxHigh=dHigh;
         barHigh=iBar;
        }
     }

//---- fibo data
   if(barLow>barHigh)
     {
      price1=minLow;
      price2=maxHigh;
     }
   else
     {
      price1=maxHigh;
      price2=minLow;
     }
   return;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Set_FiboRetracement(datetime time1,double price1,datetime time2,double price2)
  {
//-- adjust time2  
   if(time2>iTime(Symbol(),Period(),0))
      time2=iTime(Symbol(),Period(),0);

   string obName;
//-- 1. Fibo Line   ---------------------------------------
   obName=sName+"Line_"+TimeToString(time1);
   Draw_TrendLine(obName,time1,price1,time2,price2,
                  FiboLine_Color,FiboLine_Style,FiboLine_Width);

//-- 2. Fibo Levels ---------------------------------------
   double minPrice,levelPrice;
   double diffPrice=MathAbs(price1-price2);
   if(price1<price2) minPrice=price1; else minPrice=price2;

   for(int i=0;i<numLevels;i++)
     {
      obName=sName+"Level"+(string)i+"_"+TimeToString(time1);
      levelPrice=minPrice+diffPrice*arrLevels[i];
      Draw_TrendLine(obName,time1,levelPrice,time2,levelPrice,
                     FiboLevels_Color,FiboLevels_Style,FiboLevels_Width);
     }

//-- 3. Fibo Percents Text --------------------------------
   string sText;
   for(int i=0;i<numLevels;i++)
     {
      obName=sName+"Percent"+(string)i+"_"+TimeToString(time1);
      levelPrice=minPrice+diffPrice*arrLevels[i];
      sText="("+DoubleToString(arrLevels[i]*100.0,1)+") "+DoubleToString(levelPrice,Digits);
      Draw_Text(obName,sText,time2,levelPrice,
                FiboText_Color,FiboText_Font,FiboText_FontSize);
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Set_FiboAreas(datetime time1,double price1,datetime time2,double price2)
  {
//-- adjust time2  
   if(time2>iTime(Symbol(),Period(),0))
      time2=iTime(Symbol(),Period(),0);

   double p1,p2,pUP,pDN;
   string objX;

   string obName=sName+"Area_"+TimeToString(time1);

//-- upper rectangle 
   if(price1>price2)
     {
      p1=price1;
      p2=price2;
     }
   else
     {
      p1=price2;
      p2=price1;
     }
   double diffPrice=MathAbs(price1-price2)*0.236;
   pUP=p1-diffPrice;
   pDN=p2+diffPrice;

//-- upper rectangle
   objX=obName+"-UP";
   ObjectDelete(objX);
   ObjectCreate(objX,OBJ_RECTANGLE,0,time1,p1,time2,pUP);
   ObjectSet(objX,OBJPROP_COLOR,FiboAreaSell_Color);
   ObjectSet(objX,OBJPROP_STYLE,STYLE_SOLID);
   ObjectSet(objX,OBJPROP_BACK,true);

//-- lower rectangle 
   objX=obName+"-DN";
   ObjectDelete(objX);
   ObjectCreate(objX,OBJ_RECTANGLE,0,time1,p2,time2,pDN);
   ObjectSet(objX,OBJPROP_COLOR,FiboAreaBuy_Color);
   ObjectSet(objX,OBJPROP_STYLE,STYLE_SOLID);
   ObjectSet(objX,OBJPROP_BACK,true);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Draw_TrendLine(string objX,datetime dTime1,double dPrice1,
                    datetime dTime2,double dPrice2,
                    color dColor,int iStyle,int iWidth)
  {
   ObjectDelete(objX);

   ObjectCreate(objX,OBJ_TREND,0,dTime1,dPrice1,dTime2,dPrice2);
   ObjectSet(objX,OBJPROP_COLOR,dColor);
   ObjectSet(objX,OBJPROP_STYLE,iStyle);
   ObjectSet(objX,OBJPROP_WIDTH,iWidth);
   ObjectSet(objX,OBJPROP_RAY,false);
   ObjectSet(objX,OBJPROP_BACK,true);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Draw_VerticalLine(string objX,datetime dTime1,color dColor,int iStyle,int iWidth)
  {
   ObjectDelete(objX);

   ObjectCreate(objX,OBJ_VLINE,0,dTime1,0);
   ObjectSet(objX,OBJPROP_COLOR,dColor);
   ObjectSet(objX,OBJPROP_STYLE,iStyle);
   ObjectSet(objX,OBJPROP_WIDTH,iWidth);
   ObjectSet(objX,OBJPROP_RAY,false);
   ObjectSet(objX,OBJPROP_BACK,true);
   ObjectSet(objX,OBJPROP_SELECTABLE,true);   
   ObjectSet(objX,OBJPROP_SELECTED,false);
  }  
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Draw_Text(string objX,string text,datetime time,double price,
               color dColor,string font,int font_size)
  {
   ObjectDelete(objX);

   ObjectCreate(objX,OBJ_TEXT,0,time,price);
   ObjectSetString(0,objX,OBJPROP_TEXT,text);
   ObjectSetString(0,objX,OBJPROP_FONT,font);
   ObjectSet(objX,OBJPROP_FONTSIZE,font_size);
   ObjectSet(objX,OBJPROP_COLOR,dColor);
   ObjectSet(objX,OBJPROP_BACK,false);
   ObjectSet(objX,OBJPROP_ANCHOR,ANCHOR_LOWER);
   ObjectSet(objX,OBJPROP_ALIGN,ALIGN_RIGHT);
  }
//+------------------------------------------------------------------+
