//+------------------------------------------------------------------+
//|   BlueAce_RangeInd by Ian Foster                                 |
//|   (part of BlueAce Pivots set&forget system)                     |
//|           based on Auslanco                  Pivot Points v8.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Jason Normandin"
#property link      ""

#property indicator_chart_window
#property indicator_buffers 7
//--------------------------------------
#property indicator_color1 MediumVioletRed
#property indicator_color2 MediumVioletRed
#property indicator_color3 Blue
#property indicator_color4 Teal
#property indicator_color5 Teal
#property indicator_color6 Red
#property indicator_color7 Orange
#property indicator_width1 1
#property indicator_width2 1
#property indicator_width3 1
#property indicator_width4 1
#property indicator_width5 1
#property indicator_width6 1
#property indicator_width7 1

#define	SECONDS_IN_MINUTE	60
#define	SECONDS_IN_HOUR	3600
#define	SECONDS_IN_DAY		86400


#define	PIVOT_R2			1
#define	PIVOT_R1			2
#define	PIVOT_PP			3
#define	PIVOT_S1			4
#define	PIVOT_S2			5
#define	PIVOT_SSL		6
#define	PIVOT_BSL		7
#define  PRICE_RANGE    8  // I'm using the pivots array to return the previous Day's range(DaystartHour to DayStartHour)


//extern int	DayStartHour	= 21; // = 17:00 EST (Daylight saving Time) since IBFX is GMT +0
//extern int	DayStartHour	= 0 ; // = 17:00 EST (Daylight saving Time) since FXPRO is GMT +3
// cORRECT START TIME FOR BlueAce PIVOT SYSTEM IS 00:00 EST = 04:00 GMT in Summer, 05:00 GMT in Winter
extern int	DayStartHour	= 7 ; // = 00:00 EST (Daylight saving Time) since FXPRO is GMT +3


// buffers
// double dR3Buffer[];
double dR2Buffer[];
double dR1Buffer[];
double dPPBuffer[];
double dS1Buffer[];
double dS2Buffer[];
// double dS3Buffer[];
double sslBuffer[];
double bslBuffer[];


int init() {

	SetIndexBuffer(0,dR2Buffer);
 	SetIndexBuffer(1,dR1Buffer);
 	SetIndexBuffer(2,dPPBuffer);
 	SetIndexBuffer(3,dS1Buffer);
 	SetIndexBuffer(4,dS2Buffer);
 	SetIndexBuffer(5,sslBuffer);
 	SetIndexBuffer(6,bslBuffer);

	
	IndicatorShortName("BlueAce PivotSysLines");

			SetIndexLabel(0,"Daily Pivot R2");
 			SetIndexLabel(1,"Daily Pivot R1");
 			SetIndexLabel(2,"Daily Pivot Point");
 			SetIndexLabel(3,"Daily Pivot S1");
 			SetIndexLabel(4,"Daily Pivot S2");
			SetIndexLabel(5,"Sell StopLoss");
			SetIndexLabel(6,"Buy StopLoss");
		
} // End init


int start() {
	
	double dPrices[4];  
	double dPivots[9];  // seems to need to be 1 more than I would expect!
	
	// Don't show lines on inappropriate timeframes
		if (Period() > PERIOD_D1) return(0);
	
		// Determine how far back to iterate
	int	iBarsToCalc = Bars - IndicatorCounted();
	if (iBarsToCalc < Bars) iBarsToCalc++;
		
	// Iterate over bars and perform calcs
	for (int i=iBarsToCalc-1;i>=0;i--) {
	
		// DAILY PIVOTS
		// If it's a new day then calc pivots
				datetime dtDayStart0 = getDayStart(Time[i]);
			   datetime dtDayStart1 = getDayStart(Time[i+1]);
			   if (dtDayStart0 != dtDayStart1) {
				// Calculate prev 5 Day average range 00:00 to 00:00
				  double WeeksAvRange = get5DayRange(dtDayStart0);
            // don't recalculate Pivots & SL Lines for Monday - use Sunday's i.e. values from Friday HLC
				   if (TimeDayOfWeek(Time[i]) != 1) {
				        getPrevDayPrices(dPrices,dtDayStart0);
				        getPivots(dPivots,dPrices);
 				   } // end if not a Monday 
 
			  } // End of new day block
		// If the pivots have been updated, this will push out the changes
		// if the pivots haven't been updated, the previous values will carry forward
//		dR3Buffer[i] = dPivots[PIVOT_R3];
		dR2Buffer[i] = dPivots[PIVOT_R2];
		dR1Buffer[i] = dPivots[PIVOT_R1];
		dPPBuffer[i] = dPivots[PIVOT_PP];
		dS1Buffer[i] = dPivots[PIVOT_S1];
		dS2Buffer[i] = dPivots[PIVOT_S2];
//		dS3Buffer[i] = dPivots[PIVOT_S3];
				        // If previous day's range is too big > WeeksAvRange, set StopLoss levels to 0
 				        if (dPivots[PRICE_RANGE] > WeeksAvRange) {
					       sslBuffer[i] = 0;
					       bslBuffer[i] = 0;				
				        } 
				        else {
				        sslBuffer[i] = dPivots[PIVOT_SSL];
		              bslBuffer[i] = dPivots[PIVOT_BSL];
		              }
	}  // End iterate over bars block
   return (0);
} // End main program
void getPivots(double& pivots[], double prices[]) {
		// Calculate the pivots
		pivots[PIVOT_PP] = NormalizeDouble((prices[PRICE_HIGH] + prices[PRICE_LOW] + prices[PRICE_CLOSE]) / 3,Digits);
		pivots[PIVOT_R1] = NormalizeDouble(2 * pivots[PIVOT_PP] - prices[PRICE_LOW],Digits);
		pivots[PIVOT_S1] = NormalizeDouble(2 * pivots[PIVOT_PP] - prices[PRICE_HIGH],Digits);
		pivots[PIVOT_R2] = NormalizeDouble(pivots[PIVOT_PP] + (pivots[PIVOT_R1] - pivots[PIVOT_S1]),Digits);
		pivots[PIVOT_S2] = NormalizeDouble(pivots[PIVOT_PP] - (pivots[PIVOT_R1] - pivots[PIVOT_S1]),Digits);
//		pivots[PIVOT_R3] = NormalizeDouble(prices[PRICE_HIGH] + 2 * (pivots[PIVOT_PP] - prices[PRICE_LOW]),Digits);
//		pivots[PIVOT_S3] = NormalizeDouble(prices[PRICE_LOW] - 2 * (prices[PRICE_HIGH] - pivots[PIVOT_PP]),Digits);
		pivots[PIVOT_SSL] = NormalizeDouble(pivots[PIVOT_S1] + 0.667 * (pivots[PIVOT_S1] - pivots[PIVOT_S2]),Digits); 
		pivots[PIVOT_BSL] = NormalizeDouble(pivots[PIVOT_R1] - 0.667 * (pivots[PIVOT_R2] - pivots[PIVOT_R1]),Digits); 
      pivots[PRICE_RANGE] = NormalizeDouble((prices[PRICE_HIGH] - prices[PRICE_LOW]),Digits);
} // End getPivots



