//+------------------------------------------------------------------+
//|                                           ExtendedMarketOpen.mq4 |
//+------------------------------------------------------------------+
#property copyright ""
#property link      "https://www.freelancer.com/u/financialcris.html"
#property version   "1.00"
#property strict
#property indicator_chart_window

//--- input parameters
input int      Duration=48;               // Duration Hours
input int      MaxDaysBack=3;             // Maximum Days Back

input int      GermanyOpen=9;             // Germany Open Time
input color    GermanyColor=clrBlue;      // Germany Color
input int      GermanyLineWidth=1;        // Germany Line Witdh
input int      GermanyLineStyle=2;        // Germany Line Style (0=Solid; 1=Dash; 2=Dot; 3=Ds/Dt; 4=Ds/Dt/Ds)

input int      LondonOpen=10;             // London Open Time
input color    LondonColor=clrGreen;      // London Color
input int      LondonLineWidth=1;         // London Line Witdh
input int      LondonLineStyle=2;         // London Line Style (0=Solid; 1=Dash; 2=Dot; 3=Ds/Dt; 4=Ds/Dt/Ds)

input int      USOpen=15;                 // US Open Time
input color    USColor=clrCrimson;        // US Color
input int      USLineWidth=1;             // US Line Witdh
input int      USLineStyle=2;             // US Line Style (0=Solid; 1=Dash; 2=Dot; 3=Ds/Dt; 4=Ds/Dt/Ds)

input int      AsiaOpen=3;                // Asia Open Time
input color    AsiaColor=clrDarkOrange;   // Asia Color
input int      AsiaLineWidth=1;           // Asia Line Witdh
input int      AsiaLineStyle=2;           // Asia Line Style (0=Solid; 1=Dash; 2=Dot; 3=Ds/Dt; 4=Ds/Dt/Ds)

input int      Custom1Open=12;            // Custom #1 Open Time
input color    Custom1Color=clrGold;      // Custom #1 Color
input int      Custom1LineWidth=1;        // Custom #1 Line Witdh
input int      Custom1LineStyle=2;        // Custom #1 Line Style (0=Solid; 1=Dash; 2=Dot; 3=Ds/Dt; 4=Ds/Dt/Ds)
input string   CustomName1="Market 1";    // Custom #1 Description

input int      Custom2Open=18;            // Custom #2 Open Time
input color    Custom2Color=clrBisque;    // Custom #2 Color
input int      Custom2LineWidth=1;        // Custom #2 Line Witdh
input int      Custom2LineStyle=2;        // Custom #2 Line Style (0=Solid; 1=Dash; 2=Dot; 3=Ds/Dt; 4=Ds/Dt/Ds)
input string   CustomName2="Market 2";    // Custom #2 Description

input bool     GermanyActive=true;        // Germany Enabled
input bool     LondonActive=true;         // London Enabled
input bool     USActive=true;             // US Enabled
input bool     AsiaActive=true;           // Asia Enabled
input bool     Custom1Active=false;       // Custom #1 Enabled
input bool     Custom2Active=false;       // Custom #2 Enabled

input bool     TodayHLActive=true;        // Today's High/Low Enabled
input color    TodayColorHigh=clrGreen;   // Today's High Color
input color    TodayColorLow=clrGreen;    // Today's Low Color
input int      TodayHLStyle=0;            // Today's High/Low Line Style
input int      TodayHLWidth=2;            // Today's High/Low Line Width

input bool     YesterdayHighLowActive=true;  // Yesterday's High/Low Enabled
input color    YesterdayColorHigh=clrRed;    // Yesterday's High Color
input color    YesterdayColorLow=clrRed;     // Yesterday's Low Color
input int      YesterdayHLStyle=0;           // Yesterday's High/Low Line Style
input int      YesterdayHLWidth=2;           // Yesterday's High/Low Line Width

input bool     AllowSelect=false;         // Allow Lines Select

// Buffers
double dLondonBuffer[];
double dID[];

#define STRID "EXTMRKOPNLINE"
int LineCounter;

//+------------------------------------------------------------------+
//| Delete all plotted text lines from the chart
//+------------------------------------------------------------------+
void ClearObjs()
{
   int obj_total= ObjectsTotal();
   
   for (int i= obj_total; i>=0; i--) 
   {
      string name= ObjectName(i);
      if (StringFind(name,STRID,0)!=-1)
         ObjectDelete(name);
   }   
   LineCounter = 0;   
}

