//+------------------------------------------------------------------+
//|                                             Initial Balances.mq4 |
//|                                                   Author: tgwhbb |
//|                                                                  |
//|                                                                  |
//| Initial Balances is implemented based on the Auction Market Theory |
//| and Market Profile concepts.                                     |
//|                                                                  |
//| History:                                                         |
//|      1.0: 04.07.2011 - initial version.  IB and extensions drawn |
///                        for daily and weekly balances             |
//+------------------------------------------------------------------+
//

#property indicator_chart_window

#define PREFIX "IB-"

//---- input parameters
extern string    LondonStartHour="07:30";
extern string    USStartHour="12:00";
extern string    AsiaStartHour="00:00";
extern bool       ShowDailyIB = true;
extern int       DailyIBDaysBack = 1;
extern int       DaysForAverageIB = 12;
extern int	     Daily_IB_Extensions = 3;
extern bool      Show_Daily_Text = true;
extern bool	     Weekly_Horizontal = true;
extern color     DailyColor=DimGray;
extern color     RectangleColor=DimGray;
extern color     Weekly_DIB_Color = DarkSlateBlue;
extern color     Weekly_IB_Color = FireBrick;

//variables
//int barsToInclude;
double asiaIBsum=0,londonIBsum=0,usIBsum=0;
double asiaIBVsum=0,londonIBVsum=0,usIBVsum=0;
double asiaIBcount=0,londonIBcount=0,usIBcount=0;
double asiaIBVcount=0,londonIBVcount=0,usIBVcount=0;
double asiaIBlast=0,londonIBlast=0,usIBlast=0;
double asiaIBVlast=0,londonIBVlast=0,usIBVlast=0;
double wIB=0;
//int day;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   for(int i=0;i<DailyIBDaysBack;i++) {
     CreateRectangle(i,"IB");
     CreateLine(i,"IBL");
     CreateLine(i,"IBH");
     CreateLine(i,"IBH_x1");
     CreateLine(i,"IBH_x2");
     CreateLine(i,"IBH_x3");
     CreateLine(i,"IBL_x1");
     CreateLine(i,"IBL_x2");
     CreateLine(i,"IBL_x3");
     ObjectCreate(PREFIX+"WIB",OBJ_TREND,0,0,0,0,0);
     ObjectCreate(PREFIX+"WIBH",OBJ_HLINE,0,0,0,0,0);
     ObjectCreate(PREFIX+"WIBL",OBJ_HLINE,0,0,0,0,0);
     ObjectCreate(PREFIX+"WIBH2x",OBJ_TREND,0,0,0,0,0);
     ObjectCreate(PREFIX+"WIBH2xH",OBJ_HLINE,0,0,0,0,0);
     ObjectCreate(PREFIX+"WIBH2xL",OBJ_HLINE,0,0,0,0,0);
     ObjectCreate(PREFIX+"WIBL2x",OBJ_TREND,0,0,0,0,0);
     //ObjectCreate(PREFIX+"WIBL3x",OBJ_TREND,0,0,0,0,0);
     ObjectCreate(PREFIX+"WIBL2xH",OBJ_HLINE,0,0,0,0,0);
     ObjectCreate(PREFIX+"WIBL2xL",OBJ_HLINE,0,0,0,0,0);
   }
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   DeleteObjectsByPrefix(PREFIX);
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int counted_bars=IndicatorCounted();
   int lastbar;
   drawDaily();
   drawWeekly();
   printInfo();

//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------//

// Delete all objects with given prefix
void DeleteObjectsByPrefix(string Prefix) {
   int L = StringLen(Prefix);
   int i = 0; 
   int deleted=0;
   while(i < ObjectsTotal()) {
       string ObjName = ObjectName(i);
       if(StringSubstr(ObjName, 0, L) != Prefix) { 
           i++; 
           continue;
       }
       ObjectDelete(ObjName);
       deleted++;
   }
   Print("deleted objects: "+deleted);
}

