/*-------------------------------------------------------------------
   Name: Xi Dashboard.mq4
   Copyright ©2010, Xaphod, http://forexwhiz.appspot.com
   
   Description: Xi Dashboard provides the following info on the chart
        Market Info: 
             Symbol, Bid, Ask and Spread.
        Fractal & Pip info with Up/Down color coding:
             PTFH - Pips to fractal high
	           PTFL - Pips to fractal low
	           PLFS - Pips of Last Fractal Swing.
	           PTO  - Pips to open	   
	           PTMA - Pips to MA
	      Moving Average:
	           Standard MA for use with PTMA function above
	      Last H1/H4 high and low with Up/Down color coding	           
	           S/R lines on chart 
	      Daily Range:
	           TDR - Todays Range
	           YDR - Yesterdays Range
	           5ADR - 5 day ADR. Average Range of the last 5 days
	           20ADR - 20 day ADR. Average Range of the last 20 days	           
	         
   Change log: 2010-03-28. v0.80 Release      
-----------------------------------------------------------------*/
// Indicator properties
#property copyright "Copyright © 2010, Xaphod"
#property link      "http://forexwhiz.appspot.com"
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_color1 Salmon
#property indicator_width1 2
#property indicator_color2 Salmon
#property indicator_width2 2
#property indicator_color3 White
#property indicator_width3 2
#property indicator_color4 White
#property indicator_width4 2
#property indicator_color5 Yellow

// Input parameters
extern string   ShowH1HLLinesInfo="<< Show 1H High/Low Lines on Chart >>";
extern bool     ShowH1HLLines=true;
extern string   ShowH1HLDataInfo="<< Show 1H High/Low Data on Dashboard >>";
extern bool     ShowH1HLData=true;
extern string   ShowH4HLLinesInfo="<< Show 4H High/Low Lines on Chart >>";
extern bool     ShowH4HLLines=true;
extern string   ShowH4HLDataInfo="<< Show 4H High/Low Data on Dashboard  >>";
extern bool     ShowH4HLData=true;
extern string   ShowPipsDataInfo="<< Show Pip Range Data on Dashboard >>";
extern bool     ShowPipsData=true;
extern string   TextColorInfo="<< Main Data Text Colors >>";
extern color    UpTextColor=Green;
extern color    DnTextColor=Blue;
extern string   BlankLine1="###############################";
extern string   ShowAdrDataInfo="<< Show ADR Data on Dashboard >>";
extern bool     ShowAdrData=true;
extern string   AdrTextColorInfo="<< Adr Text Color >>";
extern color    AdrTextColor=LightBlue;
extern string   BlankLine2="###############################";
extern string   MAPeriodInfo="<< MA Period. Deactivate: MA=0 >>";
extern int      MAPeriod=20;
extern string   MAShiftInfo="<< MA Shift. 0 =  >>";
extern int      MAShift=0;
extern string   MAModeInfo="<< SMA=0, EMA=1, SMMA=2, LWMA=3 >>";
extern int      MAMode=0;
extern string   MAPriceInfo0="<< CLOSE=0, OPEN=1, HIGH=2, LOW=3 >>";
extern string   MAPriceInfo1="<< MEDIAN=4, TYPICAL=5, WEIGHTED=6 >>";
extern int      MAPrice=0;
extern string   MAPTMAModeInfo="<< PTMA Mode. 0=Always 1=Within Last Fractal Swing >>";
extern int      MAPTMAMode=0;
extern string   BlankLine3="###############################";
extern string   ShowMarketDataInfo="<< Show Market Info in Dashboard >>";
extern bool     ShowMarketData=true;
extern string   MarketTextColorInfo="<< Market Info Text Colors >>";
extern color    SymbolTextColor=Gold;
extern color    BidTextColor=Lime;
extern color    AskTextColor=Maroon;
extern color    SpreadTextColor=Aqua;
extern string   ShowAskInfo="<< Show Ask Data in Dashboard >>";
extern bool     ShowAsk=true;
extern string   ShowSpreadInfo="<< Show Spread Data in Dashboard >>";
extern bool     ShowSpread=true;
extern string   BlankLine4="###############################";
extern string   DisplayCornerInfo="<<Top Left=0, Top Right=1,Bottom left=2, Bottom Right=3>>";
extern int      DisplayCorner=1;