//+------------------------------------------------------------------+
void PlotMarketLineAt(int PIndex, color PColor, string PComment,
               int PLineStyle, int PLineWidth)
{
   datetime FCloseDT = Time[PIndex]+60*60*Duration;

   int ExactShift = iBarShift(NULL,0,FCloseDT,true);
   int NearestShift = iBarShift(NULL,0,FCloseDT,false);   

   // ---  process unexisting bars because of weekend ..
   
   if (ExactShift==-1 && TimeDayOfWeek(Time[NearestShift])==5)
      {
         FCloseDT = FCloseDT+60*60*24*2; // add 2 days for weekend & try again
         ExactShift = iBarShift(NULL,0,FCloseDT,true);
         NearestShift = iBarShift(NULL,0,FCloseDT,false);   
      }
  
   if (ExactShift==-1)
      FCloseDT = Time[NearestShift];

   LineCounter++;
   string FObjName = STRID+IntegerToString(LineCounter);
      
   if (ObjectFind(0,FObjName)<0)
      ObjectCreate(0,FObjName,OBJ_TREND,0,0,0);
      
   ObjectSet(FObjName,OBJPROP_PRICE1, Open[PIndex]);
   ObjectSet(FObjName,OBJPROP_PRICE2, Open[PIndex]);
   ObjectSet(FObjName,OBJPROP_TIME1, Time[PIndex]);   
   ObjectSet(FObjName,OBJPROP_TIME2, FCloseDT);   
   ObjectSet(FObjName,OBJPROP_RAY, false);
   ObjectSet(FObjName,OBJPROP_COLOR, PColor);
   ObjectSet(FObjName,OBJPROP_WIDTH, PLineWidth);
   ObjectSet(FObjName,OBJPROP_STYLE, PLineStyle);
   ObjectSet(FObjName,OBJPROP_SELECTABLE, AllowSelect);
   ObjectSetString(0,FObjName,OBJPROP_TOOLTIP, PComment+" Open @ "+TimeToStr(Time[PIndex]));   
}

//+------------------------------------------------------------------+
void PlotHighLowAt(int PIndex, int PToIdx, double PHigh, double PLow,
                     color PColorH, color PColorL, string PCommentH, 
                     string PCommentL, int PLineStyle, int PLineWidth)
{
   //--- High 
   string FObjNameH = STRID+"H"+TimeToString(Time[PIndex],TIME_DATE);
   if (ObjectFind(0,FObjNameH)<0)
         ObjectCreate(0,FObjNameH,OBJ_TREND,0,0,0);
   ObjectSet(FObjNameH,OBJPROP_PRICE1, PHigh);
   ObjectSet(FObjNameH,OBJPROP_PRICE2, PHigh);
   ObjectSet(FObjNameH,OBJPROP_TIME1, Time[PIndex]);   
   ObjectSet(FObjNameH,OBJPROP_TIME2, Time[PToIdx]);   
   ObjectSet(FObjNameH,OBJPROP_RAY, false);
   ObjectSet(FObjNameH,OBJPROP_COLOR, PColorH);
   ObjectSet(FObjNameH,OBJPROP_WIDTH, PLineWidth);
   ObjectSet(FObjNameH,OBJPROP_STYLE, PLineStyle);
   ObjectSet(FObjNameH,OBJPROP_SELECTABLE, AllowSelect);
   ObjectSetString(0,FObjNameH,OBJPROP_TOOLTIP, PCommentH+" = "+DoubleToStr(PHigh,Digits));   
      
   //--- Low 
   string FObjNameL = STRID+"L"+TimeToString(Time[PIndex],TIME_DATE);
  if (ObjectFind(0,FObjNameL)<0)
         ObjectCreate(0,FObjNameL,OBJ_TREND,0,0,0);
   ObjectSet(FObjNameL,OBJPROP_PRICE1, PLow);
   ObjectSet(FObjNameL,OBJPROP_PRICE2, PLow);
   ObjectSet(FObjNameL,OBJPROP_TIME1, Time[PIndex]);   
   ObjectSet(FObjNameL,OBJPROP_TIME2, Time[PToIdx]);   
   ObjectSet(FObjNameL,OBJPROP_RAY, false);
   ObjectSet(FObjNameL,OBJPROP_COLOR, PColorL);
   ObjectSet(FObjNameL,OBJPROP_WIDTH, PLineWidth);
   ObjectSet(FObjNameL,OBJPROP_STYLE, PLineStyle);
   ObjectSet(FObjNameL,OBJPROP_SELECTABLE, AllowSelect);
   ObjectSetString(0,FObjNameL,OBJPROP_TOOLTIP, PCommentL+" = "+DoubleToStr(PLow,Digits));   
}

