//+------------------------------------------------------------------+
//|                                                       pivots.mq4 |
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

//---- indicator settings
#define PERIOD_Y 999999
#property indicator_chart_window
#property indicator_buffers 7
#property indicator_color1 Silver
#property indicator_color2 Aqua
#property indicator_color3 Tomato
#property indicator_color4 Aqua
#property indicator_color5 Tomato
#property indicator_color6 Aqua
#property indicator_color7 Tomato
#property indicator_width1 3
#property indicator_width2 2
#property indicator_width3 2
#property indicator_width4 2
#property indicator_width5 2
#property indicator_width6 2
#property indicator_width7 2

//---- input parameters
extern string LabelIdentifier        = "uniqueIdentifier1";
extern string TimeFrame              = "D1";
extern int    PeriodsCount           =  0;
extern bool   FixSundays             = true;
extern bool   ShowFibos              = false;
extern bool   HideConnections        = true;
extern bool   ShowLabels             = true;
extern bool   ShowPrices             = true;
extern color  LabelsColor            = Silver;
extern int    LabelsFontSize         =  10;
extern int    LabelsShiftHorizontal  = -10;
extern int    LabelsShiftVertical    =   1;

extern bool   alertsOn               = true;
extern bool   alertsMessage          = true;
extern bool   alertsSound            = true;
extern bool   alertsEmail            = false;

//---- indicator buffers
double PBuffer[];
double S1Buffer[];
double R1Buffer[];
double S2Buffer[];
double R2Buffer[];
double S3Buffer[];
double R3Buffer[];

//----
datetime yearDates[];
double   yearHigh[];
double   yearLow[];
double   yearClose[];

//----
string labels[7] = {"pivot" ,"S1","R1","S2","R2","S3","R3"};
string sounds[7] = {"alert2","S1","R1","S2","R2","S3","R3"};
int    timeFrame;
string windowID;
string Description;


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

int init()
{
   windowID  = LabelIdentifier;
   timeFrame = stringToTimeFrame(TimeFrame);
      if (PeriodsCount<=0) PeriodsCount=99999;
      if (ShowFibos)       Description =Description+"f";
   
   //
   //
   //
   //
   //
   
      SetIndexBuffer(0,PBuffer);  SetIndexLabel(0,Description+labels[0]);
      SetIndexBuffer(1,S1Buffer); SetIndexLabel(1,Description+labels[1]);
      SetIndexBuffer(2,R1Buffer); SetIndexLabel(2,Description+labels[2]);
      SetIndexBuffer(3,S2Buffer); SetIndexLabel(3,Description+labels[3]);
      SetIndexBuffer(4,R2Buffer); SetIndexLabel(4,Description+labels[4]);
      SetIndexBuffer(5,S3Buffer); SetIndexLabel(5,Description+labels[5]);
      SetIndexBuffer(6,R3Buffer); SetIndexLabel(6,Description+labels[6]);
      if (timeFrame==PERIOD_Y)
            SetUpArray();
   return(0);
}

int deinit()
{
   for (int i = 7; i>0; i--) ObjectDelete(StringConcatenate(windowID,"-",i));
   return(0);
}


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int start()
{
   int      counted_bars=IndicatorCounted();
   datetime TimeArray[];
   int      remain=PeriodsCount;
   int      i,p,limit;
   double   R,P,S1,R1,S2,R2,S3,R3;


   if (counted_bars<0) return(-1);
   if (counted_bars>0) counted_bars--;
      limit = Bars-counted_bars;

   if (Period() >= timeFrame) return(-1);

   //
   //
   //
   //
   //

   if (timeFrame==PERIOD_Y)
          ArrayCopy(TimeArray,yearDates);
   else   ArrayCopySeries(TimeArray ,MODE_TIME,NULL,timeFrame);
   
   //
   //
   //
   //
   //
   
   for (i=0,p=0; i<limit;i++)
      {
         if (Time[i]<TimeArray[p] || i == 0)
            {
               if (i != 0)
                  {
                     p++;
                        if (timeFrame==PERIOD_D1) {
                        if (FixSundays) {
                        if (TimeDayOfWeek(TimeArray[p+1]) == 0) p++; }}
                              
                     remain--;
                     if (remain<=0) break;
                  }

                  //
                  //
                  //
                  //
                  //
                                       
                  double LastLow  = iiLow(timeFrame,p+1);
                  double LastHigh = iiHigh(timeFrame,p+1);
                  
                  //
                  //
                  //
                  //
                  //
                  //

                  P  = (LastHigh+LastLow+iiClose(timeFrame,p+1))/3;
                  if (ShowFibos)
                     {
                        R  = LastHigh-LastLow;
                        R1 = P + (R * 0.382);
                        S1 = P - (R * 0.382);
                        R2 = P + (R * 0.618);
                        S2 = P - (R * 0.618);
                        R3 = P + (R * 1.000);
                        S3 = P - (R * 1.000);
                  
                     }
                  else
                     {
                        R1 = (2*P)-LastLow;
                        S1 = (2*P)-LastHigh;
                        R2 = P+(LastHigh - LastLow);
                        S2 = P-(LastHigh - LastLow);
                        R3 = (2*P)+(LastHigh-(2*LastLow));
                        S3 = (2*P)-((2* LastHigh)-LastLow); 
                     }                     
            }

         //
         //
         //
         //
         //
         
         PBuffer[i] =P;
         S1Buffer[i]=S1;
         R1Buffer[i]=R1;
         S2Buffer[i]=S2;
         R2Buffer[i]=R2;
         S3Buffer[i]=S3;
         R3Buffer[i]=R3;
   }
   if (ShowLabels || ShowPrices) DisplayLabels();
   if (alertsOn)   CheckCrossings();
   if (HideConnections) DoHideConnections(limit);
   return(0);
}



