//+------------------------------------------------------------------+
//|                                            Davits_Pivot_V3.2.mq5 |
//|                                                     Griffinssoul |
//|                         http://www.forexfactory.com/griffinssoul |
//+------------------------------------------------------------------+
#property copyright "Griffinssoul"
#property link      "http://www.forexfactory.com/griffinssoul"
#property version   "3.20"
#property indicator_plots 0
#property indicator_chart_window

#property description "Griffinssoul 2016.02.28 - added 78.6 fib-pivot and price to lines."
#property description "Griffinssoul 2016.02.28 - added long and short horizontal lines."
#property description "Nico Scholtz 2016.09.19 - fixed bug in manual pivot calculation."

//--- input parameters
input bool          autoTimeAdjustment = true;
input int           timeZoneOfData = -5;                  // TimeZoneOfData (NewYork GMT)
input bool          brokercandle = true;                  // Broker's Candle
input datetime      startofpivot = D'2026.09.12 07:00';  // Choose H1 Start Candle
input datetime      endofpivot   = D'2026.09.19 06:00';  // Choose H1 Finish Candle
input bool          StartEndLines = true;                 // Display Start and End lines for manual settings
input group         "Choose the TF ";
enum TFOfPivot
{
   M=1,     // MN
   W=2,     // W1
   D=3,     // D1
};
input TFOfPivot     swaptf = 2;

input group         "Choose Pivot Method ";
enum PivotMethod
{
   HLC=1,      // Avg of High, Low, Close
   HLCC=2,     // Avg of High, Low, Close, Close
   HLOC=3,     // Avg of High, Low, Open, Close
   HLOO=4,     // Avg of High, Low, Open, Open
   HLO=5,      // Avg of High, Low, Open
};
input PivotMethod   pivot_meth = 1;

input bool          pivot_fib = true;                    // Choose Fib(true) or Standard(false)

input color         chose_color_pivot = clrYellow;
input color         label_color_pivot = clrYellow;
input int           width_of_pivot_line = 0;
input int           line_style_of_pivot = 4;

input color         chose_color_R38 = clrMagenta;
input color         label_color_R38 = clrMagenta;
input color         chose_color_R61 = clrLime;
input color         label_color_R61 = clrLime;
input color         chose_color_R78 = clrRed;
input color         label_color_R78 = clrRed;
input color         chose_color_R100 = clrCyan;
input color         label_color_R100 = clrCyan;
input color         chose_color_R138 = clrOrange;
input color         label_color_R138 = clrOrange;
input color         chose_color_R161 = clrBlack;
input color         label_color_R161 = clrBlack;
input color         chose_color_R200 = clrDarkKhaki;
input color         label_color_R200 = clrDarkKhaki;
input int           width_of_R_line = 0;
input int           line_style_of_R = 0;

input color         chose_color_S38 = clrMagenta;
input color         label_color_S38 = clrMagenta;
input color         chose_color_S61 = clrLime;
input color         label_color_S61 = clrLime;
input color         chose_color_S78 = clrRed;
input color         label_color_S78 = clrRed;
input color         chose_color_S100 = clrCyan;
input color         label_color_S100 = clrCyan;
input color         chose_color_S138 = clrOrange;
input color         label_color_S138 = clrOrange;
input color         chose_color_S161 = clrBlack;
input color         label_color_S161 = clrBlack;
input color         chose_color_S200 = clrDarkKhaki;
input color         label_color_S200 = clrDarkKhaki;
input int           width_of_S_line = 0;
input int           line_style_of_S = 0;

input int           LL = 40;                             // Length of lines
input int           SS = 0;                              // Shift to right
input bool          show_200 = false;                   // Show all S&R to 200%
input bool          ShortHorizontalLines = false;       // Short(default) or Long(with price labels) horizontal lines

//--- global variables
double wclose  = 0;
double wopen   = 0;
double whigh   = 0;
double wlow    = 0;
double calPivot = 0;
double calRange = 0;
double R38  = 0, R61  = 0, R78  = 0, R100 = 0, R138 = 0, R161 = 0, R200 = 0;
double S38  = 0, S61  = 0, S78  = 0, S100 = 0, S138 = 0, S161 = 0, S200 = 0;
double R1 = 0, R2 = 0, R3 = 0, S1 = 0, S2 = 0, S3 = 0;
ENUM_TIMEFRAMES chose_tf;
string labelR38, labelR61, labelR78, labelR100;
string labelS38, labelS61, labelS78, labelS100;
datetime weekOpen, weekClose;
int weekCount = 0;
int diffGMT;