// Indicator buffers
double dExtMapBuffer1[];
double dExtMapBuffer2[];
double dExtMapBuffer3[];
double dExtMapBuffer4[];
double dExtMapBuffer5[];

// Constants
string sObjId = "XiDashboard_";
int iTextXPos = 10;
int iTextYInt = 13;
int iTextCorner = 1;
int iTextYPos = 1;

//---- Indicator name & version
string sIndicatorName;
string sVersion = "v0.80";


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
  // Indicator Settings
  SetIndexStyle(0,DRAW_LINE);
  SetIndexBuffer(0,dExtMapBuffer1);
  SetIndexDrawBegin(0, 60/Period());   
  SetIndexLabel(0,"H1 Last High");
  SetIndexStyle(1,DRAW_LINE);
  SetIndexBuffer(1,dExtMapBuffer2);
  SetIndexDrawBegin(1, 60/Period());
  SetIndexLabel(1,"H1 Last Low");
  SetIndexStyle(2,DRAW_LINE);
  SetIndexBuffer(2,dExtMapBuffer3);
  SetIndexDrawBegin(2, 240/Period()); 
  SetIndexLabel(2,"H4 Last High");  
  SetIndexStyle(3,DRAW_LINE);
  SetIndexBuffer(3,dExtMapBuffer4);
  SetIndexDrawBegin(3, 240/Period());   
  SetIndexLabel(3,"H4 Last Low");
  SetIndexStyle(4,DRAW_LINE);
  SetIndexBuffer(4,dExtMapBuffer5);  
  SetIndexLabel(4,"MA"+MAPeriod);
  
  // Set indicator name  
  sIndicatorName = "[Xi Dashboard " + sVersion + "]";
  IndicatorShortName(sIndicatorName);
  
  // Set Constant variables
  iTextCorner = DisplayCorner;
  
  // Exit
  return(0);
  }
  
  
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit() {
  int i;
  
  // Clear text objects
  for( i=ObjectsTotal()-1; i>-1; i--)
   if (StringFind(ObjectName(i),sObjId)>=0)  ObjectDelete(ObjectName(i));
   
  // Exit
  return(0);
  }


//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()  {
  int iNewBars;
  int iCountedBars;   
  
  // Get unprocessed bars
  iCountedBars=IndicatorCounted();
  if(iCountedBars < 0) return (-1); 
  if(iCountedBars>0) iCountedBars--;
  iNewBars=Bars-iCountedBars;
  
  // Display MA
  if (MAPeriod>0)
    for(int i=iNewBars-2; i>=0; i--) 
      dExtMapBuffer5[i]=iMA(NULL,0,MAPeriod,MAShift,MAMode,MAPrice,i);
  
  // Display/Update Dashboard
  iTextYPos = 1;  
  if (ShowMarketData==true) DisplayMarketInfo(); 
  iTextYPos++;  
  if (ShowPipsData==true) FractalPipData();
  iTextYPos++;
  if (ShowH1HLData==true) SetH1LastHigh();
  if (ShowH4HLData==true) SetH4LastHigh();
  iTextYPos++;  
  if (ShowAdrData==true) DailyRange();

  // exit
  return(0);
}
//+------------------------------------------------------------------+


