//+------------------------------------------------------------------+
//|                                               Fractals_DD_DB.mq4 |
//|                                          Copyright 2022 mql5.com |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022 mql5.com"
#property link      "https://www.mql5.com"
#property version   "2.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 2

//+------------------------------------------------------------------+
string Indi_ID = "Fractals_DD_DB";
double   dw[], up[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexStyle(0,DRAW_ARROW,0,3,clrBlue);
   SetIndexBuffer(0,dw);
   SetIndexArrow(0,233);
   SetIndexStyle(1,DRAW_ARROW,0,3,clrRed);
   SetIndexBuffer(1,up);
   SetIndexArrow(1,234);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration 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[])
  {
//---
    int limit = 0;

    // Handling first calculation or recalculation
    if (prev_calculated == 0) 
    {
        limit = rates_total - 1;  // Process all bars for the first time
    } 
    else 
    {
        limit = rates_total - prev_calculated;  // Process only new bars
    }

   for(int i=limit; i>=0; i--)
     {
      dw[i] = iFractals(NULL,0,MODE_LOWER,i);
      up[i] = iFractals(NULL,0,MODE_UPPER,i);
     }    

    // Arrays to store the last 3 fractals
    int lowFractals[3] = {-1, -1, -1}; // Store the index of the last 3 lows
    int highFractals[3] = {-1, -1, -1}; // Store the index of the last 3 highs

    if(IsNewBar(_Period))
    {
        // Loop through bars to find fractal lows and plot sections
        for(int i = limit - 1; i >= 0; i--)
        {
            double lowFractal = iFractals(NULL, 0, MODE_LOWER, i);

            if(lowFractal != 0.0)
            {
                // Shift the fractal indices to track the last 3 fractals
                lowFractals[2] = lowFractals[1];
                lowFractals[1] = lowFractals[0];
                lowFractals[0] = i;

                // Now we have 3 fractals, check if the middle is lower
                if(lowFractals[2] != -1 && lowFractals[1] != -1 && lowFractals[0] != -1)
                {
                    double low1 = iFractals(NULL, 0, MODE_LOWER, lowFractals[2]);
                    double low2 = iFractals(NULL, 0, MODE_LOWER, lowFractals[1]);
                    double low3 = iFractals(NULL, 0, MODE_LOWER, lowFractals[0]);

                    if(low2 < low1 && low2 < low3)  // Higher low - low - higher low
                    {
                        // Draw section between the first and last fractal
                        string lineName = Indi_ID+"_LowSection_" + IntegerToString(i);
                        if(ObjectFind(ChartID(), lineName) < 0)
                        { 
                            if (!ObjectCreate(lineName, OBJ_TREND, 0, time[lowFractals[1]], low2, time[lowFractals[0]], low3))
                            {
                                Print("Error creating object: ", lineName);
                            }
                            else
                            {
                                // Set line properties
                                ObjectSetInteger(0, lineName, OBJPROP_RAY_RIGHT, false);
                                ObjectSetInteger(0, lineName, OBJPROP_COLOR, clrBlue);
                                ObjectSetInteger(0, lineName, OBJPROP_WIDTH, 2);
                                ObjectSetInteger(0, lineName, OBJPROP_STYLE, STYLE_SOLID);
                            }
                        }
                    }
                }
            }
        }

        // Loop through bars to find fractal highs and plot sections
        for(int i = limit - 1; i >= 0; i--)
        {
            double highFractal = iFractals(NULL, 0, MODE_UPPER, i);

            if(highFractal != 0.0)
            {
                // Shift the fractal indices to track the last 3 fractals
                highFractals[2] = highFractals[1];
                highFractals[1] = highFractals[0];
                highFractals[0] = i;

                // Now we have 3 fractals, check if the middle is higher
                if(highFractals[2] != -1 && highFractals[1] != -1 && highFractals[0] != -1)
                {
                    double high1 = iFractals(NULL, 0, MODE_UPPER, highFractals[2]);
                    double high2 = iFractals(NULL, 0, MODE_UPPER, highFractals[1]);
                    double high3 = iFractals(NULL, 0, MODE_UPPER, highFractals[0]);

                    if(high2 > high1 && high2 > high3)  // Lower high - high - lower high
                    {
                        // Draw section between the first and last fractal
                        string lineName = Indi_ID+"_HighSection_" + IntegerToString(i);
                        if(ObjectFind(ChartID(), lineName) < 0)
                        {
                            if (!ObjectCreate(lineName, OBJ_TREND, 0, time[highFractals[1]], high2, time[highFractals[0]], high3))
                            {
                                Print("Error creating object: ", lineName);
                            }
                            else
                            {
                                // Set line properties
                                ObjectSetInteger(0, lineName, OBJPROP_RAY_RIGHT, false);
                                ObjectSetInteger(0, lineName, OBJPROP_COLOR, clrRed);
                                ObjectSetInteger(0, lineName, OBJPROP_WIDTH, 2);
                                ObjectSetInteger(0, lineName, OBJPROP_STYLE, STYLE_SOLID);
                            }
                        }
                    }
                }
            }
        }
    }

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//----
   objectsDelete(Indi_ID);
//----
  }
//+------------------------------------------------------------------+
void objectsDelete(string name)
{
   int objTotal = ObjectsTotal();
   for(int i=objTotal-1; i>=0; i--)  
  {
      string objName = ObjectName(i);
      if(StringFind(objName, name, 0) >= 0)
       ObjectDelete(0, objName);
   }
}
//+------------------------------------------------------------------+
bool IsNewBar(int per)
{ 
  static datetime Trend_Candle_prevTime1 = -1;
  
  if(Trend_Candle_prevTime1 != iTime(_Symbol, per, 6))
  { 
   Trend_Candle_prevTime1 = iTime(_Symbol, per, 6); 
       
   return(true);  
  } 

  return(false); 
}
//+------------------------------------------------------------------+