#define PREFIX "Davits_Pivot_"

//------------------------------------------------------------------+
// Helper: get day of week (0=Sunday, 6=Saturday)
int TimeDayOfWeek(datetime time)
{
   MqlDateTime tm;
   TimeToStruct(time, tm);
   return tm.day_of_week;
}

//------------------------------------------------------------------+
// Helper: get bar shift for a given time on a specified timeframe
int GetBarShiftByTime(const string symbol, ENUM_TIMEFRAMES tf, datetime time)
{
   datetime times[];
   int total = CopyTime(symbol, tf, 0, 1000, times);
   if(total == -1) return -1;
   for(int i = total - 1; i >= 0; i--)
   {
      if(times[i] <= time)
         return i;
   }
   return -1;
}

//------------------------------------------------------------------+
// Helper: get open, high, low, close for a bar on a timeframe
bool GetOHLC(const string symbol, ENUM_TIMEFRAMES tf, int shift,
             double &open, double &high, double &low, double &close)
{
   double arr[];
   if(CopyOpen(symbol, tf, shift, 1, arr) != 1) return false;
   open = arr[0];
   if(CopyHigh(symbol, tf, shift, 1, arr) != 1) return false;
   high = arr[0];
   if(CopyLow(symbol, tf, shift, 1, arr) != 1) return false;
   low = arr[0];
   if(CopyClose(symbol, tf, shift, 1, arr) != 1) return false;
   close = arr[0];
   return true;
}

//------------------------------------------------------------------+
// Helper struct for levels
struct Level
{
   string name;
   double price;
   color lineColor;
   color labelColor;
   string label;
};

//------------------------------------------------------------------+
// Helper function to draw one level (line + optional label)
void DrawLevel(string name, double price, color lineColor, color labelColor,
               int width, int style, string labelText,
               datetime startTime, datetime currentTime, int periodSec,
               bool shortLines)
{
   if(shortLines)
   {
      datetime endTime = currentTime + periodSec * (900 + SS);
      if(ObjectCreate(0, name, OBJ_TREND, 0, startTime, price, endTime, price))
      {
         ObjectSetInteger(0, name, OBJPROP_COLOR, (long)lineColor);
         ObjectSetInteger(0, name, OBJPROP_WIDTH, width);
         ObjectSetInteger(0, name, OBJPROP_STYLE, (long)style);
         ObjectSetInteger(0, name, OBJPROP_RAY, 0);
      }
      string labelName = name + "_label";
      if(ObjectCreate(0, labelName, OBJ_TEXT, 0, currentTime + periodSec * (600 + SS), price))
      {
         string text = labelText + DoubleToString(price, _Digits);
         ObjectSetString(0, labelName, OBJPROP_TEXT, text);
         ObjectSetInteger(0, labelName, OBJPROP_COLOR, (long)labelColor);
         ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 10);
         ObjectSetString(0, labelName, OBJPROP_FONT, "Arial");
      }
   }
   else
   {
      if(ObjectCreate(0, name, OBJ_HLINE, 0, 0, price))
      {
         ObjectSetInteger(0, name, OBJPROP_COLOR, (long)lineColor);
         ObjectSetInteger(0, name, OBJPROP_WIDTH, width);
         ObjectSetInteger(0, name, OBJPROP_STYLE, (long)style);
         ObjectSetInteger(0, name, OBJPROP_RAY, 0);
      }
      string labelName = name + "_label";
      if(ObjectCreate(0, labelName, OBJ_TEXT, 0, currentTime + periodSec * (600 + SS), price))
      {
         ObjectSetString(0, labelName, OBJPROP_TEXT, labelText);
         ObjectSetInteger(0, labelName, OBJPROP_COLOR, (long)labelColor);
         ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 10);
         ObjectSetString(0, labelName, OBJPROP_FONT, "Arial");
      }
   }
}

//+------------------------------------------------------------------+
//| Custom indicator initialization function                          |
//+------------------------------------------------------------------+
int OnInit()
{
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                        |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   ObjectsDeleteAll(0, PREFIX);
   ChartRedraw(0);
}