datetime getDayStart(datetime timestamp) {
	// Strip seconds from timestamp
	// (probably not required)
	timestamp -= TimeSeconds(timestamp);
	
	// Strip minutes from timestamp
	timestamp -= TimeMinute(timestamp) * SECONDS_IN_MINUTE;
	
	// Subtract enough hours to reach previous day start
	if (TimeHour(timestamp) >= DayStartHour)
		timestamp -= (TimeHour(timestamp) - DayStartHour) * SECONDS_IN_HOUR;
	else
		timestamp -= (TimeHour(timestamp) + (24 - DayStartHour)) * SECONDS_IN_HOUR;
		
	return(timestamp);
} // End getDayStart

void getPrevDayPrices(double& prices[], datetime timestamp) {

	// Get the last bar of the previous trading day
	// since iBarShift exact param = false, the previous existing bar will be returned
	int 		iBarIndex 		= iBarShift(NULL,PERIOD_H1,timestamp-SECONDS_IN_HOUR,false);
	// Get first 1Hr bar of last 24hr period from DayStarthour to DayStartHour
	datetime	dtPrevDayStart	= getDayStart(iTime(NULL,PERIOD_H1,iBarIndex));
		
	// Get close price for the day and set initial values for high and low
	prices[PRICE_HIGH]	= iHigh (NULL,PERIOD_H1,iBarIndex);
	prices[PRICE_LOW]	   = iLow  (NULL,PERIOD_H1,iBarIndex);
	prices[PRICE_OPEN]	= iOpen (NULL,PERIOD_H1,iBarIndex);
	prices[PRICE_CLOSE]	= iClose(NULL,PERIOD_H1,iBarIndex);
	iBarIndex++;
		
	// Iterate back and check for high/low prices until all of previous trading day covered
	while (getDayStart(iTime(NULL,PERIOD_H1,iBarIndex)) == dtPrevDayStart) {
		prices[PRICE_HIGH] = MathMax(prices[PRICE_HIGH], iHigh (NULL,PERIOD_H1,iBarIndex));
		prices[PRICE_LOW]  = MathMin(prices[PRICE_LOW],  iLow  (NULL,PERIOD_H1,iBarIndex));
 		prices[PRICE_OPEN] = iOpen(NULL,PERIOD_H1,iBarIndex);
		iBarIndex++;
	}
	return;
}

double   get5DayRange( datetime dtDayStart0) {
   datetime dtRangeDay5 = dtDayStart0 - SECONDS_IN_DAY; // back up to previous day
   int iDayCount;
   double d5DayRange;
   while (iDayCount<5) { // Don't include Sunday ranges
      if (TimeDayOfWeek(dtRangeDay5) != 0) {
         // ibarshift will return -1, if the 1Day bar starting at time dtRangeDay5 does not exist 
         int iBarIndex = iBarShift(NULL,PERIOD_D1,dtRangeDay5,true);
				     if (iBarIndex != -1){
				     iDayCount++;
				     d5DayRange += ( iHigh(NULL,PERIOD_D1,iBarIndex)- iLow(NULL,PERIOD_D1,iBarIndex)) ;// Sum  last 5 Daily ranges
				     } 
 	   }
	   dtRangeDay5 -= SECONDS_IN_DAY; // go back another day
	}  
	double Av5DayRange = d5DayRange/5;
   return (Av5DayRange);
}
