//+------------------------------------------------------------------+
//|                                                   Session HL.mq4 |
//|                                                           extraw |
//|                                                extraww@gmail.com |
//+------------------------------------------------------------------+
#property copyright "extraw"
#property link      "extraww@gmail.com"
#property version   "1.01"
#property strict
#property indicator_chart_window
enum Style
{
   Style_Solid       = 0,    //Solid
   Style_Dash        = 1,    //Dash
   Style_Dot         = 2,    //Dot
   Style_DashDot     = 3,    //DashDot
   Style_DashDotDot  = 4     //DashDotDot
};
enum Width
{
   Width_1 = 1,    //1
   Width_2 = 2,    //2
   Width_3 = 3,    //3
   Width_4 = 4,    //4
   Width_5 = 5     //5
};
//--- input parameters
input string      SessionBegin      = "06:00";
input string      SessionEnd        = "10:00";
input color       HiLineColor       = clrRed;
input color       LoLineColor       = clrDarkOrange;
input Style       LineStyle         = 0;
input Width       LineWidth         = 2;
input bool        LineInBackground  = true;
input bool        LineRay           = false;
input int         Lookback_Days     = 5;
input string      __                = "==================================";
input string      SessionLineBegin         = "3:45";
input string      SessionLineEnd           = "11:45";
input color       SessionLineColor         = clrYellow;
input Style       SessionLineStyle         = 0;
input Width       SessionLineWidth         = 1;
input bool        SessionLineInBackground  = true;
input bool        SessionLineRay           = false;


//--- variables
string prefix;
datetime session_begin, session_end, session_line_begin, session_line_end;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
      prefix = "[SsHL]_" + SessionBegin + "_" + SessionEnd + "_" + SessionLineBegin + "_" + SessionLineEnd + "_";
      
      session_begin = StrToTime(SessionBegin);
      session_end = StrToTime(SessionEnd);
      
      if (session_end == session_begin) session_end += PeriodSeconds(PERIOD_D1);
      
      session_line_begin = StrToTime(SessionLineBegin);
      session_line_end = StrToTime(SessionLineEnd);
      
      if (session_line_begin == session_line_end) session_line_end += PeriodSeconds(PERIOD_D1);
      
//---
   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[])
  {
//---
      if (Period() >= PERIOD_D1) return(0);
      
      DeleteAllLines();
      
      string name;
      double hi, lo, price_session_line;
      int bar_begin, bar_end, bars_count, bar_session_line_begin;
      datetime this_session_begin, this_session_end, this_session_line_begin, this_session_line_end;

      int days_count = 0;
      int i = 0;
      
      while (days_count <= Lookback_Days)
      {
         this_session_begin = session_begin - i * PeriodSeconds(PERIOD_D1);
         this_session_end = session_end - i * PeriodSeconds(PERIOD_D1);

         while (IsWeekend(this_session_begin) == true && IsWeekend(this_session_end) == true)      
         {
            i++;
            this_session_begin = session_begin - i * PeriodSeconds(PERIOD_D1);
            this_session_end = session_end - i * PeriodSeconds(PERIOD_D1);
         }      
         
         
         bar_begin = iBarShift(NULL, 0, this_session_begin, false);
         bar_end = iBarShift(NULL, 0, this_session_end, false);
         bars_count = bar_begin - bar_end;
         
         if (bar_end == 0) // in case current session not complete, update the hi/lo to lastest candle
         {
            hi = iHigh(NULL, 0, iHighest(NULL, 0, MODE_HIGH, bars_count, bar_end));  
            lo = iLow(NULL, 0, iLowest(NULL, 0, MODE_LOW, bars_count, bar_end));
         }
         else // case session complete, hi/lo before lastest candle
         {
            hi = iHigh(NULL, 0, iHighest(NULL, 0, MODE_HIGH, bars_count, bar_end + 1));  
            lo = iLow(NULL, 0, iLowest(NULL, 0, MODE_LOW, bars_count, bar_end + 1));
         }
         
         name = prefix + IntegerToString(i) + "hi";
         ObjectCreate(0, name, OBJ_TREND, 0, this_session_begin, hi, this_session_end, hi);
         ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
         ObjectSetInteger(0, name, OBJPROP_COLOR, HiLineColor);
         ObjectSetInteger(0, name, OBJPROP_STYLE, LineStyle);
         ObjectSetInteger(0, name, OBJPROP_WIDTH, LineWidth);
         ObjectSetInteger(0, name, OBJPROP_BACK, LineInBackground);
         ObjectSetInteger(0, name, OBJPROP_RAY, LineRay);
         
         
         name = prefix + IntegerToString(i) + "lo";
         ObjectCreate(0, name, OBJ_TREND, 0, this_session_begin, lo, this_session_end, lo);
         ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
         ObjectSetInteger(0, name, OBJPROP_COLOR, LoLineColor);
         ObjectSetInteger(0, name, OBJPROP_STYLE, LineStyle);
         ObjectSetInteger(0, name, OBJPROP_WIDTH, LineWidth);
         ObjectSetInteger(0, name, OBJPROP_BACK, LineInBackground);
         ObjectSetInteger(0, name, OBJPROP_RAY, LineRay);
         
         // draw line session
         this_session_line_begin = session_line_begin - i * PeriodSeconds(PERIOD_D1);
         this_session_line_end = session_line_end - i * PeriodSeconds(PERIOD_D1);
         bar_session_line_begin = iBarShift(NULL, 0, this_session_line_begin, false);
         price_session_line = iOpen(NULL, 0, bar_session_line_begin);
         
         name = prefix + IntegerToString(i) + "ss_line";
         ObjectCreate(0, name, OBJ_TREND, 0, this_session_line_begin, price_session_line, this_session_line_end, price_session_line, false);
         ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
         ObjectSetInteger(0, name, OBJPROP_COLOR, SessionLineColor);
         ObjectSetInteger(0, name, OBJPROP_STYLE, SessionLineStyle);
         ObjectSetInteger(0, name, OBJPROP_WIDTH, SessionLineWidth);
         ObjectSetInteger(0, name, OBJPROP_BACK, SessionLineInBackground);
         ObjectSetInteger(0, name, OBJPROP_RAY, SessionLineRay);
         
         days_count++;
         i++;
      }
      
      
//--- return value of prev_calculated for next call
   return(rates_total);
  }

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   DeleteAllLines();
}
  
void DeleteAllLines()
{
   int prefix_length = StringLen(prefix);
   int obj_total=ObjectsTotal();
   for(int i=obj_total; i>=0; i--)
     {
      string name=ObjectName(i);
      if(StringSubstr(name,0,prefix_length)==prefix)
         ObjectDelete(name);
     }
   return;
}  

bool IsWeekend(datetime date)
{
   int date_number = TimeDayOfWeek(date);
   switch(date_number)
   {
      case 0: return true;
      case 6: return true;
   }
   return false;
}