//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+
//
//
//
//
//

double iiLow(int tf,int shift)
{
   if (tf==PERIOD_Y)
         return(yearLow[shift]);
   else  return(iLow(NULL,tf,shift));    
}
double iiHigh(int tf,int shift)
{
   if (tf==PERIOD_Y)
         return(yearHigh[shift]);
   else  return(iHigh(NULL,tf,shift));    
}
double iiClose(int tf,int shift)
{
   if (tf==PERIOD_Y)
         return(yearClose[shift]);
   else  return(iClose(NULL,tf,shift));    
}

//
//
//
//
//

void SetUpArray()
{
   datetime timeArray[];
   int      firstYear;
   int      lastYear;
   int      counter;
   int      i,y;

      ArrayCopySeries(timeArray ,MODE_TIME,NULL,PERIOD_MN1);
            firstYear = TimeYear(timeArray[0]);
            lastYear  = TimeYear(timeArray[ArraySize(timeArray)]);
 
            //
            //
            //
            //
            //

            y = firstYear-lastYear+1;
            ArrayResize(yearDates,y); ArraySetAsSeries(yearDates,true);
            ArrayResize(yearHigh ,y); ArraySetAsSeries(yearHigh ,true); ArrayInitialize(yearHigh ,-99999999.99);
            ArrayResize(yearLow  ,y); ArraySetAsSeries(yearLow  ,true); ArrayInitialize(yearLow  ,+99999999.99);
            ArrayResize(yearClose,y); ArraySetAsSeries(yearClose,true); ArrayInitialize(yearClose,0.00);
                  for (counter=firstYear-lastYear;counter>=0;counter--)
                  {
                     yearDates[counter] = StrToTime(DoubleToStr(lastYear,0)+".01.01 00:00"); lastYear++;
                  }
      //
      //
      //
      //
      //
                        
      yearClose[0] = Close[0];
         for (i=0,y=0; i<ArraySize(timeArray)-1; i++)
         {
            if (iTime(NULL,PERIOD_MN1,i)<yearDates[y]) { y++;    yearClose[y] = iClose(NULL,PERIOD_MN1,i);}
                     if (yearHigh[y] < iHigh(NULL,PERIOD_MN1,i)) yearHigh[y]  = iHigh(NULL,PERIOD_MN1,i);
                     if (yearLow[y]  > iLow(NULL,PERIOD_MN1,i))  yearLow[y]   = iLow(NULL,PERIOD_MN1,i);
         }
                  
}

//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+
//
//
//
//
//

int barTime(int a)
{
   if(a<0)
         return(Time[0]+Period()*60*MathAbs(a));
   else  return(Time[a]);   
}

//
//
//
//
//

void DisplayLabels()
{
   ShowLabel(1,PBuffer ,Description+labels[0]);
   ShowLabel(2,S1Buffer,Description+labels[1]);
   ShowLabel(3,R1Buffer,Description+labels[2]);
   ShowLabel(4,S2Buffer,Description+labels[3]);
   ShowLabel(5,R2Buffer,Description+labels[4]);
   ShowLabel(6,S3Buffer,Description+labels[5]);
   ShowLabel(7,R3Buffer,Description+labels[6]);
}
void ShowLabel(string ID, double& forLine[],string label)
{
   string finalLabel = "";
   
   if (ShowLabels) finalLabel = label;
   if (ShowPrices) finalLabel = finalLabel+" "+DoubleToStr(forLine[0],Digits);
         SetLabel(ID,forLine[0],finalLabel);
}

//
//
//
//
//

void SetLabel(string ID,double forLine,string label)
{
   datetime theTime = barTime(LabelsShiftHorizontal);
   string   name    = windowID+"-"+ID;
   
   if(ObjectFind(name)==-1) {
      ObjectCreate(name,OBJ_TEXT,0,0,0);
      ObjectSetText(name,label,LabelsFontSize,"Arial",LabelsColor); }
      ObjectMove(name,0,theTime,forLine+LabelsShiftVertical*Point);
   
}

