//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|                                      Colored moving averages.mq5 |
//+------------------------------------------------------------------+
#property copyright "Mladen"
#property link      "http://www.forex-tsd.com"
#property version   "1.00"

#property indicator_chart_window
#property indicator_buffers 22
#property indicator_plots   11

//
//
//
//
//

#property indicator_label1  "Moving average"
#property indicator_type1   DRAW_COLOR_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

#property indicator_label2  "Slow MA"
#property indicator_type2   DRAW_COLOR_LINE
#property indicator_color2  Blue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2

#property indicator_label3  "MA Candles"
#property indicator_type3   DRAW_COLOR_CANDLES
#property indicator_color3  Red
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1

// Plot 4: TF Alignment Up Arrow  (TF1 color == TF2 color, bullish state)
#property indicator_label4  "TF Align Up"
#property indicator_type4   DRAW_ARROW
#property indicator_color4  DodgerBlue
#property indicator_style4  STYLE_SOLID
#property indicator_width4  2

// Plot 5: TF Alignment Down Arrow (TF1 color == TF2 color, bearish state)
#property indicator_label5  "TF Align Down"
#property indicator_type5   DRAW_ARROW
#property indicator_color5  OrangeRed
#property indicator_style5  STYLE_SOLID
#property indicator_width5  2

// Plot 6: TREND MA Background line
#property indicator_label6  "TREND Bgd"
#property indicator_type6   DRAW_LINE
#property indicator_color6  C'100,130,160'
#property indicator_style6  STYLE_SOLID
#property indicator_width6  11

// Plot 7: TREND MA Up
#property indicator_label7  "TREND Up"
#property indicator_type7   DRAW_LINE
#property indicator_color7  clrBlue
#property indicator_style7  STYLE_SOLID
#property indicator_width7  7

// Plot 8: TREND MA Down
#property indicator_label8  "TREND Down"
#property indicator_type8   DRAW_LINE
#property indicator_color8  clrCrimson
#property indicator_style8  STYLE_SOLID
#property indicator_width8  7

// Plot 9: SIGNAL MA Background line
#property indicator_label9  "SIGNAL Bgd"
#property indicator_type9   DRAW_LINE
#property indicator_color9  C'100,130,160'
#property indicator_style9  STYLE_SOLID
#property indicator_width9  8

// Plot 10: SIGNAL MA Up
#property indicator_label10 "SIGNAL Up"
#property indicator_type10  DRAW_LINE
#property indicator_color10 clrBlue
#property indicator_style10 STYLE_SOLID
#property indicator_width10 4

// Plot 11: SIGNAL MA Down
#property indicator_label11 "SIGNAL Down"
#property indicator_type11  DRAW_LINE
#property indicator_color11 clrCrimson
#property indicator_style11 STYLE_SOLID
#property indicator_width11 4

//
//
//
//
//

input int                inpLength     = 14;           // Moving average period (length)
input int                inpSlowLength = 34;           // Slow moving average period
input ENUM_APPLIED_PRICE Price         = PRICE_CLOSE;  // Applied price
input ENUM_MA_METHOD     Method        = MODE_EMA;     // Moving average method
input ENUM_TIMEFRAMES    CandleColorTF = PERIOD_CURRENT; // Candle coloring timeframe
input color              ColorFrom     = Lime;         // "Fast up" color
input color              ColorTo       = DeepPink;     // "Fast down" color
input int                MaxAngle      = 20;           // Angle threshhold for color steps
input bool               ColorCandles  = true;         // Color price candles?
input color              CandleColorBearish   = clrRed;          // Below both MAs (Bearish)
input color              CandleColorBullish   = clrBlue;         // Above both MAs (Bullish)
input color              CandleColorLightBlue = clrLightBlue;    // Below fast, above slow MA
input color              CandleColorLightRed  = C'255,128,128';  // Above fast, below slow MA
input bool               ColorBackground      = false;           // Color chart background?
input color              BgColorBearish       = C'45,20,20';     // Bearish background color
input color              BgColorBullish       = C'20,20,45';     // Bullish background color
input color              BgColorLightBlue     = C'20,35,45';     // Light Blue background color
input color              BgColorLightRed      = C'45,35,20';     // Light Red background color
input int                BgMaxBars            = 500;             // Max bars for background coloring

// --- TF Alignment Arrow inputs ---
enum ENUM_CANDLE_COLOR_MODE
{
   CANDLE_COLOR_MA    = 0,  // By Moving Averages (4 Colors)
   CANDLE_COLOR_ARROW = 1,  // By Arrow Direction
   CANDLE_COLOR_XUMT  = 2   // By XU-MA TREND+SIGNAL Direction
};

input ENUM_CANDLE_COLOR_MODE CandleColorMode = CANDLE_COLOR_MA; // Candle coloring mode
input ENUM_TIMEFRAMES    TF1          = PERIOD_M15;       // First comparison timeframe for arrows
input ENUM_TIMEFRAMES    TF2          = PERIOD_M30;       // Second comparison timeframe for arrows
input bool               ShowArrows   = true;             // Show TF alignment arrows?
input color              ArrowUpColor = clrDodgerBlue;    // Up arrow color (bullish match)
input color              ArrowDnColor = clrOrangeRed;     // Down arrow color (bearish match)
input int                ArrowSize    = 2;                // Arrow size (1-5)

// --- XU-MA TREND Settings ---
input string             STR_TREND  = "<<< XU-MA TREND Settings >>>";  // ─── TREND MA ───
input bool               showTREND  = true;              // Show TREND MA?
input int                TRENDper   = 36;                // TREND MA period
input ENUM_TIMEFRAMES    TRENDtf    = PERIOD_CURRENT;    // TREND MA timeframe (0=current chart)
input int                TRENDshft  = 0;                 // TREND MA shift
input ENUM_MA_METHOD     TRENDmode  = MODE_EMA;          // TREND MA method
input ENUM_APPLIED_PRICE TRENDtype  = PRICE_MEDIAN;      // TREND MA median price type
input color              TRENDupclr = clrBlue;           // TREND Up color
input color              TRENDdnclr = clrCrimson;        // TREND Down color
input color              Tbgdclr    = C'100,130,160';    // TREND Background line color
input int                TRENDwidth = 7;                 // TREND MA line width