void drawDaily() {
   string today = TimeToStr(TimeCurrent(),TIME_DATE);
   datetime asia_open = StrToTime(today+" "+AsiaStartHour);
   datetime london_open = StrToTime(today+" "+LondonStartHour);
   datetime us_open = StrToTime(today+" "+USStartHour);
   int asia_open_shift=0, london_open_shift=0,us_open_shift=0,
   asia_open_shift1=0, london_open_shift1=0,us_open_shift1=0;
   double ibh=0, ibl=0, ibv=0;
   asiaIBsum=0; asiaIBcount=0; asiaIBVsum=0; asiaIBVcount=0;
   londonIBsum=0; londonIBcount=0; londonIBVsum=0; londonIBVcount=0;
   usIBsum=0; usIBcount=0; usIBVsum=0; usIBVcount=0;

   for (int i=0; i<DaysForAverageIB; i++) {
     asia_open_shift = iBarShift(NULL,PERIOD_M30,asia_open);
     asia_open_shift1 = iBarShift(NULL,PERIOD_M30,asia_open+(PERIOD_M30*60));
     london_open_shift = iBarShift(NULL,PERIOD_M30,london_open);
     london_open_shift1 = iBarShift(NULL,PERIOD_M30,london_open+(PERIOD_M30*60));
     us_open_shift = iBarShift(NULL,PERIOD_M30,us_open);
     us_open_shift1 = iBarShift(NULL,PERIOD_M30,us_open+(PERIOD_M30*60));
     
     
     if(asia_open<TimeCurrent()) {
         ibh = MathMax(iHigh(NULL,PERIOD_M30,asia_open_shift), iHigh(NULL,PERIOD_M30,asia_open_shift1));
         ibl = MathMin(iLow(NULL,PERIOD_M30,asia_open_shift), iLow(NULL,PERIOD_M30,asia_open_shift1));
         ibv = iVolume(NULL,PERIOD_M30,asia_open_shift) + iVolume(NULL,PERIOD_M30,asia_open_shift1);
         asiaIBsum += ibh-ibl;  
         asiaIBcount++; 
         asiaIBVsum += ibv;
         asiaIBVcount++;
         if(i==0) {
            asiaIBlast = ibh-ibl;
            asiaIBVlast = ibv;
         }
         drawIBd("Asia",i,asia_open,ibh,ibl);
     }
     if(london_open<TimeCurrent()) {
         ibh = MathMax(iHigh(NULL,PERIOD_M30,london_open_shift), iHigh(NULL,PERIOD_M30,london_open_shift1));
         ibl = MathMin(iLow(NULL,PERIOD_M30,london_open_shift), iLow(NULL,PERIOD_M30,london_open_shift1));
         ibv = iVolume(NULL,PERIOD_M30,london_open_shift)+iVolume(NULL,PERIOD_M30,london_open_shift1);
         londonIBsum += ibh-ibl;  
         londonIBcount++; 
         londonIBVsum += ibv;
         londonIBVcount++;
         if(i==0) {
            londonIBlast = ibh-ibl;
            londonIBVlast = ibv;
         }
         drawIBd("London",i,london_open,ibh,ibl);
     }
     if(us_open<TimeCurrent()) {
         ibh = MathMax(iHigh(NULL,PERIOD_M30,us_open_shift), iHigh(NULL,PERIOD_M30,us_open_shift1));
         ibl = MathMin(iLow(NULL,PERIOD_M30,us_open_shift), iLow(NULL,PERIOD_M30,us_open_shift1));
         ibv = iVolume(NULL,PERIOD_M30,us_open_shift) + iVolume(NULL,PERIOD_M30,us_open_shift1);
         usIBsum += ibh-ibl;  
         usIBcount++; 
         usIBVsum += ibv;
         usIBVcount++;
         if(i==0) {
            usIBlast = ibh-ibl;
            usIBVlast = ibv;
         }
         drawIBd("US",i,us_open,ibh,ibl);
     }
                              
     asia_open -= 86400;
     london_open -= 86400;
     us_open -= 86400;
     
     if(TimeDayOfWeek(asia_open)>=5) i--; //skip saturday & sunday
   }
   
}

void drawWeekly(){
   int now = DayOfWeek();
   int startDay = 0;
   int daysTocheck = 3;
   if (now > 2) {
      daysTocheck = 3; 
      startDay = now - 2;
   } else { //if(now == 2){
      startDay = 0;
      daysTocheck = now+1;
   } 
   double wIBH = iHigh(NULL,PERIOD_D1,iHighest(NULL,PERIOD_D1,MODE_HIGH,daysTocheck,startDay));
   double wIBL = iLow(NULL,PERIOD_D1,iLowest(NULL,PERIOD_D1,MODE_LOW,daysTocheck,startDay));
   wIB = wIBH - wIBL;
   int firstBar = WindowFirstVisibleBar();
   datetime first = Time[firstBar] + (Period()*60);
   VerticalLine("WIB",first,wIBH,wIBL,Weekly_IB_Color);
   VerticalLine("WIBH2x",first,wIBH+wIB,wIBH,Weekly_DIB_Color);
   VerticalLine("WIBL2x",first,wIBL-wIB,wIBL,Weekly_DIB_Color);
}