//+------------------------------------------------------------------+
//| Custom indicator calculation function                             |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   ObjectsDeleteAll(0, PREFIX);

   diffGMT = timeZoneOfData * 3600 + TimeGMTOffset();

   if(autoTimeAdjustment)
   {
      weekCount = 0;
      datetime h1times[];
      int copied = CopyTime(_Symbol, PERIOD_H1, 0, 250, h1times);
      if(copied < 250) return(0);

      for(int z = 1; z < 250; z++)
      {
         if(h1times[z] / 86400 < h1times[z-1] / 86400 && TimeDayOfWeek(h1times[z]) == 5 && weekCount == 0)
         {
            if(diffGMT < 0)
               weekClose = h1times[z] - diffGMT + (48 * 3600);
            else
               weekClose = h1times[z] - diffGMT;
            weekCount = 1;
         }
         else if(z+1 < 250 && h1times[z+1] / 86400 < h1times[z] / 86400 && TimeDayOfWeek(h1times[z+1]) == 5 && weekCount == 1)
         {
            if(diffGMT > 0)
               weekOpen = h1times[z] - diffGMT - (48 * 3600);
            else
               weekOpen = h1times[z] - diffGMT;
            weekCount = 2;
            break;
         }
      }
   }
   else
   {
      weekOpen = startofpivot;
      weekClose = endofpivot;
   }

   switch(swaptf)
   {
      case 1: chose_tf = PERIOD_MN1; break;
      case 2: chose_tf = PERIOD_W1;  break;
      case 3: chose_tf = PERIOD_D1;  break;
   }

   if(brokercandle)
   {
      if(!GetOHLC(_Symbol, chose_tf, 1, wopen, whigh, wlow, wclose))
         return(0);
   }
   else
   {
      ObjectDelete(0, PREFIX + "Start");
      ObjectDelete(0, PREFIX + "End");

      int startBar = GetBarShiftByTime(_Symbol, PERIOD_H1, weekOpen);
      int endBar   = GetBarShiftByTime(_Symbol, PERIOD_H1, weekClose);
      if(startBar < 0 || endBar < 0 || startBar <= endBar)
      {
         Alert("Error – invalid start/end times or not enough data.");
         return(0);
      }

      if(!GetOHLC(_Symbol, PERIOD_H1, startBar, wopen, whigh, wlow, wclose))
         return(0);

      double tempClose;
      if(!GetOHLC(_Symbol, PERIOD_H1, endBar, wopen, whigh, wlow, tempClose))
         return(0);
      wclose = tempClose;

      double highArray[], lowArray[];
      int numBars = startBar - endBar + 1;
      if(CopyHigh(_Symbol, PERIOD_H1, endBar, numBars, highArray) < numBars) return(0);
      if(CopyLow(_Symbol, PERIOD_H1, endBar, numBars, lowArray) < numBars) return(0);
      whigh = highArray[ArrayMaximum(highArray)];
      wlow  = lowArray[ArrayMinimum(lowArray)];

      if(StartEndLines)
      {
         if(ObjectCreate(0, PREFIX + "Start", OBJ_VLINE, 0, weekOpen, 0))
         {
            ObjectSetInteger(0, PREFIX + "Start", OBJPROP_COLOR, (long)clrLimeGreen);
            ObjectSetInteger(0, PREFIX + "Start", OBJPROP_WIDTH, 0);
            ObjectSetInteger(0, PREFIX + "Start", OBJPROP_STYLE, (long)STYLE_DASH);
         }
         if(ObjectCreate(0, PREFIX + "End", OBJ_VLINE, 0, weekClose, 0))
         {
            ObjectSetInteger(0, PREFIX + "End", OBJPROP_COLOR, (long)clrTomato);
            ObjectSetInteger(0, PREFIX + "End", OBJPROP_WIDTH, 0);
            ObjectSetInteger(0, PREFIX + "End", OBJPROP_STYLE, (long)STYLE_DASH);
         }
      }
   }

   switch(pivot_meth)
   {
      case 1: calPivot = (whigh + wlow + wclose) / 3; break;
      case 2: calPivot = (whigh + wlow + wclose + wclose) / 4; break;
      case 3: calPivot = (whigh + wlow + wclose + wopen) / 4; break;
      case 4: calPivot = (whigh + wlow + wopen + wopen) / 4; break;
      case 5: calPivot = (whigh + wlow + wopen) / 3; break;
   }
   calRange = whigh - wlow;

   if(pivot_fib)
   {
      R38  = calPivot + calRange * 0.382;
      R61  = calPivot + calRange * 0.618;
      R78  = calPivot + calRange * 0.786;
      R100 = calPivot + calRange * 1.000;
      R138 = calPivot + calRange * 1.382;
      R161 = calPivot + calRange * 1.618;
      R200 = calPivot + calRange * 2.000;

      S38  = calPivot - calRange * 0.382;
      S61  = calPivot - calRange * 0.618;
      S78  = calPivot - calRange * 0.786;
      S100 = calPivot - calRange * 1.000;
      S138 = calPivot - calRange * 1.382;
      S161 = calPivot - calRange * 1.618;
      S200 = calPivot - calRange * 2.000;

      labelR38  = "R38 ";
      labelR61  = "R61 ";
      labelR78  = "R78 ";
      labelR100 = "R100 ";
      labelS38  = "S38 ";
      labelS61  = "S61 ";
      labelS78  = "S78 ";
      labelS100 = "S100 ";
   }
   else
   {
      R1 = 2 * calPivot - wlow;
      R2 = calPivot + (whigh - wlow);
      R3 = R2 + (whigh - wlow);
      S1 = 2 * calPivot - whigh;
      S2 = calPivot - (whigh - wlow);
      S3 = S2 - (whigh - wlow);

      labelR38  = "R1";
      labelR61  = "R2";
      labelR100 = "R3";
      labelS38  = "S1";
      labelS61  = "S2";
      labelS100 = "S3";

      R38  = R1;
      R61  = R2;
      R100 = R3;
      S38  = S1;
      S61  = S2;
      S100 = S3;
      // No assignment to show_200 – it remains as user input
   }

   int periodSec = PeriodSeconds((ENUM_TIMEFRAMES)_Period);
   datetime currentTime = time[rates_total - 1];
   datetime startTime = (rates_total > LL) ? time[rates_total - 1 - LL] : currentTime;

   DrawLevel(PREFIX + "WP_line", calPivot, chose_color_pivot, label_color_pivot,
             width_of_pivot_line, line_style_of_pivot, "Pivot",
             startTime, currentTime, periodSec, ShortHorizontalLines);

   Level levels[] = {
      {PREFIX + "WP_R38",  R38,  chose_color_R38,  label_color_R38,  labelR38},
      {PREFIX + "WP_S38",  S38,  chose_color_S38,  label_color_S38,  labelS38},
      {PREFIX + "WP_R61",  R61,  chose_color_R61,  label_color_R61,  labelR61},
      {PREFIX + "WP_S61",  S61,  chose_color_S61,  label_color_S61,  labelS61},
      {PREFIX + "WP_R78",  R78,  chose_color_R78,  label_color_R78,  labelR78},
      {PREFIX + "WP_S78",  S78,  chose_color_S78,  label_color_S78,  labelS78},
      {PREFIX + "WP_R100", R100, chose_color_R100, label_color_R100, labelR100},
      {PREFIX + "WP_S100", S100, chose_color_S100, label_color_S100, labelS100}
   };

   for(int i = 0; i < ArraySize(levels); i++)
   {
      bool isR = StringFind(levels[i].name, "R") >= 0;
      int width = isR ? width_of_R_line : width_of_S_line;
      int style = isR ? line_style_of_R : line_style_of_S;
      DrawLevel(levels[i].name, levels[i].price, levels[i].lineColor, levels[i].labelColor,
                width, style, levels[i].label,
                startTime, currentTime, periodSec, ShortHorizontalLines);
   }

   // Draw extra levels only if pivot_fib is true AND show_200 is true
   if(pivot_fib && show_200)
   {
      Level extra[] = {
         {PREFIX + "WP_R138", R138, chose_color_R138, label_color_R138, "R138 "},
         {PREFIX + "WP_S138", S138, chose_color_S138, label_color_S138, "S138 "},
         {PREFIX + "WP_R161", R161, chose_color_R161, label_color_R161, "R161 "},
         {PREFIX + "WP_S161", S161, chose_color_S161, label_color_S161, "S161 "},
         {PREFIX + "WP_R200", R200, chose_color_R200, label_color_R200, "R200 "},
         {PREFIX + "WP_S200", S200, chose_color_S200, label_color_S200, "S200 "}
      };

      for(int i = 0; i < ArraySize(extra); i++)
      {
         bool isR = StringFind(extra[i].name, "R") >= 0;
         int width = isR ? width_of_R_line : width_of_S_line;
         int style = isR ? line_style_of_R : line_style_of_S;
         DrawLevel(extra[i].name, extra[i].price, extra[i].lineColor, extra[i].labelColor,
                   width, style, extra[i].label,
                   startTime, currentTime, periodSec, ShortHorizontalLines);
      }
   }

   ChartRedraw(0);
   return(rates_total);
}
//+------------------------------------------------------------------+