//+------------------------------------------------------------------+
//|                                                 i-SessionsLn.mq4 |
//|                        Version 2 - Update by 2010 Simon Kaufmann |
//|                                                                  |
//|                                                                  |
//|  16.11.2005  original version                                    |
//|  10.06.2010  bug fixes and updates                               |
//+------------------------------------------------------------------+

#property copyright ""
#property link      ""

#property indicator_chart_window

//------- external parameters -------------------------------
extern int    NumberOfDays = 13;        // Number of days to lookback
extern string AsiaBegin    = "17:00";   // Start time of Asian session in your brokers time 
extern string AsiaEnd      = "05:00";   // End time of Asian session in your brokers time
extern color  AsiaColor    = Tan;       // Color for Asian Session box
extern string EurBegin     = "03:00";   // Start time of European session in your brokers time
extern string EurEnd       = "12:00";   // End time of European session in your brokers time
extern color  EurColor     = IndianRed; // Color for European Session box
extern string USABegin     = "08:00";   // Start time of New York session in your brokers time
extern string USAEnd       = "17:00";   // Endtime of New York session in your brokers time
extern color  USAColor     = CornflowerBlue; // Color for New York session box
extern bool   ShowPrice    = True;      // Show latest session price range
extern color  clFont       = Snow;   // font color for prices

extern bool  AsiaBg     = false;        // background on/off
extern int   AsiaLn     = 2;            // linestyle 0/4
extern bool  EurBg      = false;        // background on/off
extern int   EurLn      = 2;            // linestyle 0/4
extern bool  USABg      = false;        // background on/off
extern int   USALn      = 2;            // linestyle 0/4

extern int    SizeFont  = 8;            // price font size
extern int    OffSet    = 10;           // price position

datetime dt, time, prevtime;
bool done;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void init() 
{
  DeleteObjects();
  for (int i=0; i<NumberOfDays; i++) {
    CreateObjects("AS"+i, AsiaColor,AsiaBg,AsiaLn);
    CreateObjects("EU"+i, EurColor,EurBg,EurLn);
    CreateObjects("US"+i, USAColor,USABg,USALn);
  }
  done = false;
  Comment("");
}

//+------------------------------------------------------------------+
//| Custor indicator deinitialization function                       |
//+------------------------------------------------------------------+
void deinit() {
  DeleteObjects();
  Comment("");
}

//+------------------------------------------------------------------+
//| void CreateObjects()                                             |
//| Inputs   :                                                       |
//|   no - string object identifier                                  |
//|   cl - session color                                             |
//+------------------------------------------------------------------+
void CreateObjects(string no, color cl,int bg,int ln) 
{
  ObjectCreate(no, OBJ_RECTANGLE, 0, 0,0, 0,0);
  ObjectSet(no, OBJPROP_COLOR, cl);
  ObjectSet(no, OBJPROP_STYLE, ln);
  ObjectSet(no, OBJPROP_BACK,  bg);
}