//------------------------------------------------------------------------------
int FirstBarOfDay(int PIndex)
{
   int p_d = -1;
   int i = PIndex;
   MqlDateTime dt;
   
   do 
     {
      TimeToStruct(Time[i],dt);
        if (dt.day != p_d && p_d != -1)
           return(i-1);
      i++;
      p_d = dt.day;
     }
     while (i<Bars);
   return(-1);
}

//------------------------------------------------------------------------------
int GetLimitFromDays(int PDays)
{
   int j=-1;
   for (int i=0;i<=PDays;i++)
      j=FirstBarOfDay(j+1);
   return(j);
}


//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   ClearObjs();
}

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   IndicatorShortName("Extended Market Open Lines");
   LineCounter = 0;
//---
   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[])
  {
//---
   int limit = rates_total - prev_calculated;
   int MaxBar = GetLimitFromDays(MaxDaysBack);
   if (MaxBar>0 && MaxBar<limit) limit=MaxBar;
   
   // -- plot history
   if (prev_calculated==0)
      for (int i=0;i<limit;i++)
      {   
         if (LondonActive)
            if (TimeHour(Time[i])==LondonOpen && TimeMinute(Time[i])==0)
                PlotMarketLineAt(i, LondonColor, "London", LondonLineStyle, LondonLineWidth);

         if (USActive)
            if (TimeHour(Time[i])==USOpen && TimeMinute(Time[i])==0)
                PlotMarketLineAt(i, USColor, "US", USLineStyle, USLineWidth);

         if (GermanyActive)
            if (TimeHour(Time[i])==GermanyOpen && TimeMinute(Time[i])==0)
                PlotMarketLineAt(i, GermanyColor, "Germany", GermanyLineStyle, GermanyLineWidth);

         if (AsiaActive)
            if (TimeHour(Time[i])==AsiaOpen && TimeMinute(Time[i])==0)
                PlotMarketLineAt(i, AsiaColor, "Asia", AsiaLineStyle, AsiaLineWidth);

         if (Custom1Active)
            if (TimeHour(Time[i])==Custom1Open && TimeMinute(Time[i])==0)
                PlotMarketLineAt(i, Custom1Color, CustomName1, Custom1LineStyle, Custom1LineWidth);
            
         if (Custom2Active)
         if (TimeHour(Time[i])==Custom2Open && TimeMinute(Time[i])==0)
             PlotMarketLineAt(i, Custom2Color, CustomName2, Custom2LineStyle, Custom2LineWidth);
      }

   // Current day's HIGH/LOWs
   int CDFB = FirstBarOfDay(0); 
   PlotHighLowAt(0, CDFB, High[iHighest(NULL,0,MODE_HIGH,CDFB,0)], 
                          Low[iLowest(NULL,0,MODE_LOW,CDFB,0)],
                          TodayColorHigh, TodayColorLow, 
                          "Today High","Today Low",
                          TodayHLStyle,TodayHLWidth);

   // Previous day's HIGH/LOWs

   int PDFB = FirstBarOfDay(CDFB+1); 
   PlotHighLowAt(CDFB+1, PDFB, High[iHighest(NULL,0,MODE_HIGH,PDFB-CDFB,CDFB+1)], 
                          Low[iLowest(NULL,0,MODE_LOW,CDFB-CDFB,CDFB+1)],
                          YesterdayColorHigh, YesterdayColorLow, 
                          "Yesterday High", "Yesterday Low",
                          YesterdayHLStyle,YesterdayHLWidth);

//--- return value of prev_calculated for next call
   return(rates_total);
  }




