//+------------------------------------------------------------------+
//|                                         Candle-Close-Percent.mq5 |
//|                                          Copyright 2024,JBlanked |
//|                                        https://www.jblanked.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024,JBlanked"
#property link      "https://www.jblanked.com/"
#property version   "1.00"
#property indicator_separate_window
#property indicator_plots 2
#property indicator_buffers 2

#property indicator_minimum 0
#property indicator_maximum 100

#property indicator_level1 25
#property indicator_level2 75
#property indicator_level3 50

#property indicator_label1  "Percent-Up"
#property indicator_color1  Lime
#property indicator_width1  2
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_style1  STYLE_SOLID

#property indicator_label2  "Percent-Dn"
#property indicator_color2  Magenta
#property indicator_width2  2
#property indicator_type2   DRAW_HISTOGRAM
#property indicator_style2  STYLE_SOLID

double percentBull[], percentBear[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0, percentBull, INDICATOR_DATA);
   SetIndexBuffer(1, percentBear, INDICATOR_DATA);
//---
   IndicatorSetInteger(INDICATOR_DIGITS, 2);
   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 = rates_total - prev_calculated;
   if(prev_calculated < 1)
     {
      ArrayInitialize(percentBull, EMPTY_VALUE);
      ArraySetAsSeries(percentBull, true);

      ArrayInitialize(percentBear, EMPTY_VALUE);
      ArraySetAsSeries(percentBear, true);
     }
   else
     {
      limit++;
     }
//---
   for(int i = limit - 1; i >= 0; i--)
     {
      percentBull[i] = EMPTY_VALUE;
      percentBear[i] = EMPTY_VALUE;

      switch(candleTrend(i))
        {
         case ENUM_BEARISH:
            percentBear[i] = percentOfClose(i);
            break;
         case ENUM_BULLISH:
            percentBull[i] = percentOfClose(i);
            break;
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
enum ENUM_BULLISH_OR_BEARISH
  {
   ENUM_BEARISH = -1,   // Bearish
   ENUM_NEUTRAL = 0,    // Neutral
   ENUM_BULLISH = 1,    // Bullish
  };
//---
ENUM_BULLISH_OR_BEARISH candleTrend(const int shift)
  {
   return
      iClose(_Symbol, PERIOD_CURRENT, shift) > iOpen(_Symbol, PERIOD_CURRENT, shift) ? ENUM_BULLISH :
      iClose(_Symbol, PERIOD_CURRENT, shift) < iOpen(_Symbol, PERIOD_CURRENT, shift) ? ENUM_BEARISH :
      ENUM_NEUTRAL;
  }
//---
double percentOfClose(const int shift)
  {
//--- bar range
   const double barRange = MathAbs(iHigh(_Symbol, PERIOD_CURRENT, shift) - iLow(_Symbol, PERIOD_CURRENT, shift));
//--- candle type
   const ENUM_BULLISH_OR_BEARISH candleType = candleTrend(shift);
//--- return percent of close
   return
      candleType == ENUM_BULLISH ? (iClose(_Symbol, PERIOD_CURRENT, shift) - iLow(_Symbol, PERIOD_CURRENT, shift)) / barRange * 100 :
      candleType == ENUM_BEARISH ? (iHigh(_Symbol, PERIOD_CURRENT, shift) - iClose(_Symbol, PERIOD_CURRENT, shift)) / barRange * 100 :
      50;
  }
//+------------------------------------------------------------------+