int drawIBd(string session, int i, datetime dt, double ibh, double ibl) {
   if(!ShowDailyIB) return(-1);
   double ib = ibh - ibl;
   string name = PREFIX+session+i+"_";
   //IB rectangle
   SetRectangle(name+"IB",dt,ibl,ibh,RectangleColor); 
   ObjectSetter(name+"IBL","IBL: "+DoubleToStr(ibl,Digits),dt,ibl);
   ObjectSetter(name+"IBH","IBH: "+DoubleToStr(ibh,Digits),dt,ibh);
   for(int j=1; j<= Daily_IB_Extensions; j++) {
      ObjectSetter(name+"IBL_x"+j,j+"x: "+DoubleToStr(ibl-(ib*j),Digits),dt,ibl-(ib*j));
      ObjectSetter(name+"IBH_x"+j,j+"x: "+DoubleToStr(ibh+(ib*j),Digits),dt,ibh+(ib*j));
   }
}



void VerticalLine(string name, datetime dt, double price1, double price2, color col) {
   ObjectSet(PREFIX+name,OBJPROP_RAY,false);
   ObjectSet(PREFIX+name,OBJPROP_WIDTH,5);
   ObjectSet(PREFIX+name,OBJPROP_BACK,true);
   ObjectSet(PREFIX+name,OBJPROP_COLOR,col);
   ObjectSet(PREFIX+name,OBJPROP_TIME1,dt);
   ObjectSet(PREFIX+name,OBJPROP_TIME2,dt);
   ObjectSet(PREFIX+name,OBJPROP_PRICE1,price1);
   ObjectSet(PREFIX+name,OBJPROP_PRICE2,price2);
   //
   //datetime lastTime = TimeCurrent() + 5*Period()*60;
   if(Weekly_Horizontal) {
      if(StringLen(name)==3) {
         ObjectSet(PREFIX+name+"H",OBJPROP_PRICE1,price1);
         ObjectSet(PREFIX+name+"H",OBJPROP_COLOR,col);
         ObjectSet(PREFIX+name+"H",OBJPROP_STYLE,STYLE_DOT);
         ObjectSet(PREFIX+name+"L",OBJPROP_PRICE1,price2);
         ObjectSet(PREFIX+name+"L",OBJPROP_COLOR,col);
         ObjectSet(PREFIX+name+"L",OBJPROP_STYLE,STYLE_DOT);
      } else {
         ObjectSet(PREFIX+name+"H",OBJPROP_PRICE1,price1);
         ObjectSet(PREFIX+name+"H",OBJPROP_COLOR,col);
         ObjectSet(PREFIX+name+"H",OBJPROP_STYLE,STYLE_DOT);
      }
   }
}

void ObjectSetter(string name, string label, datetime dt, double price) {
   double length = 10 * Period() * 60;
   //if (StringFind(name,"Asia") != -1) length = 7*3600;
   //else if (StringFind(name,"London") != -1) length = 5*3600;
   //else if (StringFind(name,"US") != -1) length = 9*3600;
   //if (length < 0) length *= -1;
   ObjectSet(name,OBJPROP_TIME1,dt);
   ObjectSet(name,OBJPROP_TIME2,dt+length);
   ObjectSet(name,OBJPROP_PRICE1,price);
   ObjectSet(name,OBJPROP_PRICE2,price);
   ObjectSet(name,OBJPROP_RAY,false);
   ObjectSet(name,OBJPROP_COLOR,DailyColor);
   ObjectSet(name,OBJPROP_BACK,true);
   ObjectSet(name,OBJPROP_STYLE,STYLE_SOLID);
   if(Show_Daily_Text) {
      ObjectSetText(name+"_text",label,8,"Arial",DailyColor);
      ObjectSet(name+"_text",OBJPROP_TIME1,dt+3600);
      ObjectSet(name+"_text",OBJPROP_PRICE1,price);
      ObjectSet(name+"_text",OBJPROP_BACK,true);
   }
}

void SetRectangle(string name, datetime dt, double low, double high, color col) {
   //string name = PREFIX+session+i+"_"+ib;
   ObjectSet(name,OBJPROP_TIME1,dt);
   ObjectSet(name,OBJPROP_TIME2,dt+3300);
   ObjectSet(name,OBJPROP_PRICE1,high);
   ObjectSet(name,OBJPROP_PRICE2,low);
   ObjectSet(name,OBJPROP_COLOR,col);
   ObjectSet(name,OBJPROP_BACK,true);
}

