//+------------------------------------------------------------------+
//|                                                 pivot points.mq4 |
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_separate_window
#property indicator_buffers 8
#property indicator_color1 DimGray
#property indicator_color2 DeepSkyBlue
#property indicator_color3 PaleVioletRed
#property indicator_color4 DeepSkyBlue
#property indicator_color5 PaleVioletRed
#property indicator_color6 DeepSkyBlue
#property indicator_color7 PaleVioletRed
#property indicator_color8 PaleVioletRed
#property indicator_style1 STYLE_DOT
#property indicator_style2 STYLE_DOT
#property indicator_style3 STYLE_DOT
#property indicator_style4 STYLE_DOT
#property indicator_style5 STYLE_DOT
#property indicator_style6 STYLE_DOT
#property indicator_style7 STYLE_DOT
#property indicator_width8 2

//
//
//
//
//

extern int    PivotLevel            = 3;
extern int    PivotPrice            = PRICE_CLOSE;
string PivotIdentifier       = "pivot oscialltor 1";
extern string TimeFrame             = "D1";
extern int    HourShift             = 0;
extern bool   FixSundays            = true;
extern bool   ShowLabels            = true;
extern bool   ShowValues            = false;
extern color  LabelsColor           = DimGray;
extern int    LabelsFontSize        =  10;
extern int    LabelsShiftHorizontal = -15;
extern int    LabelsShiftVertical   =  10;


//
//
//
//
//

double PBuffer[];
double S1Buffer[];
double R1Buffer[];
double S2Buffer[];
double R2Buffer[];
double S3Buffer[];
double R3Buffer[];
double Price[];

//
//
//
//
//

string labels[7] = {"pivot" ,"S1","R1","S2","R2","S3","R3"};
int    timeFrame;
int    lookupTimeFrame;
string Description;


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

int init()
{
   lookupTimeFrame = PERIOD_H1;
   timeFrame       = stringToTimeFrame(TimeFrame);
            if (timeFrame<PERIOD_D1)
            {
               HourShift=0;
               lookupTimeFrame = timeFrame;
            }         
            if (timeFrame==PERIOD_W1)
            {
               if (HourShift<0) HourShift -= 24;
               if (HourShift>0) HourShift += 24;
            }
            PivotLevel = MathMax(MathMin(PivotLevel,3),1);
   
   //
   //
   //
   //
   //
   
      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]);
      SetIndexBuffer(7,Price); 
      PivotIdentifier=PivotIdentifier+TimeFrame+PivotLevel;
   IndicatorShortName(PivotIdentifier);
   return(0);
}

int deinit()
{
   for (int i = 7; i>0; i--) ObjectDelete(StringConcatenate(PivotIdentifier,"-",i));
   return(0);
}


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

double work[][7];
#define _p  0
#define _s1 1
#define _s2 2
#define _s3 3
#define _r1 4
#define _r2 5
#define _r3 6

//
//
//
//
//