//-----------------------------------------------------------------------------
// function: SetH1LastHigh()
// Description: Calc and display H1 High and Low 
//-----------------------------------------------------------------------------
void SetH1LastHigh() {
  double dHigh;
  double dLow;
  int iNrOfBars;
  int iPeriod;
  int iShift=-1;
  int i;
  color cTextColor;
  
  // Get and display 14 high & low and draw SR lines
  iPeriod=GetPeriod(Period());  
  if (iPeriod<60) {  
    // Get index of the end of the last 1H bar
    for (iShift=0; iShift<Bars; iShift++) 
      if (TimeMinute(Time[iShift])== 0) 
        break;
    iShift++;    
    
    // Get nr of bars for the 1H period. There can be bars missing!
    for (i=iShift; i<Bars; i++) 
      if (TimeMinute(Time[i])== 0) 
        break;
    iNrOfBars=i-iShift+1;   
    
    // Find the highest and lowest data for specified nr of bars
    dHigh=High[iHighest(NULL,0,MODE_HIGH,iNrOfBars,iShift)];
    dLow=Low[iLowest(NULL,0,MODE_LOW,iNrOfBars,iShift)];
  
    // Display on dashboard    
    if (Bid<((dHigh-dLow)/2)+dLow) cTextColor=DnTextColor; else cTextColor=UpTextColor ;
    WriteText("LH(H1) " + DoubleToStr(dHigh, Digits), sObjId+"LH-H1", iTextCorner, iTextXPos, iTextYInt*iTextYPos,cTextColor);
    iTextYPos++;
    WriteText("LL(H1) " + DoubleToStr(dLow, Digits), sObjId+"LL-H1", iTextCorner, iTextXPos, iTextYInt*iTextYPos,cTextColor);
    iTextYPos++;
        
    // Draw H/L line
    if (ShowH1HLLines==True)  {
      for(i=iShift; i<iNrOfBars+iShift; i++) {    
        dExtMapBuffer1[i]=dHigh;
        dExtMapBuffer2[i]=dLow;    
      } // end if
      // Clear old lines
      for(; i<iNrOfBars+iShift+(60/iPeriod)+2; i++) {    
        dExtMapBuffer1[i]=EMPTY_VALUE;
        dExtMapBuffer2[i]=EMPTY_VALUE;    
      } // endfor
    } // endfor    
  } // endif
  
}  // end funcion()


//-----------------------------------------------------------------------------
// function: SetH4LastHigh()
// Description: Calc and display H4 High and Low 
//-----------------------------------------------------------------------------
void SetH4LastHigh() {
  double dHigh;
  double dLow;
  int iNrOfBars;
  int iPeriod;
  int iShift;
  int i;
  color cTextColor;
  
  // Get and display H4 high & low and draw SR lines
  iPeriod=GetPeriod(Period());  
  if (iPeriod<240) {
  
    // Get index of the end of the last 4H bar
    for (iShift=0; iShift<Bars; iShift++)
      if (TimeMinute(Time[iShift])== 0 && MathRound(MathMod(TimeHour(Time[iShift]),4))==0) 
        break;
    iShift++;
    
    // Get nr of bars for the 4H period. There can be bars missing!
    for (i=iShift; i<Bars; i++) 
      if (TimeMinute(Time[i])== 0 && MathRound(MathMod(TimeHour(Time[i]),4))==0) 
        break;
    iNrOfBars=i-iShift+1;
   
    // Calc Hih and low for specified nr of bars
    dHigh=High[iHighest(NULL,0,MODE_HIGH,iNrOfBars,iShift)];
    dLow=Low[iLowest(NULL,0,MODE_LOW,iNrOfBars,iShift)];  
    
    // Display on dashboard
    if (Bid<((dHigh-dLow)/2)+dLow) cTextColor=DnTextColor; else cTextColor=UpTextColor ;
    WriteText("LH(H4) " + DoubleToStr(dHigh, Digits), sObjId+"LH-H4", iTextCorner, iTextXPos, iTextYInt*iTextYPos,cTextColor);
    iTextYPos++;   
    WriteText("LL(H4) " + DoubleToStr(dLow, Digits), sObjId+"LL-H4", iTextCorner, iTextXPos, iTextYInt*iTextYPos,cTextColor);    
    iTextYPos++;
    
    // Draw H/L line
    if (ShowH4HLLines==True)  {
      for(i=iShift; i<iNrOfBars+iShift; i++) {    
        dExtMapBuffer3[i]=dHigh;
        dExtMapBuffer4[i]=dLow;   
      } // endfor
      // Clear old lines
      for(; i<iNrOfBars+iShift+(240/iPeriod)+2; i++) {    
        dExtMapBuffer1[i]=EMPTY_VALUE;
        dExtMapBuffer2[i]=EMPTY_VALUE; 
      } // endfor
    } // endif
    
  } // endif
} //end funcion()