void CreateLine(int i, string ib) {
     ObjectCreate(PREFIX+"Asia"+i+"_"+ib,OBJ_TREND,0,0,0,0,0);
     ObjectCreate(PREFIX+"London"+i+"_"+ib,OBJ_TREND,0,0,0,0,0);
     ObjectCreate(PREFIX+"US"+i+"_"+ib,OBJ_TREND,0,0,0,0,0);
     ObjectCreate(PREFIX+"Asia"+i+"_"+ib+"_text",OBJ_TEXT,0,0,0);
     ObjectCreate(PREFIX+"London"+i+"_"+ib+"_text",OBJ_TEXT,0,0,0);
     ObjectCreate(PREFIX+"US"+i+"_"+ib+"_text",OBJ_TEXT,0,0,0);
}

void CreateRectangle(int i, string ib) {
   ObjectCreate(PREFIX+"Asia"+i+"_"+ib,OBJ_RECTANGLE,0,0,0,0,0);
   ObjectCreate(PREFIX+"London"+i+"_"+ib,OBJ_RECTANGLE,0,0,0,0,0);
   ObjectCreate(PREFIX+"US"+i+"_"+ib,OBJ_RECTANGLE,0,0,0,0,0);
}

void printInfo() {
   int y = 10;
   //double asiaDiff = ((asiaIBlast/(asiaIBsum/asiaIBcount))-1)*100;
   y=createTextObject("IBtitle","","Initial Balances      ",y);
   y=createTextObject("desc","","Last      Avg     %diff",y);
   y=createTextObject("asia","","Asia: " +DoubleToStr(asiaIBlast/Point/10,1)+"    "+
                        DoubleToStr(asiaIBsum/asiaIBcount/Point/10,1)+"    "+
                        DoubleToStr(((asiaIBlast/(asiaIBsum/asiaIBcount))-1)*100,1),y);
   y=createTextObject("asiaV","","Vol: " +DoubleToStr(asiaIBVlast,0)+"    "+
                        DoubleToStr(asiaIBVsum/asiaIBVcount,0)+"    "+
                        DoubleToStr(((asiaIBVlast/(asiaIBVsum/asiaIBVcount))-1)*100,1),y);
   y=createTextObject("london","","London: " +DoubleToStr(londonIBlast/Point/10,1)+"    "+
                        DoubleToStr(londonIBsum/londonIBcount/Point/10,1)+"    "+
                        DoubleToStr(((londonIBlast/(londonIBsum/londonIBcount))-1)*100,1),y);
   y=createTextObject("londonV","","Vol: " +DoubleToStr(londonIBVlast,0)+"    "+
                        DoubleToStr(londonIBVsum/londonIBVcount,0)+"    "+
                        DoubleToStr(((londonIBVlast/(londonIBVsum/londonIBVcount))-1)*100,1),y);
   y=createTextObject("us","","US: " +DoubleToStr(usIBlast/Point/10,1)+"    "+
                        DoubleToStr(usIBsum/usIBcount/Point/10,1)+"    "+
                        DoubleToStr(((usIBlast/(usIBsum/usIBcount))-1)*100,1),y);
   y=createTextObject("usV","","Vol: " +DoubleToStr(usIBVlast,0)+"    "+
                        DoubleToStr(usIBVsum/usIBVcount,0)+"    "+
                        DoubleToStr(((usIBVlast/(usIBVsum/usIBVcount))-1)*100,1),y);
   //y=createTextObject("wIBTitle","","Weekly Initial Balances",y+5);
   
   y=createTextObject("wIB","","Week: "+DoubleToStr(wIB/Point/10,1),y+5);
                       
}

int createTextObject(string label, string name, string value,int y,color col=NULL) {
   if(col == NULL) col = DailyColor;
   ObjectCreate(label, OBJ_LABEL, 0, 0, 0);
   ObjectSetText(label,name, 9, "Arial", col);
   ObjectSet(label, OBJPROP_CORNER, 1);
   ObjectSet(label, OBJPROP_XDISTANCE, 60);
   ObjectSet(label, OBJPROP_YDISTANCE, y); 
   
   ObjectCreate(label+"_1", OBJ_LABEL, 0, 0, 0);
   ObjectSetText(label+"_1",value, 9, "Arial", col);
   ObjectSet(label+"_1", OBJPROP_CORNER, 1);
   ObjectSet(label+"_1", OBJPROP_XDISTANCE, 10);
   ObjectSet(label+"_1", OBJPROP_YDISTANCE, y);  
   return(y+11);
}