// --- XU-MA SIGNAL Settings ---
input string             STR_SIGNAL  = "<<< XU-MA SIGNAL Settings >>>"; // ─── SIGNAL MA ───
input bool               showSIGNAL  = true;             // Show SIGNAL MA?
input int                SIGNALper   = 9;                // SIGNAL MA period
input ENUM_TIMEFRAMES    SIGNALtf    = PERIOD_CURRENT;   // SIGNAL MA timeframe (0=current chart)
input int                SIGNALshft  = 0;                // SIGNAL MA shift
input ENUM_MA_METHOD     SIGNALmode  = MODE_EMA;         // SIGNAL MA method
input ENUM_APPLIED_PRICE SIGNALtype  = PRICE_MEDIAN;     // SIGNAL MA median price type
input color              SIGNALupclr = clrBlue;          // SIGNAL Up color
input color              SIGNALdnclr = clrCrimson;       // SIGNAL Down color
input color              Sbgdclr     = C'100,130,160';   // SIGNAL Background line color
input int                SIGNALwidth = 4;                // SIGNAL MA line width

//
//
//
//
//

double maBuffer[];
double maColors[];
double maSlowBuffer[];
double maSlowColors[];
double candleOpen[];
double candleHigh[];
double candleLow[];
double candleClose[];
double candleColors[];
double atrBuffer[];
double arrowUpBuf[];
double arrowDnBuf[];
double arrowStateBuf[];

// XU-MA Buffers
double TbgdBuf[];
double TRENDupBuf[];
double TRENDdnBuf[];
double trendCalcBuf[];
double SbgdBuf[];
double SIGNALupBuf[];
double SIGNALdnBuf[];
double signalCalcBuf[];
double xtrendCalcBuf[];

int maHandle;
int maSlowHandle;
int atrHandle;
int candleMaHandle;
int candleMaSlowHandle;
int candleAtrHandle;
int tf1MaHandle;
int tf1MaSlowHandle;
int tf2MaHandle;
int tf2MaSlowHandle;

// XU-MA Handles
int trendMaHighHandle;
int trendMaLowHandle;
int trendMaMedHandle;
int signalMaHighHandle;
int signalMaLowHandle;
int signalMaMedHandle;

//
//
//
//
//

#define angleBars   6
#define atrBars   100