//-----------------------------------------------------------------------------
// function: FractalPipData()
// Description: Calc and display:
//        PLFS - Pips of Last Fractal Swing, 
//        PTFH - Pips To Fractal High, 
//        PTFL - Pips To Fractal Low 
//        PTO - Pips to open
//        PTMA - Pips to MA
//-----------------------------------------------------------------------------
void FractalPipData() {
  double dFractalHigh;
  int iFractalHigh;
  double dPTFH;
  double dFractalLow;
  int iFractalLow;
  double dPTFL;
  double dFractalSwing;
  double dPTO;
  double dPTMA;
  int i;
  color cTextColor;
  
  // Calc Fractals - PLFS - Pips of Last Fractal Swing, PTFH - Pips To Fractal High, PTFL - Pips To Fractal Low 
  iFractalHigh=GetLastFractalIndex( 0, MODE_UPPER);
  iFractalLow=GetLastFractalIndex( 0, MODE_LOWER);    
  if (iFractalHigh>=0) 
    dPTFH=PriceToPips( Bid - High[iFractalHigh]);
  if (iFractalLow>=0) 
    dPTFL=PriceToPips( Bid - Low[iFractalLow]);
  dFractalSwing=PriceToPips(High[iFractalHigh]-Low[iFractalLow]); 
  
  // Display Fractal data
  if (dPTFH<=0) cTextColor=DnTextColor; else cTextColor=UpTextColor ;
  WriteText("PTFH " + DoubleToStr(MathAbs(dPTFH), PipPrecision()), sObjId+"PTFH", iTextCorner, iTextXPos, iTextYInt*iTextYPos,cTextColor);
  iTextYPos++;
  if (dPTFL<=0) cTextColor=DnTextColor; else cTextColor=UpTextColor ;
  WriteText("PTFL " + DoubleToStr(MathAbs(dPTFL), PipPrecision()), sObjId+"PTFL", iTextCorner, iTextXPos, iTextYInt*iTextYPos,cTextColor);
  iTextYPos++;
  
  if (iFractalHigh>iFractalLow) cTextColor=DnTextColor; else cTextColor=UpTextColor ;
  WriteText("PLFS " + DoubleToStr(dFractalSwing, PipPrecision()), sObjId+"PLFS", iTextCorner, iTextXPos, iTextYInt*iTextYPos,UpTextColor);
  iTextYPos++;

  // Calc PTO - Pips to open
  dPTO=PriceToPips( Bid-iOpen(NULL,PERIOD_D1,0));
  if (dPTO<=0) cTextColor=DnTextColor; else cTextColor=UpTextColor ;
  WriteText(" PTO " + DoubleToStr( MathAbs(dPTO) ,PipPrecision()),sObjId+"PTO", iTextCorner, iTextXPos, iTextYInt*iTextYPos,cTextColor);
  iTextYPos++;
  
  // Calc PTMA - Pips to MA
  if (MAPeriod>0) {
    double dCurMA=iMA(NULL,0,MAPeriod,MAShift,MAMode,MAPrice,0);     

    if (MAPTMAMode==0 || (dCurMA>dFractalLow && dCurMA<dFractalHigh)) {    
      dPTMA=PriceToPips(Bid-dCurMA);
      if (dPTO<=0) cTextColor=DnTextColor; else cTextColor=UpTextColor ;
      WriteText("PTMA " + DoubleToStr(MathAbs(dPTMA) , PipPrecision()), sObjId+"PTMA", iTextCorner, iTextXPos, iTextYInt*iTextYPos,cTextColor);
      iTextYPos++;
    }
  }
} // end funcion()


