//+------------------------------------------------------------------+
//|                         Auto-Pivot Plotter (Mid-Levels) V1-3.mq4 |
//|                                  Copyright � 2006, Elton Treloar |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright � 2006, Elton Treloar"
#property link      ""

#property indicator_chart_window
#property indicator_buffers 8
#property indicator_color1 Blue
#property indicator_color2 Blue
#property indicator_color3 Blue
#property indicator_color4 Black
#property indicator_color5 Red
#property indicator_color6 Red
#property indicator_color7 Red
#property indicator_color8 LimeGreen
//---- input parameters
extern int       StartHour=0;
extern int       StartMinute=0;
extern int       DaysToPlot=15;
//---- buffers
double Res3[];
double Res2[];
double Res1[];
double Pivot[];
double Supp1[];
double Supp2[];
double Supp3[];
double Extra1[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_LINE,STYLE_DOT);
   SetIndexBuffer(0,Res3);
   SetIndexStyle(1,DRAW_LINE,STYLE_DOT);
   SetIndexBuffer(1,Res2);
   SetIndexStyle(2,DRAW_LINE,STYLE_DOT);
   SetIndexBuffer(2,Res1);
   SetIndexStyle(3,DRAW_LINE,STYLE_DOT);
   SetIndexBuffer(3,Pivot);
   SetIndexStyle(4,DRAW_LINE,STYLE_DOT);
   SetIndexBuffer(4,Supp1);
   SetIndexStyle(5,DRAW_LINE,STYLE_DOT);
   SetIndexBuffer(5,Supp2);
   SetIndexStyle(6,DRAW_LINE,STYLE_DOT);
   SetIndexBuffer(6,Supp3);
   SetIndexStyle(7,DRAW_LINE,STYLE_DOT);
   SetIndexBuffer(7,Extra1);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    counted_bars=IndicatorCounted();
   
   if(counted_bars<0) return(-1);
   //---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;

   int limit=Bars-counted_bars;
   int StartMinutesIntoDay=(StartHour*60)+StartMinute; // 8' o'clock x 60 = 480
   int CloseMinutesIntoDay=StartMinutesIntoDay-Period(); //
   // ****************************************************
   //    Check That cloes time isn't now a negative number.
   //    Correct if it is by adding a full day's worth 
   //    of minutes.
   // ****************************************************
   
   if (CloseMinutesIntoDay<0)
      {
         CloseMinutesIntoDay=CloseMinutesIntoDay+1440;
      }
      
   // ****************************************************
   //    Establish the nuber of bars in a day.
   // ****************************************************
   int BarsInDay=1440/Period();
    
   // ******************************************************************************************
   // ******************************************************************************************
   //                                        Main Loop                                      
   // ******************************************************************************************
   // ******************************************************************************************
   
   for(int i=0; i<limit; i++)
   { 
      // ***************************************************************************
      //       Only do all this if we are within the plotting range we want.
      //       i.e. DaysToPlot 
      //       If DaysToPlot is "0" (zero) we plot ALL available data. This can be 
      //    VERY slow with a large history and at small time frames. Expect to
      //    wait if plotting a year or more on a say a five minute chart. On my PC 
      //    two years of data at Five Minutes takes around 30 seconds per indicator. 
      //    i.e. 30 seconds for main pivot levels indicator then another 30 seconds 
      //    to plot the seperate mid-levels indicator. 
      // ***************************************************************************
      if ( (i<((DaysToPlot+1)*BarsInDay))||DaysToPlot==0)   // Used to limit the number of days
      {                                                     // that are mapped out. Less waiting ;)
      
      // *****************************************************
      //    Find previous day's opening and closing bars.
      // *****************************************************
      
      int PreviousClosingBar = FindLastTimeMatch(CloseMinutesIntoDay,BarsInDay,i+1);
      int PreviousOpeningBar = FindLastTimeMatch(StartMinutesIntoDay,BarsInDay,PreviousClosingBar+1);
      double PreviousHigh= High[PreviousClosingBar];
      double PreviousLow = Low [PreviousClosingBar];
      double PreviousClose = Close[PreviousClosingBar];
      
      // *****************************************************
      //    Find previous day's high and low.
      // *****************************************************
      
      for (int SearchHighLow=PreviousClosingBar;SearchHighLow<(PreviousOpeningBar+1);SearchHighLow++)
      {
         if (High[SearchHighLow]>PreviousHigh) PreviousHigh=High[SearchHighLow];
         if (Low[SearchHighLow]<PreviousLow) PreviousLow=Low[SearchHighLow];
      }
      
      // ************************************************************************
      //    Calculate Pivot lines and map into indicator buffers.
      // ************************************************************************
      
            double P =  (PreviousHigh+PreviousLow+PreviousClose)/3;
            double R1 = (2*P)-PreviousLow;
            double S1 = (2*P)-PreviousHigh;
            double R2 =  P+(PreviousHigh - PreviousLow);
            double S2 =  P-(PreviousHigh - PreviousLow);
            double R3 = (2*P)+(PreviousHigh-(2*PreviousLow));
            double S3 = (2*P)-((2* PreviousHigh)-PreviousLow); 
            
       //   **********************************************
       //      Calculate the mid-levels in to the buffers. 
       //   **********************************************(Twe)
            
            Res1[i] =((R1-P)/2)+P;    //M3
            Res2[i] =((R2-R1)/2)+R1;  //M4
            Res3[i] =((R3-R2)/2)+R2;  
            Supp1[i]=((P-S1)/2)+S1;   //M2
            Supp2[i]=((S1-S2)/2)+S2;  //M1
            Supp3[i]=((S2-S3)/2)+S3;

      //            Pivot[i]=P;
      //            Res1[i] =R1;    
      //            Res2[i] =R2;  
      //            Res3[i] =R3;  
      //            Supp1[i]=S1;   
      //            Supp2[i]=S2;  
      //            Supp3[i]=S3;
      //            Extra1[i]=OpenPriceAt+i;

      } //End of 'DaysToPlot 'if' statement.
   }   
      // ***************************************************************************************
      //                            End of Main Loop
      // ***************************************************************************************


   // *******************************************************************
   //    Return From Start() (Main Routine)
   return(0);
  }
