//+------------------------------------------------------------------+
//| ADXVMA Smooth on Chart Generic Trend                              |
//| © Adapted by Grok, 2025                                          |
//| Based on mladen's Jurik version                                  |
//+------------------------------------------------------------------+
#property copyright   "© Adapted by Grok, 2025"
#property link        "Based on mladen's Jurik version"
#property description "Triple ADXVMA on chart generic trend"
#property indicator_chart_window
#property indicator_buffers 12

//--- indicator styles
#property indicator_label1  "Smooth high up"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDeepPink
#property indicator_style1  STYLE_DOT
#property indicator_label2  "Smooth high down"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrGreen
#property indicator_style2  STYLE_DOT
#property indicator_label3  "Smooth high default"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrDarkGray
#property indicator_style3  STYLE_DOT
#property indicator_label4  "Smooth close up"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrDeepPink
#property indicator_style4  STYLE_DOT
#property indicator_label5  "Smooth close down"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrGreen
#property indicator_style5  STYLE_DOT
#property indicator_label6  "Smooth close default"
#property indicator_type6   DRAW_LINE
#property indicator_color6  clrDarkGray
#property indicator_style6  STYLE_DOT
#property indicator_label7  "Smooth low up"
#property indicator_type7   DRAW_LINE
#property indicator_color7  clrDeepPink
#property indicator_style7  STYLE_DOT
#property indicator_label8  "Smooth low down"
#property indicator_type8   DRAW_LINE
#property indicator_color8  clrGreen
#property indicator_style8  STYLE_DOT
#property indicator_label9  "Smooth low default"
#property indicator_type9   DRAW_LINE
#property indicator_color9  clrDarkGray
#property indicator_style9  STYLE_DOT
#property indicator_label10 "Smooth generic up"
#property indicator_type10  DRAW_LINE
#property indicator_color10 clrDeepPink
#property indicator_style10 STYLE_SOLID
#property indicator_width10 2
#property indicator_label11 "Smooth generic down"
#property indicator_type11  DRAW_LINE
#property indicator_color11 clrGreen
#property indicator_style11 STYLE_SOLID
#property indicator_width11 2
#property indicator_label12 "Smooth generic default"
#property indicator_type12  DRAW_LINE
#property indicator_color12 clrDarkGray
#property indicator_style12 STYLE_SOLID
#property indicator_width12 2

//--- input parameters
input double inpADXVMA_Period = 5; // ADXVMA period

//--- indicator buffers
double valu_up[], valu_down[], valu_def[];
double valc_up[], valc_down[], valc_def[];
double vald_up[], vald_down[], vald_def[];
double valg_up[], valg_down[], valg_def[];

//--- global variables for ADXVMA
double adxvmaWork[][28]; // 4 instances × 7 columns
#define _adxvmaWprc 0
#define _adxvmaWpdm 1
#define _adxvmaWmdm 2
#define _adxvmaWpdi 3
#define _adxvmaWmdi 4
#define _adxvmaWout 5
#define _adxvmaWval 6