//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+
//
//
//
//
//

void DoHideConnections(int limit)
{
   
   for (int i=limit;i>=0;i--)
   {
      if (PBuffer[i]  != PBuffer[i+1])  HideIt(i,PBuffer);
      if (R1Buffer[i] != R1Buffer[i+1]) HideIt(i,R1Buffer);
      if (S1Buffer[i] != S1Buffer[i+1]) HideIt(i,S1Buffer);
      if (R2Buffer[i] != R2Buffer[i+1]) HideIt(i,R2Buffer);
      if (S2Buffer[i] != S2Buffer[i+1]) HideIt(i,S2Buffer);
      if (R3Buffer[i] != R3Buffer[i+1]) HideIt(i,R3Buffer);
      if (S3Buffer[i] != S3Buffer[i+1]) HideIt(i,S3Buffer);
   }
}

void HideIt(int i, double& from[])
{
   if ((from[i] != EMPTY_VALUE) && (from[i+1] != EMPTY_VALUE))
        from[i+1] = EMPTY_VALUE;  
}

//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+
//
//
//
//
//

void CheckCrossings()
{
   double currPrice = Close[0];
   double prevPrice = Close[1];
   
      CheckIfCrossed(currPrice,prevPrice,0,PBuffer);
      CheckIfCrossed(currPrice,prevPrice,1,S1Buffer);
      CheckIfCrossed(currPrice,prevPrice,2,R1Buffer);
      CheckIfCrossed(currPrice,prevPrice,3,S2Buffer);
      CheckIfCrossed(currPrice,prevPrice,4,R2Buffer);
      CheckIfCrossed(currPrice,prevPrice,5,S3Buffer);
      CheckIfCrossed(currPrice,prevPrice,6,R3Buffer);
}

void CheckIfCrossed(double curr, double prev, int index, double& compareTo[])
{
   if (curr > compareTo[0] && prev < compareTo[1]) doAlert(index,Description+labels[index]+" line crossed up");
   if (curr < compareTo[0] && prev > compareTo[1]) doAlert(index,Description+labels[index]+" line crossed down");
}

//
//
//
//
//

void doAlert(int whichSound,string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
      if (previousAlert != doWhat || previousTime != Time[0]) {
          previousAlert  = doWhat;
          previousTime   = Time[0];

          //
          //
          //
          //
          //

          message =  StringConcatenate(Symbol()," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," pivot ",doWhat);
             if (alertsMessage) Alert(message);
             if (alertsEmail)   SendMail(StringConcatenate(Symbol()," pivot line crossing"),message);
             if (alertsSound)   PlaySound(sounds[whichSound]+".wav");
      }
}


//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+
//
//
//
//
//

int stringToTimeFrame(string tfs)
{
   int tf=0;
       tfs = StringUpperCase(tfs);
         if (tfs=="M1" || tfs=="1")     { tf=PERIOD_M1;  Description = "";}
         if (tfs=="M5" || tfs=="5")     { tf=PERIOD_M5;  Description = "5 minutes "; }
         if (tfs=="M15"|| tfs=="15")    { tf=PERIOD_M15; Description = "15 minutes ";}
         if (tfs=="M30"|| tfs=="30")    { tf=PERIOD_M30; Description = "half hour "; }
         if (tfs=="H1" || tfs=="60")    { tf=PERIOD_H1;  Description = "hourly ";    }
         if (tfs=="H4" || tfs=="240")   { tf=PERIOD_H4;  Description = "4 hourly ";  }
         if (tfs=="D1" || tfs=="1440")  { tf=PERIOD_D1;  Description = "daily ";     }
         if (tfs=="W1" || tfs=="10080") { tf=PERIOD_W1;  Description = "weekly ";    }
         if (tfs=="MN" || tfs=="43200") { tf=PERIOD_MN1; Description = "monthly ";   }
         if (tfs=="Y" )                 { tf=PERIOD_Y;   Description = "yearly ";    }
  return(tf);
}

//
//
//
//
//

string StringUpperCase(string str)
{
   string   s = str;
   int      lenght = StringLen(str) - 1;
   int      tchar;
   
   while(lenght >= 0)
      {
         tchar = StringGetChar(s, lenght);
         
         //
         //
         //
         //
         //
         
         if((tchar > 96 && tchar < 123) || (tchar > 223 && tchar < 256))
                  s = StringSetChar(s, lenght, tchar - 32);
         else 
              if(tchar > -33 && tchar < 0)
                  s = StringSetChar(s, lenght, tchar + 224);
         lenght--;
   }
   return(s);
}