//-----------------------------------------------------------------------------
// function: GetLastFractalIndex()
// Description: Get the index of the latest High or Low Fractal
//-----------------------------------------------------------------------------
int GetLastFractalIndex(int iTimeFrame, int iMode) {
  
  for (int i=0; i<Bars; i++) 
    if (iFractals(NULL, iTimeFrame, iMode, i)!=NULL) return(i); 

  return(-1);
}  // end funcion()


//-----------------------------------------------------------------------------
// function: DailyRange()
// Description: Calc and display the daily range
//-----------------------------------------------------------------------------
void DailyRange() {
  double dTDR;
  double dYDR;
  double d5DR;
  double d20DR;
  
  // Calc the ADR
  dTDR=PriceToPips(iHigh(NULL,PERIOD_D1,0)-iLow(NULL,PERIOD_D1,0));
  dYDR=PriceToPips(iHigh(NULL,PERIOD_D1,1)-iLow(NULL,PERIOD_D1,1));
  d5DR=PriceToPips(CalcDailyRange(5));
  d20DR=PriceToPips(CalcDailyRange(20));
  
  // Display ADR on dashboard
  WriteText("  TDR " + DoubleToStr(dTDR, PipPrecision()), sObjId+"TDR", iTextCorner, iTextXPos, iTextYInt* iTextYPos, AdrTextColor);
  iTextYPos++;
  WriteText("  YDR " + DoubleToStr(dYDR, PipPrecision()), sObjId+"YDR", iTextCorner, iTextXPos, iTextYInt*iTextYPos, AdrTextColor);
  iTextYPos++;
  WriteText(" 5ADR " + DoubleToStr(d5DR, PipPrecision()), sObjId+"5ADR", iTextCorner, iTextXPos, iTextYInt*iTextYPos, AdrTextColor);
  iTextYPos++;
  WriteText("20ADR " + DoubleToStr(d20DR, PipPrecision()), sObjId+"20ADR", iTextCorner, iTextXPos, iTextYInt*iTextYPos, AdrTextColor);
  iTextYPos++;
}  // end funcion()


//-----------------------------------------------------------------------------
// function: CalcDailyRange()
// Description: Calc the average daily range over a number of days
//-----------------------------------------------------------------------------
double CalcDailyRange(int iNrOfDays) {
  double dADR=0;
  int i;
 
  for (i=1; i<=iNrOfDays; i++)
    dADR=dADR+ iHigh(NULL,PERIOD_D1,i)-iLow(NULL,PERIOD_D1,i);
 
  return (dADR/iNrOfDays);  
} //end funcion()


//-----------------------------------------------------------------------------
// function: DisplayMarketInfo()
// Description: Calc the average daily range over a number of days
//-----------------------------------------------------------------------------
void DisplayMarketInfo() {
  int iX,iY;
  
  // Instrument  
  if (DisplayCorner==1 || DisplayCorner==3) iX=90; else iX=10;  // Set display positions depending the corner
  if (DisplayCorner==2 || DisplayCorner==3) iY=iTextYInt*iTextYPos+14; else iY=iTextYInt*iTextYPos-3;
  WriteText(GetShortSymbol(Symbol()), sObjId+"Symbol", iTextCorner, iX, iY,SymbolTextColor,24);
  //iTextYPos++;
  
  // Price
  if (DisplayCorner==0 || DisplayCorner==2) iX=50; else iX=10; // Set display positions depending the corner
  WriteText(DoubleToStr( Bid, Digits), sObjId+"Bid", iTextCorner, iX, iTextYInt*iTextYPos,BidTextColor, 14);
  iTextYPos++;  
  
  if (ShowAsk==True) {
    if (DisplayCorner==0 || DisplayCorner==2) iX=50; else iX=33; // Set display positions depending the corner
    WriteText( DoubleToStr(Ask, Digits), sObjId+"Ask", iTextCorner, iX, iTextYInt*iTextYPos,AskTextColor,9);
    iTextYPos++;
  }
  
  if (ShowSpread==True) {
    if (ShowAsk==False) 
      if (DisplayCorner==0 || DisplayCorner==2) iX=50; else iX=35;
    else
      iX=iTextXPos;
    WriteText("SP "+ DoubleToStr( PriceToPips(Ask-Bid) , PipPrecision()), sObjId+"Spread", iTextCorner, iX, iTextYInt*iTextYPos,SpreadTextColor,9);      
  iTextYPos++;
  }
}  // end funcion()