//+------------------------------------------------------------------+

// *****************************************************************************************
// -----------------------------------------------------------------------------------------
//    The following routine will look a particular time (in minutes of day) starting from
//    bar "StartingBar" and searching as far back as "BarsInDay".
// -----------------------------------------------------------------------------------------

int FindLastTimeMatch(int TimeToLookFor,int BarsInDay,int StartingBar) //0 48 
   {

   for (int SearchCount= StartingBar ;SearchCount<(StartingBar + BarsInDay+5) ;SearchCount++)
      {
      // ******************************************************************************
      //    Find time (in minutes) of the current bar AND the two bars either side of it.
      // This is done to allow for any missing bars in the data.   i.e. If THE bar you 
      // were after were to be missing you'd never get a valid close/open time.  
      //    This is the same reason for searching rather than just looking back a certain
      // number of bars from the close time. Missing bars upset the count back and 
      // screw up all pivot calculations. There is still room for error but it's improved.
      // The best calculations will come from having the best data. ...of course. :)
      // ******************************************************************************
      //
      int PreviousBarsTime=(TimeHour(Time[SearchCount+1])*60)+TimeMinute(Time[SearchCount+1]);
      int CurrentBarsTime=(TimeHour(Time[SearchCount])*60)+TimeMinute(Time[SearchCount]);
      int NextBarsTime=(TimeHour(Time[SearchCount-1])*60)+TimeMinute(Time[SearchCount-1]);
      
      if (CurrentBarsTime==TimeToLookFor)
         {
         return(SearchCount);    // *** If current bar is what we are after than lets get out.
                                 // *** without mucking about with the rest of the checks.
         }
      
      // **********************************
      //    Check that previous bar doesn't
      // lay on a different day.
      //    Adjust if it is
      // **********************************
      if(PreviousBarsTime>CurrentBarsTime)  
         {                                       
         PreviousBarsTime=PreviousBarsTime-1440;
         }
      // **********************************
      //    Check that following bar doesn't
      // lay on a different day. 
      //    Adjust if it is.
      // **********************************
      if(NextBarsTime<CurrentBarsTime)         
         {
         NextBarsTime=NextBarsTime+1440;
         }
      // ******************************************
      //    If this is the best we can get
      // to the actual bar we are after, then 
      // exit, returning current bar number.
      // *******************************************    
      if(PreviousBarsTime<TimeToLookFor)
         {
            if( TimeToLookFor<NextBarsTime)
            {
            return(SearchCount);
            }
         }
      }
  
   return(0);
   }