//+------------------------------------------------------------------+
//| Clean up background rectangle objects                            |
//+------------------------------------------------------------------+
void DeleteBackgroundObjects()
{
   int total = ObjectsTotal(0, 0, OBJ_RECTANGLE);
   for(int i = total - 1; i >= 0; i--)
   {
      string name = ObjectName(0, i, 0, OBJ_RECTANGLE);
      if(StringFind(name, "MA_Bg_Rec_") == 0)
      {
         ObjectDelete(0, name);
      }
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//
//

int OnInit()
{
   DeleteBackgroundObjects();

   // --- Existing Buffers ---
   SetIndexBuffer(0, maBuffer,    INDICATOR_DATA);           ArraySetAsSeries(maBuffer,    true);
   SetIndexBuffer(1, maColors,    INDICATOR_COLOR_INDEX);    ArraySetAsSeries(maColors,    true);
   SetIndexBuffer(2, maSlowBuffer,INDICATOR_DATA);           ArraySetAsSeries(maSlowBuffer,true);
   SetIndexBuffer(3, maSlowColors,INDICATOR_COLOR_INDEX);    ArraySetAsSeries(maSlowColors,true);
   SetIndexBuffer(4, candleOpen,  INDICATOR_DATA);           ArraySetAsSeries(candleOpen,  true);
   SetIndexBuffer(5, candleHigh,  INDICATOR_DATA);           ArraySetAsSeries(candleHigh,  true);
   SetIndexBuffer(6, candleLow,   INDICATOR_DATA);           ArraySetAsSeries(candleLow,   true);
   SetIndexBuffer(7, candleClose, INDICATOR_DATA);           ArraySetAsSeries(candleClose, true);
   SetIndexBuffer(8, candleColors,INDICATOR_COLOR_INDEX);    ArraySetAsSeries(candleColors,true);
   SetIndexBuffer(9, arrowUpBuf,  INDICATOR_DATA);           ArraySetAsSeries(arrowUpBuf,  true);
   SetIndexBuffer(10,arrowDnBuf,  INDICATOR_DATA);           ArraySetAsSeries(arrowDnBuf,  true);
   SetIndexBuffer(11,atrBuffer,   INDICATOR_CALCULATIONS);   ArraySetAsSeries(atrBuffer,   true);
   SetIndexBuffer(12,arrowStateBuf,INDICATOR_CALCULATIONS);  ArraySetAsSeries(arrowStateBuf,true);

   // --- XU-MA Buffers (plots 5-10, buffers 13-21) ---
   SetIndexBuffer(13,TbgdBuf,      INDICATOR_DATA);          ArraySetAsSeries(TbgdBuf,      true);
   SetIndexBuffer(14,TRENDupBuf,   INDICATOR_DATA);          ArraySetAsSeries(TRENDupBuf,   true);
   SetIndexBuffer(15,TRENDdnBuf,   INDICATOR_DATA);          ArraySetAsSeries(TRENDdnBuf,   true);
   SetIndexBuffer(16,trendCalcBuf, INDICATOR_CALCULATIONS);  ArraySetAsSeries(trendCalcBuf, true);
   SetIndexBuffer(17,SbgdBuf,      INDICATOR_DATA);          ArraySetAsSeries(SbgdBuf,      true);
   SetIndexBuffer(18,SIGNALupBuf,  INDICATOR_DATA);          ArraySetAsSeries(SIGNALupBuf,  true);
   SetIndexBuffer(19,SIGNALdnBuf,  INDICATOR_DATA);          ArraySetAsSeries(SIGNALdnBuf,  true);
   SetIndexBuffer(20,signalCalcBuf,INDICATOR_CALCULATIONS);  ArraySetAsSeries(signalCalcBuf,true);
   SetIndexBuffer(21,xtrendCalcBuf,INDICATOR_CALCULATIONS);  ArraySetAsSeries(xtrendCalcBuf,true);

   //
   //
   //
   //
   //

   int iLength    = (inpLength    > 0) ? inpLength    : 1;
   int iSlowLen   = (inpSlowLength> 0) ? inpSlowLength: 1;
   int iTRENDper  = (TRENDper     > 0) ? TRENDper     : 1;
   int iSIGNALper = (SIGNALper    > 0) ? SIGNALper    : 1;

      maHandle           = iMA(NULL,0,iLength,0,Method,Price);
      maSlowHandle       = iMA(NULL,0,iSlowLen,0,Method,Price);
      atrHandle          = iATR(NULL,0,atrBars);
      candleMaHandle     = iMA(NULL,CandleColorTF,iLength,0,Method,Price);
      candleMaSlowHandle = iMA(NULL,CandleColorTF,iSlowLen,0,Method,Price);
      candleAtrHandle    = iATR(NULL,CandleColorTF,atrBars);
      tf1MaHandle        = iMA(NULL,TF1,iLength, 0,Method,Price);
      tf1MaSlowHandle    = iMA(NULL,TF1,iSlowLen,0,Method,Price);
      tf2MaHandle        = iMA(NULL,TF2,iLength, 0,Method,Price);
      tf2MaSlowHandle    = iMA(NULL,TF2,iSlowLen,0,Method,Price);

      // XU-MA handles: High/Low band + Median line for each MA
      trendMaHighHandle  = iMA(NULL,TRENDtf, iTRENDper, TRENDshft, TRENDmode, PRICE_HIGH);
      trendMaLowHandle   = iMA(NULL,TRENDtf, iTRENDper, TRENDshft, TRENDmode, PRICE_LOW);
      trendMaMedHandle   = iMA(NULL,TRENDtf, iTRENDper, TRENDshft, TRENDmode, TRENDtype);
      signalMaHighHandle = iMA(NULL,SIGNALtf,iSIGNALper,SIGNALshft,SIGNALmode,PRICE_HIGH);
      signalMaLowHandle  = iMA(NULL,SIGNALtf,iSIGNALper,SIGNALshft,SIGNALmode,PRICE_LOW);
      signalMaMedHandle  = iMA(NULL,SIGNALtf,iSIGNALper,SIGNALshft,SIGNALmode,SIGNALtype);

      if(maHandle == INVALID_HANDLE || maSlowHandle == INVALID_HANDLE || atrHandle == INVALID_HANDLE ||
         candleMaHandle == INVALID_HANDLE || candleMaSlowHandle == INVALID_HANDLE || candleAtrHandle == INVALID_HANDLE ||
         tf1MaHandle == INVALID_HANDLE || tf1MaSlowHandle == INVALID_HANDLE ||
         tf2MaHandle == INVALID_HANDLE || tf2MaSlowHandle == INVALID_HANDLE ||
         trendMaHighHandle  == INVALID_HANDLE || trendMaLowHandle  == INVALID_HANDLE || trendMaMedHandle  == INVALID_HANDLE ||
         signalMaHighHandle == INVALID_HANDLE || signalMaLowHandle == INVALID_HANDLE || signalMaMedHandle == INVALID_HANDLE)
      {
         Print("Error creating indicator handles");
         return(INIT_FAILED);
      }

      // --- Gradient color MA plots ---
      PlotIndexSetInteger(0,PLOT_COLOR_INDEXES,20);
      PlotIndexSetInteger(1,PLOT_COLOR_INDEXES,20);
      PlotIndexSetInteger(2,PLOT_COLOR_INDEXES,4);
      for(int i=0;i<20;i++)
      {
         color c = gradientColor(i,20,ColorTo,ColorFrom);
         PlotIndexSetInteger(0,PLOT_LINE_COLOR,i,c);
         PlotIndexSetInteger(1,PLOT_LINE_COLOR,i,c);
      }

      PlotIndexSetInteger(2,PLOT_LINE_COLOR,0,CandleColorBearish);
      PlotIndexSetInteger(2,PLOT_LINE_COLOR,1,CandleColorBullish);
      PlotIndexSetInteger(2,PLOT_LINE_COLOR,2,CandleColorLightBlue);
      PlotIndexSetInteger(2,PLOT_LINE_COLOR,3,CandleColorLightRed);

      if(!ColorCandles)
         PlotIndexSetInteger(2,PLOT_DRAW_TYPE,DRAW_NONE);
      else
         PlotIndexSetInteger(2,PLOT_DRAW_TYPE,DRAW_COLOR_CANDLES);

      // --- Arrow plots ---
      PlotIndexSetInteger(3,PLOT_ARROW,233);
      PlotIndexSetInteger(3,PLOT_LINE_COLOR,ArrowUpColor);
      PlotIndexSetInteger(3,PLOT_LINE_WIDTH,ArrowSize);
      PlotIndexSetDouble (3,PLOT_EMPTY_VALUE,EMPTY_VALUE);
      PlotIndexSetInteger(3,PLOT_DRAW_TYPE,ShowArrows ? DRAW_ARROW : DRAW_NONE);

      PlotIndexSetInteger(4,PLOT_ARROW,234);
      PlotIndexSetInteger(4,PLOT_LINE_COLOR,ArrowDnColor);
      PlotIndexSetInteger(4,PLOT_LINE_WIDTH,ArrowSize);
      PlotIndexSetDouble (4,PLOT_EMPTY_VALUE,EMPTY_VALUE);
      PlotIndexSetInteger(4,PLOT_DRAW_TYPE,ShowArrows ? DRAW_ARROW : DRAW_NONE);

      // --- XU-MA TREND plots (plot indices 5, 6, 7) ---
      PlotIndexSetDouble(5,PLOT_EMPTY_VALUE,EMPTY_VALUE);
      PlotIndexSetDouble(6,PLOT_EMPTY_VALUE,EMPTY_VALUE);
      PlotIndexSetDouble(7,PLOT_EMPTY_VALUE,EMPTY_VALUE);

      if(showTREND)
      {
         PlotIndexSetInteger(5,PLOT_DRAW_TYPE,DRAW_LINE);
         PlotIndexSetInteger(5,PLOT_LINE_COLOR,Tbgdclr);
         PlotIndexSetInteger(5,PLOT_LINE_WIDTH,TRENDwidth+4);
         PlotIndexSetInteger(6,PLOT_DRAW_TYPE,DRAW_LINE);
         PlotIndexSetInteger(6,PLOT_LINE_COLOR,TRENDupclr);
         PlotIndexSetInteger(6,PLOT_LINE_WIDTH,TRENDwidth);
         PlotIndexSetInteger(7,PLOT_DRAW_TYPE,DRAW_LINE);
         PlotIndexSetInteger(7,PLOT_LINE_COLOR,TRENDdnclr);
         PlotIndexSetInteger(7,PLOT_LINE_WIDTH,TRENDwidth);
      }
      else
      {
         PlotIndexSetInteger(5,PLOT_DRAW_TYPE,DRAW_NONE);
         PlotIndexSetInteger(6,PLOT_DRAW_TYPE,DRAW_NONE);
         PlotIndexSetInteger(7,PLOT_DRAW_TYPE,DRAW_NONE);
      }

      // --- XU-MA SIGNAL plots (plot indices 8, 9, 10) ---
      PlotIndexSetDouble(8, PLOT_EMPTY_VALUE,EMPTY_VALUE);
      PlotIndexSetDouble(9, PLOT_EMPTY_VALUE,EMPTY_VALUE);
      PlotIndexSetDouble(10,PLOT_EMPTY_VALUE,EMPTY_VALUE);

      if(showSIGNAL)
      {
         PlotIndexSetInteger(8,PLOT_DRAW_TYPE,DRAW_LINE);
         PlotIndexSetInteger(8,PLOT_LINE_COLOR,Sbgdclr);
         PlotIndexSetInteger(8,PLOT_LINE_WIDTH,SIGNALwidth+4);
         PlotIndexSetInteger(9,PLOT_DRAW_TYPE,DRAW_LINE);
         PlotIndexSetInteger(9,PLOT_LINE_COLOR,SIGNALupclr);
         PlotIndexSetInteger(9,PLOT_LINE_WIDTH,SIGNALwidth);
         PlotIndexSetInteger(10,PLOT_DRAW_TYPE,DRAW_LINE);
         PlotIndexSetInteger(10,PLOT_LINE_COLOR,SIGNALdnclr);
         PlotIndexSetInteger(10,PLOT_LINE_WIDTH,SIGNALwidth);
      }
      else
      {
         PlotIndexSetInteger(8, PLOT_DRAW_TYPE,DRAW_NONE);
         PlotIndexSetInteger(9, PLOT_DRAW_TYPE,DRAW_NONE);
         PlotIndexSetInteger(10,PLOT_DRAW_TYPE,DRAW_NONE);
      }

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   DeleteBackgroundObjects();
   IndicatorRelease(maHandle);
   IndicatorRelease(maSlowHandle);
   IndicatorRelease(atrHandle);
   IndicatorRelease(candleMaHandle);
   IndicatorRelease(candleMaSlowHandle);
   IndicatorRelease(candleAtrHandle);
   IndicatorRelease(tf1MaHandle);
   IndicatorRelease(tf1MaSlowHandle);
   IndicatorRelease(tf2MaHandle);
   IndicatorRelease(tf2MaSlowHandle);
   // XU-MA Handles
   IndicatorRelease(trendMaHighHandle);
   IndicatorRelease(trendMaLowHandle);
   IndicatorRelease(trendMaMedHandle);
   IndicatorRelease(signalMaHighHandle);
   IndicatorRelease(signalMaLowHandle);
   IndicatorRelease(signalMaMedHandle);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

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 = rates_total-prev_calculated;
          if (prev_calculated >  0) limit++;
          if (prev_calculated == 0) limit-=(angleBars+1);

      if (!checkCalculated(maHandle,    rates_total,"averages"))      return(prev_calculated);
      if (!checkCalculated(maSlowHandle,rates_total,"slow averages")) return(prev_calculated);
      if (!checkCalculated(atrHandle,   rates_total,"ATR"))           return(prev_calculated);
      if (!doCopy(maHandle,    maBuffer,    0,limit,"averages"))      return(prev_calculated);
      if (!doCopy(maSlowHandle,maSlowBuffer,0,limit,"slow averages")) return(prev_calculated);
      if (!doCopy(atrHandle,   atrBuffer,   0,limit,"ATR"))           return(prev_calculated);

      // --- TF Arrow Calculations (run early so arrowStateBuf is ready for candle coloring) ---
      bool calcArrows = (ShowArrows || CandleColorMode == CANDLE_COLOR_ARROW);
      int arrowLimit  = (prev_calculated <= 0) ? rates_total - 1 : limit;

      if(calcArrows)
      {
         int tf1Calc     = BarsCalculated(tf1MaHandle);
         int tf1SlowCalc = BarsCalculated(tf1MaSlowHandle);
         int tf2Calc     = BarsCalculated(tf2MaHandle);
         int tf2SlowCalc = BarsCalculated(tf2MaSlowHandle);

         if(tf1Calc <= 1 || tf1SlowCalc <= 1 || tf2Calc <= 1 || tf2SlowCalc <= 1)
            return(prev_calculated);

         int tf1CopyCount = MathMin(MathMin(tf1Calc, tf1SlowCalc), Bars(_Symbol,TF1));
         int tf2CopyCount = MathMin(MathMin(tf2Calc, tf2SlowCalc), Bars(_Symbol,TF2));

         if(tf1CopyCount <= 0 || tf2CopyCount <= 0)
            return(prev_calculated);

         double tf1Ma[], tf1MaSlow[], tf1Close[];
         double tf2Ma[], tf2MaSlow[], tf2Close[];
         ArraySetAsSeries(tf1Ma,    true); ArraySetAsSeries(tf1MaSlow,true); ArraySetAsSeries(tf1Close,true);
         ArraySetAsSeries(tf2Ma,    true); ArraySetAsSeries(tf2MaSlow,true); ArraySetAsSeries(tf2Close,true);

         if(CopyBuffer(tf1MaHandle,    0,0,tf1CopyCount,tf1Ma)     <= 0) return(prev_calculated);
         if(CopyBuffer(tf1MaSlowHandle,0,0,tf1CopyCount,tf1MaSlow) <= 0) return(prev_calculated);
         if(CopyClose(_Symbol,TF1,0,tf1CopyCount,tf1Close)         <= 0) return(prev_calculated);
         if(CopyBuffer(tf2MaHandle,    0,0,tf2CopyCount,tf2Ma)     <= 0) return(prev_calculated);
         if(CopyBuffer(tf2MaSlowHandle,0,0,tf2CopyCount,tf2MaSlow) <= 0) return(prev_calculated);
         if(CopyClose(_Symbol,TF2,0,tf2CopyCount,tf2Close)         <= 0) return(prev_calculated);

         for(int i = arrowLimit; i >= 0; i--)
         {
            if(ShowArrows)
            {
               arrowUpBuf[i] = EMPTY_VALUE;
               arrowDnBuf[i] = EMPTY_VALUE;
            }

            double lastState = -1.0;
            if(i < rates_total - 1)
               lastState = arrowStateBuf[i+1];
            double currentState = lastState;

            int barIndex = rates_total - 1 - i;
            if(barIndex < 0 || barIndex >= rates_total)
            {
               arrowStateBuf[i] = currentState;
               continue;
            }

            int s1 = iBarShift(_Symbol,TF1,time[barIndex],false);
            int s2 = iBarShift(_Symbol,TF2,time[barIndex],false);
            if(s1 < 0 || s1 >= tf1CopyCount || s2 < 0 || s2 >= tf2CopyCount)
            {
               arrowStateBuf[i] = currentState;
               continue;
            }

            int col1 = getCandleColorIndex(tf1Close[s1],tf1Ma[s1],tf1MaSlow[s1]);
            int col2 = getCandleColorIndex(tf2Close[s2],tf2Ma[s2],tf2MaSlow[s2]);

            // Check for Bullish signal: both TFs are strictly Blue (1)
            if(col1 == 1 && col2 == 1)
            {
               bool becameBullish = false;
               if(barIndex > 0)
               {
                  int prev_s1 = iBarShift(_Symbol,TF1,time[barIndex-1],false);
                  int prev_s2 = iBarShift(_Symbol,TF2,time[barIndex-1],false);
                  if(prev_s1 >= 0 && prev_s1 < tf1CopyCount && prev_s2 >= 0 && prev_s2 < tf2CopyCount)
                  {
                     int prev_col1 = getCandleColorIndex(tf1Close[prev_s1],tf1Ma[prev_s1],tf1MaSlow[prev_s1]);
                     int prev_col2 = getCandleColorIndex(tf2Close[prev_s2],tf2Ma[prev_s2],tf2MaSlow[prev_s2]);
                     if(prev_col1 != 1 || prev_col2 != 1)
                        becameBullish = true;
                  }
               }
               else becameBullish = true;

               if(becameBullish)
               {
                  if(ShowArrows)
                  {
                     double gap = (atrBuffer[i] > 0) ? atrBuffer[i] * 0.5 : _Point * 10;
                     arrowUpBuf[i] = low[barIndex] - gap;
                  }
                  currentState = 1.0;
               }
            }

            // Check for Bearish signal: both TFs are strictly Red (0)
            if(col1 == 0 && col2 == 0)
            {
               bool becameBearish = false;
               if(barIndex > 0)
               {
                  int prev_s1 = iBarShift(_Symbol,TF1,time[barIndex-1],false);
                  int prev_s2 = iBarShift(_Symbol,TF2,time[barIndex-1],false);
                  if(prev_s1 >= 0 && prev_s1 < tf1CopyCount && prev_s2 >= 0 && prev_s2 < tf2CopyCount)
                  {
                     int prev_col1 = getCandleColorIndex(tf1Close[prev_s1],tf1Ma[prev_s1],tf1MaSlow[prev_s1]);
                     int prev_col2 = getCandleColorIndex(tf2Close[prev_s2],tf2Ma[prev_s2],tf2MaSlow[prev_s2]);
                     if(prev_col1 != 0 || prev_col2 != 0)
                        becameBearish = true;
                  }
               }
               else becameBearish = true;

               if(becameBearish)
               {
                  if(ShowArrows)
                  {
                     double gap = (atrBuffer[i] > 0) ? atrBuffer[i] * 0.5 : _Point * 10;
                     arrowDnBuf[i] = high[barIndex] + gap;
                  }
                  currentState = 0.0;
               }
            }

            arrowStateBuf[i] = currentState;
         }
      }
      else
      {
         for(int i = arrowLimit; i >= 0; i--)
         {
            arrowUpBuf[i]    = EMPTY_VALUE;
            arrowDnBuf[i]    = EMPTY_VALUE;
            arrowStateBuf[i] = -1.0;
         }
      }

      // ================================================================
      // --- XU-MA v3 TREND + SIGNAL MTF Logic --------------------------
      // ================================================================
      // Each MA uses a High-price band and Low-price band.
      // price > MA(High)  => direction = +1  (bullish)
      // price < MA(Low)   => direction = -1  (bearish)
      // price in between  => hold previous direction (persistence)
      // xtrend = +1 only when BOTH trend=+1 AND signal=+1
      // xtrend = -1 only when BOTH trend=-1 AND signal=-1
      // ================================================================
      {
         int tCalcH = BarsCalculated(trendMaHighHandle);
         int tCalcL = BarsCalculated(trendMaLowHandle);
         int tCalcM = BarsCalculated(trendMaMedHandle);
         int sCalcH = BarsCalculated(signalMaHighHandle);
         int sCalcL = BarsCalculated(signalMaLowHandle);
         int sCalcM = BarsCalculated(signalMaMedHandle);

         if(tCalcH <= 1 || tCalcL <= 1 || tCalcM <= 1 ||
            sCalcH <= 1 || sCalcL <= 1 || sCalcM <= 1)
            return(prev_calculated);

         bool trendDiffTF  = (TRENDtf  != PERIOD_CURRENT && TRENDtf  != (ENUM_TIMEFRAMES)_Period);
         bool signalDiffTF = (SIGNALtf != PERIOD_CURRENT && SIGNALtf != (ENUM_TIMEFRAMES)_Period);

         int tBarsAvail = trendDiffTF  ? Bars(_Symbol,TRENDtf)  : rates_total;
         int sBarsAvail = signalDiffTF ? Bars(_Symbol,SIGNALtf) : rates_total;

         int tCopyCount = MathMin(MathMin(tCalcH, MathMin(tCalcL, tCalcM)), tBarsAvail);
         int sCopyCount = MathMin(MathMin(sCalcH, MathMin(sCalcL, sCalcM)), sBarsAvail);

         if(tCopyCount <= 0 || sCopyCount <= 0) return(prev_calculated);

         double tHighArr[], tLowArr[], tMedArr[];
         double sHighArr[], sLowArr[], sMedArr[];
         ArraySetAsSeries(tHighArr,true); ArraySetAsSeries(tLowArr,true); ArraySetAsSeries(tMedArr,true);
         ArraySetAsSeries(sHighArr,true); ArraySetAsSeries(sLowArr,true); ArraySetAsSeries(sMedArr,true);

         if(CopyBuffer(trendMaHighHandle,  0,0,tCopyCount,tHighArr) <= 0) return(prev_calculated);
         if(CopyBuffer(trendMaLowHandle,   0,0,tCopyCount,tLowArr)  <= 0) return(prev_calculated);
         if(CopyBuffer(trendMaMedHandle,   0,0,tCopyCount,tMedArr)  <= 0) return(prev_calculated);
         if(CopyBuffer(signalMaHighHandle, 0,0,sCopyCount,sHighArr) <= 0) return(prev_calculated);
         if(CopyBuffer(signalMaLowHandle,  0,0,sCopyCount,sLowArr)  <= 0) return(prev_calculated);
         if(CopyBuffer(signalMaMedHandle,  0,0,sCopyCount,sMedArr)  <= 0) return(prev_calculated);

         // Use full history on first run for proper trend persistence
         int xuLimit = (prev_calculated <= 0) ? rates_total - 1 : limit;

         for(int i = xuLimit; i >= 0; i--)
         {
            int barIndex = rates_total - 1 - i;

            // ---- TREND direction ----
            int tShift = i; // default: same TF as current chart
            if(trendDiffTF)
            {
               tShift = iBarShift(_Symbol,TRENDtf,time[barIndex],false);
               if(tShift < 0 || tShift >= tCopyCount)
               {
                  // Can't map this bar — carry forward last known state
                  trendCalcBuf[i]  = (i < rates_total-1) ? trendCalcBuf[i+1]  : 0;
                  signalCalcBuf[i] = (i < rates_total-1) ? signalCalcBuf[i+1] : 0;
                  xtrendCalcBuf[i] = 0;
                  TbgdBuf[i]     = EMPTY_VALUE; TRENDupBuf[i]  = EMPTY_VALUE; TRENDdnBuf[i]  = EMPTY_VALUE;
                  SbgdBuf[i]     = EMPTY_VALUE; SIGNALupBuf[i] = EMPTY_VALUE; SIGNALdnBuf[i] = EMPTY_VALUE;
                  continue;
               }
            }

            double prevTrend = (i < rates_total-1) ? trendCalcBuf[i+1] : 0;

            if     (close[barIndex] > tHighArr[tShift]) trendCalcBuf[i] =  1; // price broke above high band → bull
            else if(close[barIndex] < tLowArr[tShift])  trendCalcBuf[i] = -1; // price broke below low band  → bear
            else                                         trendCalcBuf[i] = prevTrend; // in the band → persist

            if(showTREND)
            {
               TbgdBuf[i]    = tMedArr[tShift];
               TRENDupBuf[i] = (trendCalcBuf[i] ==  1) ? tMedArr[tShift] : EMPTY_VALUE;
               TRENDdnBuf[i] = (trendCalcBuf[i] == -1) ? tMedArr[tShift] : EMPTY_VALUE;
            }
            else
            {
               TbgdBuf[i]    = EMPTY_VALUE;
               TRENDupBuf[i] = EMPTY_VALUE;
               TRENDdnBuf[i] = EMPTY_VALUE;
            }

            // ---- SIGNAL direction ----
            int sShift = i; // default: same TF as current chart
            if(signalDiffTF)
            {
               sShift = iBarShift(_Symbol,SIGNALtf,time[barIndex],false);
               if(sShift < 0 || sShift >= sCopyCount)
               {
                  signalCalcBuf[i] = (i < rates_total-1) ? signalCalcBuf[i+1] : 0;
                  xtrendCalcBuf[i] = 0;
                  SbgdBuf[i]     = EMPTY_VALUE; SIGNALupBuf[i] = EMPTY_VALUE; SIGNALdnBuf[i] = EMPTY_VALUE;
                  continue;
               }
            }

            double prevSignal = (i < rates_total-1) ? signalCalcBuf[i+1] : 0;

            if     (close[barIndex] > sHighArr[sShift]) signalCalcBuf[i] =  1;
            else if(close[barIndex] < sLowArr[sShift])  signalCalcBuf[i] = -1;
            else                                          signalCalcBuf[i] = prevSignal;

            if(showSIGNAL)
            {
               SbgdBuf[i]     = sMedArr[sShift];
               SIGNALupBuf[i] = (signalCalcBuf[i] ==  1) ? sMedArr[sShift] : EMPTY_VALUE;
               SIGNALdnBuf[i] = (signalCalcBuf[i] == -1) ? sMedArr[sShift] : EMPTY_VALUE;
            }
            else
            {
               SbgdBuf[i]     = EMPTY_VALUE;
               SIGNALupBuf[i] = EMPTY_VALUE;
               SIGNALdnBuf[i] = EMPTY_VALUE;
            }

            // ---- xtrend: BOTH must agree ----
            if     (trendCalcBuf[i] ==  1 && signalCalcBuf[i] ==  1) xtrendCalcBuf[i] =  1;
            else if(trendCalcBuf[i] == -1 && signalCalcBuf[i] == -1) xtrendCalcBuf[i] = -1;
            else                                                       xtrendCalcBuf[i] =  0;
         }
      }
      // ================================================================

      double candleMaBuffer[], candleMaSlowBuffer[], candleCloseBuffer[];
      bool useSelectedCandleTF = (CandleColorTF != PERIOD_CURRENT);

      if((ColorCandles || ColorBackground) && useSelectedCandleTF)
      {
         int oldestShift = iBarShift(_Symbol,CandleColorTF,time[0],false);
         if(oldestShift < 0)
            return(prev_calculated);

         int copyCount = oldestShift + angleBars + 2;
         int candleBars = Bars(_Symbol,CandleColorTF);
         if(copyCount > candleBars) copyCount = candleBars;

         ArraySetAsSeries(candleMaBuffer,    true);
         ArraySetAsSeries(candleMaSlowBuffer,true);
         ArraySetAsSeries(candleCloseBuffer, true);

         if(!checkCalculated(candleMaHandle,    copyCount,"candle timeframe averages"))      return(prev_calculated);
         if(!checkCalculated(candleMaSlowHandle,copyCount,"candle timeframe slow averages")) return(prev_calculated);
         if(!doCopy(candleMaHandle,    candleMaBuffer,    0,copyCount,"candle timeframe averages"))      return(prev_calculated);
         if(!doCopy(candleMaSlowHandle,candleMaSlowBuffer,0,copyCount,"candle timeframe slow averages")) return(prev_calculated);
         if(CopyClose(_Symbol,CandleColorTF,0,copyCount,candleCloseBuffer)<=0)
         {
            Print("Getting candle timeframe close failed!");
            return(prev_calculated);
         }
      }

   //
   //
   //
   //
   //

   for(int i=limit; i>=0; i--)
   {
      maColors[i]     = slopeColor(i, maBuffer);
      maSlowColors[i] = slopeColor(i, maSlowBuffer);

      if(ColorCandles || ColorBackground)
      {
         int barIndex = rates_total - 1 - i;
         if(barIndex >= 0 && barIndex < rates_total)
         {
            candleOpen[i]  = open[barIndex];
            candleHigh[i]  = high[barIndex];
            candleLow[i]   = low[barIndex];
            candleClose[i] = close[barIndex];

            double price  = 0;
            double fastMA = 0;
            double slowMA = 0;

            if(useSelectedCandleTF)
            {
               int shift = iBarShift(_Symbol,CandleColorTF,time[barIndex],false);
               if(shift >= 0 && shift < ArraySize(candleCloseBuffer))
               {
                  price  = candleCloseBuffer[shift];
                  fastMA = candleMaBuffer[shift];
                  slowMA = candleMaSlowBuffer[shift];
               }
            }
            else
            {
               price  = close[barIndex];
               fastMA = maBuffer[i];
               slowMA = maSlowBuffer[i];
            }

            if(CandleColorMode == CANDLE_COLOR_ARROW)
            {
               double state = arrowStateBuf[i];
               if     (state == 1.0) candleColors[i] = 1; // Bullish (Blue)
               else if(state == 0.0) candleColors[i] = 0; // Bearish (Red)
               else                  candleColors[i] = getCandleColorIndex(price, fastMA, slowMA);
            }
            else if(CandleColorMode == CANDLE_COLOR_XUMT)
            {
               // Color by XU-MA combined TREND + SIGNAL direction
               double xstate = xtrendCalcBuf[i];
               if(xstate == 1.0)       candleColors[i] = 1; // Both bull  → Blue
               else if(xstate == -1.0) candleColors[i] = 0; // Both bear  → Red
               else
               {
                  // Disagreement: use individual trend for nuance
                  if     (trendCalcBuf[i] ==  1) candleColors[i] = 2; // TREND bull, SIGNAL not → LightBlue
                  else if(trendCalcBuf[i] == -1) candleColors[i] = 3; // TREND bear, SIGNAL not → LightRed
                  else                            candleColors[i] = getCandleColorIndex(price, fastMA, slowMA);
               }
            }
            else
            {
               candleColors[i] = getCandleColorIndex(price, fastMA, slowMA);
            }
         }
      }
   }

   // Background coloring
   if(ColorBackground)
   {
      int maxBars = (BgMaxBars > 0) ? BgMaxBars : 2000;
      int bgLimit = (limit > maxBars) ? maxBars : limit;
      if(bgLimit < 0) bgLimit = 0;

      for(int i = bgLimit; i >= 0; i--)
      {
         int barIndex = rates_total - 1 - i;
         if(barIndex >= 0 && barIndex < rates_total)
         {
            datetime time1 = time[barIndex];
            datetime time2 = time1 + PeriodSeconds(_Period);

            int colorIdx = (int)candleColors[i];
            color bgCol  = clrNONE;
            switch(colorIdx)
            {
               case 0: bgCol = BgColorBearish;   break;
               case 1: bgCol = BgColorBullish;   break;
               case 2: bgCol = BgColorLightBlue; break;
               case 3: bgCol = BgColorLightRed;  break;
            }

            string rectName = "MA_Bg_Rec_" + TimeToString(time1);
            if(bgCol != clrNONE)
            {
               if(ObjectFind(0, rectName) < 0)
               {
                  if(ObjectCreate(0, rectName, OBJ_RECTANGLE, 0, time1, 2000000000.0, time2, -2000000000.0))
                  {
                     ObjectSetInteger(0, rectName, OBJPROP_COLOR,     bgCol);
                     ObjectSetInteger(0, rectName, OBJPROP_FILL,      true);
                     ObjectSetInteger(0, rectName, OBJPROP_BACK,      true);
                     ObjectSetInteger(0, rectName, OBJPROP_SELECTABLE,false);
                     ObjectSetInteger(0, rectName, OBJPROP_SELECTED,  false);
                     ObjectSetInteger(0, rectName, OBJPROP_HIDDEN,    true);
                  }
               }
               else
               {
                  if((color)ObjectGetInteger(0, rectName, OBJPROP_COLOR) != bgCol)
                     ObjectSetInteger(0, rectName, OBJPROP_COLOR, bgCol);

                  if((datetime)ObjectGetInteger(0, rectName, OBJPROP_TIME, 0) != time1)
                     ObjectSetInteger(0, rectName, OBJPROP_TIME, 0, time1);

                  if((datetime)ObjectGetInteger(0, rectName, OBJPROP_TIME, 1) != time2)
                     ObjectSetInteger(0, rectName, OBJPROP_TIME, 1, time2);
               }
            }
            else
            {
               ObjectDelete(0, rectName);
            }
         }
      }

      // Clean up older background objects beyond BgMaxBars
      if(limit > maxBars)
      {
         int oldestBarIdx = rates_total - 1 - maxBars;
         if(oldestBarIdx >= 0 && oldestBarIdx < rates_total)
         {
            datetime oldestTime = time[oldestBarIdx];
            int total = ObjectsTotal(0, 0, OBJ_RECTANGLE);
            for(int idx = total - 1; idx >= 0; idx--)
            {
               string name = ObjectName(0, idx, 0, OBJ_RECTANGLE);
               if(StringFind(name, "MA_Bg_Rec_") == 0)
               {
                  datetime objTime = (datetime)ObjectGetInteger(0, name, OBJPROP_TIME, 0);
                  if(objTime < oldestTime)
                     ObjectDelete(0, name);
               }
            }
         }
      }
   }
   else
   {
      DeleteBackgroundObjects();
   }

   return(rates_total);
}




//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

#define Pi 3.141592653589793238462643

//
//
//

int slopeColor(int i, const double &maArray[])
{
   double range  = atrBuffer[i];
   double angle  = 0.00;
   double change = maArray[i]-maArray[i+angleBars];

      if (range != 0) angle = MathArctan(change/(range*angleBars))*180.0/Pi;

      int theColor = (int)round((angle+MaxAngle)/(MaxAngle/10.0));
          theColor = (theColor>=0) ? ((theColor<20) ? theColor : 19) : 0;
   return(theColor);
}

//
//
//
//

int slopeColorFromBuffers(const double &maValues[], const double &atrValues[], int shift)
{
   if(shift < 0 || shift + angleBars >= ArraySize(maValues) || shift >= ArraySize(atrValues))
      return(10);

   double range  = atrValues[shift];
   double angle  = 0.00;
   double change = maValues[shift]-maValues[shift+angleBars];

      if (range != 0) angle = MathArctan(change/(range*angleBars))*180.0/Pi;

      int theColor = (int)round((angle+MaxAngle)/(MaxAngle/10.0));
          theColor = (theColor>=0) ? ((theColor<20) ? theColor : 19) : 0;
   return(theColor);
}

//+------------------------------------------------------------------+
//| Get Candle Color Index based on Price relative to Fast & Slow MA |
//+------------------------------------------------------------------+
int getCandleColorIndex(double price, double fastMA, double slowMA)
{
   if(price < fastMA && price < slowMA) return 0; // Red       – below both MAs
   if(price > fastMA && price > slowMA) return 1; // Blue      – above both MAs
   if(price < fastMA && price > slowMA) return 2; // LightBlue – below fast, above slow
   if(price > fastMA && price < slowMA) return 3; // LightRed  – above fast, below slow
   return 0;
}

//
//
//
//
//

color gradientColor(int step, int totalSteps, color from, color to)
{
   color newBlue  = getColor(step,totalSteps,(from & 0XFF0000)>>16,(to & 0XFF0000)>>16)<<16;
   color newGreen = getColor(step,totalSteps,(from & 0X00FF00)>> 8,(to & 0X00FF00)>> 8) <<8;
   color newRed   = getColor(step,totalSteps,(from & 0X0000FF)    ,(to & 0X0000FF)    )    ;
   return(newBlue+newGreen+newRed);
}

color getColor(int stepNo, int totalSteps, color from, color to)
{
   double step = (from-to)/(totalSteps-1.0);
   return((color)round(from-step*stepNo));
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//

bool checkCalculated(int bufferHandle, int total, string checkDescription)
{
   int calculated=BarsCalculated(bufferHandle);
   if (calculated<total)
   {
      Print("Not all data of "+checkDescription+" calculated (",(string)(total-calculated)," un-calculated bars )");
      return(false);
   }
   return(true);
}

//
//
//
//
//

bool doCopy(const int bufferHandle, double& buffer[], const int buffNum, const int copyCount, string copyDescription)
{
   if(CopyBuffer(bufferHandle,buffNum,0,copyCount,buffer)<=0)
   {
      Print("Getting "+copyDescription+" failed! Error",GetLastError());
      return(false);
   }
   return(true);
}