//-----------------------------------------------------------------------------
// function: WriteText()
// Description: Write text strings to window
//-----------------------------------------------------------------------------
void WriteText(string sText, string sTextId, int iCorner, int iXPos, int iYPos, color cTxtColor=LightBlue, int iTxtSize=9) {
  int i;      

  // Delete text object if it already exists      
  for( i=ObjectsTotal()-1; i>-1; i--)
    if (StringFind(ObjectName(i),sTextId)>=0)  ObjectDelete(sTextId);
      //ObjectDelete(sTextId);
  
  if (iCorner==2 || iCorner==3) iYPos=250-iYPos;    
  // Print Text
  ObjectCreate(sTextId, OBJ_LABEL, 0, 0, 0, 0, 0);
  ObjectSet(sTextId, OBJPROP_CORNER, iCorner);
  ObjectSet(sTextId, OBJPROP_WIDTH, 3);
  ObjectSet(sTextId, OBJPROP_XDISTANCE, iXPos);
  ObjectSet(sTextId, OBJPROP_YDISTANCE, iYPos);
  ObjectSetText(sTextId, sText, iTxtSize, "Courier New", cTxtColor);
}  // end funcion()


//-----------------------------------------------------------------------------
// function: GetPeriod()
// Description: Get the current period. Translate vHandsTrade simulator periods
//              to standard  periods.
//-----------------------------------------------------------------------------
int GetPeriod(int iCurPeriod)  {
  int iResult;
  
  if (iCurPeriod==0) iCurPeriod=Period();
  
  switch (iCurPeriod) {
    case 2: iResult=1; break;   
    case 6: iResult=5; break;   
    case 16: iResult=15; break;
    case 31: iResult=30; break;
    case 61: iResult=60; break;
    case 241: iResult=240; break;
    case 1441: iResult=1440; break;
    case 10081: iResult=10080; break;
    case 43201: iResult=43200; break;
    default: iResult=iCurPeriod; 
  }
  
  // exit
  return(iResult);
} // end funcion()


//-----------------------------------------------------------------------------
// function: PriceToPips()
// Description: Convert a proce difference to pips.
//-----------------------------------------------------------------------------
double PriceToPips(double dPrice) {
  
  if (Digits==3 || Digits==5) 
    return(dPrice/0.0001); 
  else if (Digits==2 || Digits==4) 
    return(dPrice/0.0001); 
  else
    return(dPrice);            
} // end funcion()


//-----------------------------------------------------------------------------
// function: PipPrecision()
// Description: Convert a price difference to pips.
//-----------------------------------------------------------------------------
double PipPrecision() {

 if (Digits==3 || Digits==5) 
    return(1); 
  else if (Digits==2 || Digits==4) 
    return(0); 
  else
    return(0);            
} // end funcion()
  

//-----------------------------------------------------------------------------
// function: GetShortSymbol()
// Description: Shorten a symbol name. Tex. EURUSD = EU, GBPUSD = GU
//-----------------------------------------------------------------------------
string GetShortSymbol(string sSymbol) {
  string sResult="";
  
  if (StringLen(sSymbol)>5)
    sResult=StringSubstr( sSymbol, 0, 1)+ StringSubstr( sSymbol, 3, 1);
  else
    sResult="sSymbol";
 
  return(sResult);
} // end funcion()


