//+------------------------------------------------------------------+
//|                                     KagiChartReversal_EDIT_AI.mq4 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property strict
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 clrDodgerBlue    // Up trend
#property indicator_color2 clrRed     // Down trend
#property indicator_color3 clrDodgerBlue    // Up Arrow
#property indicator_color4 clrRed     // Down Arrow
#property indicator_width1 5
#property indicator_width2 5
#property indicator_width3 5
#property indicator_width4 5

// Input parameters
input double ReversalAmount = 2900;     // Reversal amount in points
input bool UsePercentage = false;      // Use percentage for reversal
input int LineThickness = 2;           // Line thickness
input int ArrowSize = 5;               // Arrow size
input int ArrowDistance = 20;          // Distance of arrows from price

// Indicator buffers
double UpBuffer[];
double DownBuffer[];
double UpArrowBuffer[];
double DownArrowBuffer[];

// Global variables
double lastPrice;
int lastDirection;
double lastExtreme;
int initialBars;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                           |
//+------------------------------------------------------------------+
int OnInit()
{
   IndicatorShortName("Kagi with Arrows");
   
   // Initialize buffers
   SetIndexBuffer(0, UpBuffer);
   SetIndexBuffer(1, DownBuffer);
   SetIndexBuffer(2, UpArrowBuffer);
   SetIndexBuffer(3, DownArrowBuffer);
   
   // Set drawing styles
   SetIndexStyle(0, DRAW_LINE);
   SetIndexStyle(1, DRAW_LINE);
   SetIndexStyle(2, DRAW_ARROW);
   SetIndexStyle(3, DRAW_ARROW);
   
   // Set arrow codes
   SetIndexArrow(2, 233);  // Up arrow
   SetIndexArrow(3, 234);  // Down arrow
   
   // Set empty value
   SetIndexEmptyValue(0, 0.0);
   SetIndexEmptyValue(1, 0.0);
   SetIndexEmptyValue(2, 0.0);
   SetIndexEmptyValue(3, 0.0);
   
   // Set line labels
   SetIndexLabel(0, "Kagi Up");
   SetIndexLabel(1, "Kagi Down");
   SetIndexLabel(2, "Up Arrow");
   SetIndexLabel(3, "Down Arrow");
   
   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[])
{
   // Initialize on first call
   if(prev_calculated == 0)
   {
      ArrayInitialize(UpBuffer, 0.0);
      ArrayInitialize(DownBuffer, 0.0);
      ArrayInitialize(UpArrowBuffer, 0.0);
      ArrayInitialize(DownArrowBuffer, 0.0);
      lastPrice = close[rates_total-1];
      lastDirection = 0;
      lastExtreme = lastPrice;
      initialBars = rates_total;
   }
   
   double point = Point;
   if(_Digits == 3 || _Digits == 5) point *= 10;
   
   double reversalSize = UsePercentage ? ReversalAmount/100.0 : ReversalAmount * point;
   double arrowOffset = ArrowDistance * point;  // Distance for arrow placement
   
   // Main calculation loop
   int limit = prev_calculated == 0 ? rates_total-1 : rates_total-prev_calculated+1;
   
   for(int i = limit; i >= 0; i--)
   {
      double currentPrice = close[i];
      
      // Clear arrow buffers
      UpArrowBuffer[i] = 0.0;
      DownArrowBuffer[i] = 0.0;
      
      // Initialize direction on first bar
      if(lastDirection == 0)
      {
         lastDirection = 1;  // Start with up direction
         UpBuffer[i] = currentPrice;
         lastExtreme = currentPrice;
         continue;
      }
      
      // Calculate reversal threshold
      double threshold = UsePercentage ? lastExtreme * reversalSize : reversalSize;
      
      if(lastDirection == 1)  // Current trend is up
      {
         if(currentPrice > lastExtreme)
         {
            // New high - extend up line
            UpBuffer[i] = currentPrice;
            DownBuffer[i] = 0;
            lastExtreme = currentPrice;
         }
         else if(currentPrice < (lastExtreme - threshold))
         {
            // Reversal down
            lastDirection = -1;
            DownBuffer[i] = currentPrice;
            UpBuffer[i] = 0;
            DownArrowBuffer[i] = high[i] + arrowOffset;  // Place arrow above bar
            lastExtreme = currentPrice;
         }
         else
         {
            // Continue previous trend
            UpBuffer[i] = UpBuffer[i+1];
            DownBuffer[i] = 0;
         }
      }
      else  // Current trend is down
      {
         if(currentPrice < lastExtreme)
         {
            // New low - extend down line
            DownBuffer[i] = currentPrice;
            UpBuffer[i] = 0;
            lastExtreme = currentPrice;
         }
         else if(currentPrice > (lastExtreme + threshold))
         {
            // Reversal up
            lastDirection = 1;
            UpBuffer[i] = currentPrice;
            DownBuffer[i] = 0;
            UpArrowBuffer[i] = low[i] - arrowOffset;  // Place arrow below bar
            lastExtreme = currentPrice;
         }
         else
         {
            // Continue previous trend
            DownBuffer[i] = DownBuffer[i+1];
            UpBuffer[i] = 0;
         }
      }
      
      lastPrice = currentPrice;
   }
   
   return(rates_total);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                         |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   ObjectsDeleteAll(0, "Kagi_");
}