int start()
{
   int counted_bars=IndicatorCounted();
   int i,r,limit;

   if (Period() >= timeFrame) return(-1);
   if (counted_bars<0) return(-1);
   if (counted_bars>0) counted_bars--;
      limit = MathMin(Bars-counted_bars,Bars-1);
      if (ArrayRange(work,0)!=Bars) ArrayResize(work,Bars);

   //
   //
   //
   //
   //

   double P =  work[Bars-limit-2][_p];
   double S1 = work[Bars-limit-2][_s1];
   double R1 = work[Bars-limit-2][_r1];
   double S2 = work[Bars-limit-2][_s2];
   double R2 = work[Bars-limit-2][_r2];
   double S3 = work[Bars-limit-2][_s3];
   double R3 = work[Bars-limit-2][_r3];
   
   for (i=limit,r=Bars-i-1; i>=0; i--,r++)
   {
      int x = iBarShift(NULL,timeFrame,Time[i+1]-HourShift*3600,true);
      int y = iBarShift(NULL,timeFrame,Time[i]  -HourShift*3600,true);
      if (x!=y)
      {
         int k = i;
         if (FixSundays && timeFrame==PERIOD_D1)
         {
            while (k<Bars && TimeDayOfWeek(Time[k+1]-HourShift*3600)==0) k++;
         }
         int z = iBarShift(NULL,lookupTimeFrame,Time[k+1]-timeFrame*60-HourShift*3600);
             x = iBarShift(NULL,lookupTimeFrame,Time[k+1]             -HourShift*3600);
               
             //
             //
             //
             //
             //

             double LastHigh  = iHigh (NULL,lookupTimeFrame,iHighest(NULL,lookupTimeFrame,MODE_HIGH,z-x,x));
             double LastLow   = iLow  (NULL,lookupTimeFrame,iLowest( NULL,lookupTimeFrame,MODE_LOW ,z-x,x));
             double LastClose = Close[k+1];
               
             //
             //
             //
             //
             //
               
             P  = (LastHigh+LastLow+LastClose)/3;
             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); 
      }
                  
      //
      //
      //
      //
      //

         work[r][_p] =P;
         work[r][_s1]=S1;
         work[r][_r1]=R1;
         work[r][_s2]=S2;
         work[r][_r2]=R2;
         work[r][_s3]=S3;
         work[r][_r3]=R3;

         //
         //
         //
         //
         //
         
         double range;
         double lower;
         switch (PivotLevel)
         {
            case 1 : 
               lower = work[r][_s1];
               range = work[r][_r1]-work[r][_s1];
               if (range!=0)
               {
                  R1Buffer[i] =  1;
                  S1Buffer[i] = -1;
               }                  
               break;
               
               //
               //
               //
               //
               //
               
            case 2 : 
               lower = work[r][_s2];
               range = work[r][_r2]-work[r][_s2];
               if (range!=0)
               {
                  R2Buffer[i] =  1;
                  S2Buffer[i] = -1;
                  R1Buffer[i] = 2.0*((work[r][_r1]-lower)/range-0.5);
                  S1Buffer[i] = 2.0*((work[r][_s1]-lower)/range-0.5);
               }
               break;
               
               //
               //
               //
               //
               //
                              
            case 3 : 
               lower = work[r][_s3];
               range = work[r][_r3]-work[r][_s3];
               if (range!=0)
               {
                  R3Buffer[i] =  1;
                  S3Buffer[i] = -1;
                  R1Buffer[i] = 2.0*((work[r][_r1]-lower)/range-0.5);
                  S1Buffer[i] = 2.0*((work[r][_s1]-lower)/range-0.5);
                  R2Buffer[i] = 2.0*((work[r][_r2]-lower)/range-0.5);
                  S2Buffer[i] = 2.0*((work[r][_s2]-lower)/range-0.5);
               }
               break;
         }

         //
         //
         //
         //
         //
         
         if (range !=0)
         {
            PBuffer[i] = 2.0*((work[r][_p]-lower)/range-0.5);
            Price[i]   = 2.0*((iMA(NULL,0,1,0,MODE_SMA,PivotPrice,i)-lower)/range-0.5);
         }
   }
   if (ShowLabels) DisplayLabels();
   return(0);
}



//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+
//
//
//
//
//

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 (ShowValues) 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    = PivotIdentifier+"-"+ID;
   int      window = WindowFind(PivotIdentifier);
   
   if(ObjectFind(name)==-1) {
      ObjectCreate(name,OBJ_TEXT,window,0,0);
      ObjectSetText(name,label,LabelsFontSize,"Arial",LabelsColor); }
      ObjectMove(name,0,theTime,forLine+LabelsShiftVertical/100.0);
   
}

//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+
//
//
//
//
//

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 ";   }
  return(tf);
}

//
//
//
//
//

string StringUpperCase(string str)
{
   string   s = str;
   int      length = StringLen(str) - 1;
   int      char;
   
   while(length >= 0)
      {
         char = StringGetChar(s, length);
         
         //
         //
         //
         //
         //
         
         if((char > 96 && char < 123) || (char > 223 && char < 256))
                  s = StringSetChar(s, length, char - 32);
         else 
              if(char > -33 && char < 0)
                  s = StringSetChar(s, length, char + 224);
         length--;
   }
   return(s);
}