//+------------------------------------------------------------------+
//|                                                   GannSwingZigZag |
//+------------------------------------------------------------------+
#property copyright "Your Name"
#property link      "Your Website"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots   6

// Buffers
double HLBuffer[]; // Higher Low
double HHBuffer[]; // Higher High
double LHBuffer[]; // Lower High
double LLBuffer[]; // Lower Low
double DTBuffer[]; // Double Top
double DBBuffer[]; // Double Bottom

// Input Parameters
input int ZigZagDepth = 12;          // ZigZag Depth
input int ZigZagDeviation = 5;       // ZigZag Deviation
input int ZigZagBackstep = 3;        // ZigZag Backstep
input double DoubleTopBottomTolerance = 0.0005; // Tolerance for Double Tops/Bottoms

//+------------------------------------------------------------------+
//| Initialization                                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Set buffers
   SetIndexBuffer(0, HLBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, HHBuffer, INDICATOR_DATA);
   SetIndexBuffer(2, LHBuffer, INDICATOR_DATA);
   SetIndexBuffer(3, LLBuffer, INDICATOR_DATA);
   SetIndexBuffer(4, DTBuffer, INDICATOR_DATA);
   SetIndexBuffer(5, DBBuffer, INDICATOR_DATA);

   // Initialize buffers to empty values
   ArrayInitialize(HLBuffer, EMPTY_VALUE);
   ArrayInitialize(HHBuffer, EMPTY_VALUE);
   ArrayInitialize(LHBuffer, EMPTY_VALUE);
   ArrayInitialize(LLBuffer, EMPTY_VALUE);
   ArrayInitialize(DTBuffer, EMPTY_VALUE);
   ArrayInitialize(DBBuffer, EMPTY_VALUE);

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Calculation                                                      |
//+------------------------------------------------------------------+
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[])
  {
   // Check minimum bars required
   if(rates_total < ZigZagDepth) return(0);

   // Get ZigZag values
   double ZigZagBuffer[];
   ArraySetAsSeries(ZigZagBuffer, true);

   int ZigZagHandle = iCustom(NULL, 0, "ZigZag", ZigZagDepth, ZigZagDeviation, ZigZagBackstep);
   if(ZigZagHandle == INVALID_HANDLE) return(0);

   // Copy ZigZag data
   if(CopyBuffer(ZigZagHandle, 0, 0, rates_total, ZigZagBuffer) <= 0) return(0);

   // Process ZigZag swing points
   for(int i = prev_calculated; i < rates_total; i++)
     {
      if(ZigZagBuffer[i] == 0) continue; // Skip non-swing points

      // Detect Higher High, Higher Low, Lower High, Lower Low
      if(i > 1)
        {
         if(ZigZagBuffer[i] > ZigZagBuffer[i - 1]) // Swing high
           {
            if(ZigZagBuffer[i - 1] > ZigZagBuffer[i - 2]) // Higher High
               HHBuffer[i] = ZigZagBuffer[i];
            else // Lower High
               LHBuffer[i] = ZigZagBuffer[i];
           }
         else if(ZigZagBuffer[i] < ZigZagBuffer[i - 1]) // Swing low
           {
            if(ZigZagBuffer[i - 1] < ZigZagBuffer[i - 2]) // Lower Low
               LLBuffer[i] = ZigZagBuffer[i];
            else // Higher Low
               HLBuffer[i] = ZigZagBuffer[i];
           }
        }

      // Detect Double Tops and Double Bottoms
      if(i > 2 && ZigZagBuffer[i] != 0 && ZigZagBuffer[i - 2] != 0)
        {
         if(MathAbs(ZigZagBuffer[i] - ZigZagBuffer[i - 2]) <= ZigZagBuffer[i] * DoubleTopBottomTolerance)
           {
            if(ZigZagBuffer[i] > ZigZagBuffer[i - 1]) // Double Top
               DTBuffer[i] = ZigZagBuffer[i];
            else // Double Bottom
               DBBuffer[i] = ZigZagBuffer[i];
           }
        }
     }

   return(rates_total);
  }
//+------------------------------------------------------------------+