//+------------------------------------------------------------------+
//| Custom indicator initialization function                          |
//+------------------------------------------------------------------+
int init()
{
   //--- indicator buffers mapping
   SetIndexBuffer(0, valu_up);   SetIndexStyle(0, DRAW_LINE, STYLE_DOT, 1, clrDeepPink);
   SetIndexBuffer(1, valu_down); SetIndexStyle(1, DRAW_LINE, STYLE_DOT, 1, clrGreen);
   SetIndexBuffer(2, valu_def);  SetIndexStyle(2, DRAW_LINE, STYLE_DOT, 1, clrDarkGray);
   SetIndexBuffer(3, valc_up);   SetIndexStyle(3, DRAW_LINE, STYLE_DOT, 1, clrDeepPink);
   SetIndexBuffer(4, valc_down); SetIndexStyle(4, DRAW_LINE, STYLE_DOT, 1, clrGreen);
   SetIndexBuffer(5, valc_def);  SetIndexStyle(5, DRAW_LINE, STYLE_DOT, 1, clrDarkGray);
   SetIndexBuffer(6, vald_up);   SetIndexStyle(6, DRAW_LINE, STYLE_DOT, 1, clrDeepPink);
   SetIndexBuffer(7, vald_down); SetIndexStyle(7, DRAW_LINE, STYLE_DOT, 1, clrGreen);
   SetIndexBuffer(8, vald_def);  SetIndexStyle(8, DRAW_LINE, STYLE_DOT, 1, clrDarkGray);
   SetIndexBuffer(9, valg_up);   SetIndexStyle(9, DRAW_LINE, STYLE_SOLID, 2, clrDeepPink);
   SetIndexBuffer(10, valg_down); SetIndexStyle(10, DRAW_LINE, STYLE_SOLID, 2, clrGreen);
   SetIndexBuffer(11, valg_def);  SetIndexStyle(11, DRAW_LINE, STYLE_SOLID, 2, clrDarkGray);

   //--- indicator short name
   IndicatorShortName("Triple ADXVMA OCGT (" + DoubleToStr(inpADXVMA_Period, 1) + ")");
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator de-initialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                               |
//+------------------------------------------------------------------+
int start()
{
   int rates_total = Bars;
   int prev_calculated = IndicatorCounted();
   int i = prev_calculated > 0 ? prev_calculated - 1 : 0;

   for(; i < rates_total; i++)
   {
      //--- calculate ADXVMA values
      double high_val = iAdxvma(High[i], inpADXVMA_Period, rates_total, i, 0);
      double close_val = iAdxvma(Close[i], inpADXVMA_Period, rates_total, i, 1);
      double low_val = iAdxvma(Low[i], inpADXVMA_Period, rates_total, i, 2);
      double generic_val = iAdxvma((High[i] + Low[i] + Close[i]) / 3.0, inpADXVMA_Period, rates_total, i, 3);

      //--- validate ADXVMA values
      if (high_val == 0 || close_val == 0 || low_val == 0 || generic_val == 0)
         continue; // Skip invalid values to prevent rendering issues

      //--- initialize buffers
      valu_up[i] = valu_down[i] = valu_def[i] = EMPTY_VALUE;
      valc_up[i] = valc_down[i] = valc_def[i] = EMPTY_VALUE;
      vald_up[i] = vald_down[i] = vald_def[i] = EMPTY_VALUE;
      valg_up[i] = valg_down[i] = valg_def[i] = EMPTY_VALUE;

      //--- determine trend direction for high
      double high_color = (i > 0) ? (high_val > iAdxvma(High[i-1], inpADXVMA_Period, rates_total, i-1, 0)) ? 1 :
                                    (high_val < iAdxvma(High[i-1], inpADXVMA_Period, rates_total, i-1, 0)) ? 2 : 0 : 0;
      //--- determine trend direction for close
      double close_color = (i > 0) ? (close_val > iAdxvma(Close[i-1], inpADXVMA_Period, rates_total, i-1, 1)) ? 1 :
                                     (close_val < iAdxvma(Close[i-1], inpADXVMA_Period, rates_total, i-1, 1)) ? 2 : 0 : 0;
      //--- determine trend direction for low
      double low_color = (i > 0) ? (low_val > iAdxvma(Low[i-1], inpADXVMA_Period, rates_total, i-1, 2)) ? 1 :
                                   (low_val < iAdxvma(Low[i-1], inpADXVMA_Period, rates_total, i-1, 2)) ? 2 : 0 : 0;
      //--- determine trend direction for generic
      double generic_color = (high_color == 1 && close_color == 1 && low_color == 1) ? 1 :
                             (high_color == 2 && close_color == 2 && low_color == 2) ? 2 : 0;

      //--- assign values to buffers based on trend
      if (high_color == 1) valu_up[i] = high_val;
      else if (high_color == 2) valu_down[i] = high_val;
      else valu_def[i] = high_val;

      if (close_color == 1) valc_up[i] = close_val;
      else if (close_color == 2) valc_down[i] = close_val;
      else valc_def[i] = close_val;

      if (low_color == 1) vald_up[i] = low_val;
      else if (low_color == 2) vald_down[i] = low_val;
      else vald_def[i] = low_val;

      //--- ensure generic trend line is continuous
      if (generic_color == 1) valg_up[i] = generic_val;
      else if (generic_color == 2) valg_down[i] = generic_val;
      else valg_def[i] = generic_val; // Default to gray if no clear trend
   }
   return(0);
}

//+------------------------------------------------------------------+
//| Custom functions                                                 |
//+------------------------------------------------------------------+
// ADXVMA calculation function
double iAdxvma(double price, double period, int bars, int r, int instanceNo)
{
   if (ArrayRange(adxvmaWork, 0) != bars)
      ArrayResize(adxvmaWork, bars);
   instanceNo *= 7;

   adxvmaWork[r][instanceNo + _adxvmaWprc] = price;
   if (r < 1)
   {
      adxvmaWork[r][instanceNo + _adxvmaWval] = price;
      return(adxvmaWork[r][instanceNo + _adxvmaWval]);
   }

   double tpdm = 0;
   double tmdm = 0;
   double diff = adxvmaWork[r][instanceNo + _adxvmaWprc] - adxvmaWork[r - 1][instanceNo + _adxvmaWprc];
   if (diff > 0)
      tpdm = diff;
   else
      tmdm = -diff;

   adxvmaWork[r][instanceNo + _adxvmaWpdm] = ((period - 1.0) * adxvmaWork[r - 1][instanceNo + _adxvmaWpdm] + tpdm) / period;
   adxvmaWork[r][instanceNo + _adxvmaWmdm] = ((period - 1.0) * adxvmaWork[r - 1][instanceNo + _adxvmaWmdm] + tmdm) / period;

   double trueRange = adxvmaWork[r][instanceNo + _adxvmaWpdm] + adxvmaWork[r][instanceNo + _adxvmaWmdm];
   double tpdi = 0;
   double tmdi = 0;
   if (trueRange > 0)
   {
      tpdi = adxvmaWork[r][instanceNo + _adxvmaWpdm] / trueRange;
      tmdi = adxvmaWork[r][instanceNo + _adxvmaWmdm] / trueRange;
   }
   adxvmaWork[r][instanceNo + _adxvmaWpdi] = ((period - 1.0) * adxvmaWork[r - 1][instanceNo + _adxvmaWpdi] + tpdi) / period;
   adxvmaWork[r][instanceNo + _adxvmaWmdi] = ((period - 1.0) * adxvmaWork[r - 1][instanceNo + _adxvmaWmdi] + tmdi) / period;

   double tout = 0;
   if ((adxvmaWork[r][instanceNo + _adxvmaWpdi] + adxvmaWork[r][instanceNo + _adxvmaWmdi]) > 0)
      tout = MathAbs(adxvmaWork[r][instanceNo + _adxvmaWpdi] - adxvmaWork[r][instanceNo + _adxvmaWmdi]) /
             (adxvmaWork[r][instanceNo + _adxvmaWpdi] + adxvmaWork[r][instanceNo + _adxvmaWmdi]);
   adxvmaWork[r][instanceNo + _adxvmaWout] = ((period - 1.0) * adxvmaWork[r - 1][instanceNo + _adxvmaWout] + tout) / period;

   double thi = MathMax(adxvmaWork[r][instanceNo + _adxvmaWout], adxvmaWork[r - 1][instanceNo + _adxvmaWout]);
   double tlo = MathMin(adxvmaWork[r][instanceNo + _adxvmaWout], adxvmaWork[r - 1][instanceNo + _adxvmaWout]);
   for (int j = 2; j < period && r - j >= 0; j++)
   {
      thi = MathMax(adxvmaWork[r - j][instanceNo + _adxvmaWout], thi);
      tlo = MathMin(adxvmaWork[r - j][instanceNo + _adxvmaWout], tlo);
   }
   double vi = 0;
   if ((thi - tlo) > 0)
      vi = (adxvmaWork[r][instanceNo + _adxvmaWout] - tlo) / (thi - tlo);

   adxvmaWork[r][instanceNo + _adxvmaWval] = ((period - vi) * adxvmaWork[r - 1][instanceNo + _adxvmaWval] +
                                              vi * adxvmaWork[r][instanceNo + _adxvmaWprc]) / period;
   return(adxvmaWork[r][instanceNo + _adxvmaWval]);
}
//+------------------------------------------------------------------+