//+------------------------------------------------------------------+
//| void DeleteObject()                                              |
//+------------------------------------------------------------------+
void DeleteObjects() 
{
  for (int i=0; i<NumberOfDays; i++) 
  {
    ObjectDelete("AS"+i);
    ObjectDelete("EU"+i);
    ObjectDelete("US"+i);
  }
  ObjectDelete("ASup");
  ObjectDelete("ASdn");
  ObjectDelete("EUup");
  ObjectDelete("EUdn");
  ObjectDelete("USup");
  ObjectDelete("USdn");
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
void start() 
{ 
  if (Period() > PERIOD_H4)
  { return; }
  
  time = iTime(NULL,PERIOD_M1,0);  // updates only every minute
  if (time == prevtime)
  { return; }
  
  prevtime = time;
  dt = CurTime();
  DrawSessions();

}

//+------------------------------------------------------------------+
//| void DrawSessions()                                              |
//+------------------------------------------------------------------+
void DrawSessions()
{
  for (int i=0; (i<NumberOfDays); i++) 
  {
    if (i==0)
    {
      if ( TimeHour(dt)>TimeHour(StrToTime(AsiaBegin)) )
      {    
        DrawObjects(dt, "AS0", AsiaBegin, AsiaEnd);
        DrawPrices(dt, "AS", AsiaBegin, AsiaEnd); 
      }
      if ( TimeHour(dt)>TimeHour(StrToTime(EurBegin)) )
      {
         DrawObjects(dt, "EU0", EurBegin, EurEnd);
         DrawPrices(dt, "EU", EurBegin, EurEnd);
      }
      if ( TimeHour(dt)>TimeHour(StrToTime(USABegin)) )
      { 
         DrawObjects(dt, "US0", USABegin, USAEnd);
         DrawPrices(dt, "US", USABegin, USAEnd);
      }
    }
    else if (i>0 && !(done) )
    {
      DrawObjects(dt, "AS"+i, AsiaBegin, AsiaEnd); 
      DrawObjects(dt, "EU"+i, EurBegin, EurEnd);
      DrawObjects(dt, "US"+i, USABegin, USAEnd);
    }
    dt=decDateTradeDay(dt);
    while ( (TimeDayOfWeek(dt)==6) || (TimeDayOfWeek(dt)==0) ) dt=decDateTradeDay(dt);
  }
  done = true;
}

//+------------------------------------------------------------------+
//| void DrawObjects()                                               |
//| Inputs:                                                          |
//|   dt - date time of session start                                |
//|   no - string object identifier                                  |
//|   tb - session time begin (hours)                                |
//|   te - session time end (hours)                                  |
//+------------------------------------------------------------------+
void DrawObjects(datetime dt, string no, string tb, string te) 
{
  datetime t1, t2, temp;
  double   p1, p2;
  int      b1, b2;

  t1=StrToTime(TimeToStr(dt, TIME_DATE)+" "+tb);
  t2=StrToTime(TimeToStr(dt, TIME_DATE)+" "+te);
  if (t2<t1) 
  { 
    t2=incDateTradeDay(t2);
    while ( (TimeDayOfWeek(t2)==6) || (TimeDayOfWeek(t2)==0) ) { t2=incDateTradeDay(t2); }
  }
  b1=iBarShift(NULL, 0, t1);
  b2=iBarShift(NULL, 0, t2);
  p1=High[Highest(NULL, 0, MODE_HIGH, b1-b2, b2)];
  p2=Low [Lowest (NULL, 0, MODE_LOW , b1-b2, b2)];
  
// Print("S=", no, " DT=",TimeToStr(dt)," T1=", TimeToStr(t1)," T2=", TimeToStr(t2)," b1=",b1," b2=",b2," p1=",p1," p2=",p2);

  ObjectSet(no, OBJPROP_TIME1 , t1);
  ObjectSet(no, OBJPROP_PRICE1, p1);
  ObjectSet(no, OBJPROP_TIME2 , t2);
  ObjectSet(no, OBJPROP_PRICE2, p2);

}

//+------------------------------------------------------------------+
//| void DrawPrices                                                  |
//| Inputs   :                                                       |
//|   dt - datetime for session begin                                |
//|   no - string object identifier                                  |
//|   tb - session time begin (hours)                                |
//|   te - session time end (hours)                                  |
//+------------------------------------------------------------------+
void DrawPrices(datetime dt, string no, string tb, string te) 
{
  datetime t1, t2;
  double   p1, p2;
  int      b1, b2;

  t1=StrToTime(TimeToStr(dt, TIME_DATE)+" "+tb);
  t2=StrToTime(TimeToStr(dt, TIME_DATE)+" "+te);
  if (t2<t1) 
  { 
    t2=incDateTradeDay(t2);
    while ( (TimeDayOfWeek(t2)==6) || (TimeDayOfWeek(t2)==0) ) { t2=incDateTradeDay(t2); }
  }
  b1=iBarShift(NULL, 0, t1);
  b2=iBarShift(NULL, 0, t2);
  p1=High[Highest(NULL, 0, MODE_HIGH, b1-b2, b2)];
  p2=Low [Lowest (NULL, 0, MODE_LOW , b1-b2, b2)];
  
  if (ObjectFind(no+"up")<0) ObjectCreate(no+"up", OBJ_TEXT, 0, 0,0);
  ObjectSet(no+"up", OBJPROP_TIME1   , t2);
  ObjectSet(no+"up", OBJPROP_PRICE1  , p1+OffSet*Point);
  ObjectSet(no+"up", OBJPROP_COLOR   , clFont);
  ObjectSet(no+"up", OBJPROP_FONTSIZE, SizeFont);
  ObjectSetText(no+"up", DoubleToStr(p1, Digits));

  if (ObjectFind(no+"dn")<0) ObjectCreate(no+"dn", OBJ_TEXT, 0, 0,0);
  ObjectSet(no+"dn", OBJPROP_TIME1   , t2);
  ObjectSet(no+"dn", OBJPROP_PRICE1  , p2);
  ObjectSet(no+"dn", OBJPROP_COLOR   , clFont);
  ObjectSet(no+"dn", OBJPROP_FONTSIZE, SizeFont);
  ObjectSetText(no+"dn", DoubleToStr(p2, Digits));
}

//+------------------------------------------------------------------+
//| decDateTradeDay()                                                |
//| input:                                                           |
//|   dt - date tme of trading session                               |
//+------------------------------------------------------------------+
datetime decDateTradeDay (datetime dt) 
{
  int ty=TimeYear(dt);
  int tm=TimeMonth(dt);
  int td=TimeDay(dt);
  int th=TimeHour(dt);
  int ti=TimeMinute(dt);

  td--;
  if (td==0) 
  {
    tm--;
    if (tm==0) 
    {
      ty--;
      tm=12;
    }
    if (tm==1 || tm==3 || tm==5 || tm==7 || tm==8 || tm==10 || tm==12) td=31;
    if (tm==2) if (MathMod(ty, 4)==0) td=29; else td=28;
    if (tm==4 || tm==6 || tm==9 || tm==11) td=30;
  }
  return(StrToTime(ty+"."+tm+"."+td+" "+th+":"+ti));
}
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| incDateTradeDay()   - increment datetime                         |
//| input:                                                           |
//|   dt - date tme of trading session                               |
//+------------------------------------------------------------------+
datetime incDateTradeDay (datetime dt) 
{
  int ty=TimeYear(dt);
  int tm=TimeMonth(dt);
  int td=TimeDay(dt);
  int th=TimeHour(dt);
  int ti=TimeMinute(dt);

  td++;
  if ( (td==29) && (tm==2) && (MathMod(ty, 4)!=0) ) { td =1; tm++; }
  if ( (td==30) && (tm==2) && (MathMod(ty, 4)==0) ) { td =1; tm++; }
  if ( (td==31) && (tm==4 || tm==6 || tm==9 || tm==11) ) { td=1; tm++; }
  if (  td==32) { td=1; tm++; }  
  if (  tm==13) { ty++; tm=1; }
   
  return(StrToTime(ty+"."+tm+"."+td+" "+th+":"+ti));
}