//+------------------------------------------------------------------+
//|                                                      RedK EVEREX |
//|           Converted from https://www.tradingview.com/v/I5qJDPxT/ |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 12
#property strict

/*
User Notes:
--------------------------

RedK EVEREX is an experimental indicator that explores "Volume Price Analysis"
basic concepts and Wyckoff law "Effort versus Result" - by inspecting the
relative volume (effort) and the associated (relative) price action (result) for
each bar - showing the analysis as an easy to read "stacked bands" visual. From
that analysis, we calculate a "Relative Rate of Flow" (RROF) - an easy to use
+100/-100 oscilator that can be used to trigger a signal when a bullish or
bearish mode is detected for a certain user-selected length of bars.

What is RROF?
--------------------------

* Once we have the values of relative volume and relative price strength, it's
  easy from there to combine these values into a moving index that can be used
  to track overall strength and detect reversals in market direction - if you
  think about it this a very similar concept to a volume-weighted RSI. I call
  that index the "Relative Rate of Flow" - or RROF (cause we're not using the
  direct volume and price values in the calculation, but rather relative values
  that we calculated with the proprietary "Normalize" function in the script.

* You can show RROF as a single or double-period - and you can customize it in
  terms of smoothing, and signal line.

* Once you attach RROF to a chart, you will see how the RROF is able to detect
  change in market condition from Bearsh to Bullish - then from Bullish to
  Bearish with good accuracy.

* RROF is a "strength indicator" - it does not track price values (levels) or
  momentum - as you will see when you use it, the price can be moving up, while
  the RROF signal line starts moving down, reflecting decreasing strength (or
  otherwise, increasing bear strength) - So if you incorporate EVEREX in your
  trading you will need to use it alongside other momentum and price value
  indicators (like MACD, MA's, Trend Channels, Support & Resistance Lines, Fib /
  Donchian..etc) - to use for trade confirmation
 */

input int              length      = 10;            // RROF Length
input ENUM_MA_METHOD   MA_Type     = MODE_SMA;      // RROF MA Type
input int              smooth      = 3;             // RROF Smooth
input int              sig_length  = 5;             // Signal Length
input ENUM_MA_METHOD   S_Type      = MODE_SMA;      // Signal Type
input int              lookback    = 20;            // Lookback Length
input string           lkbk_Calc   = "Simple";      // Lookback Calc
//+-----------------------------------------------------------------------------------------------------------+
input bool             showBias    = false;         // Show Bias
input int              B_Length    = 30;            // Bias Length
input ENUM_MA_METHOD   B_Type      = MODE_SMA;      // Bias MA Type
input bool             showEVEREX  = false;         // Show EVEREX
input int              bandscale   = 100;           // Note: Band scale options ["100", "200", "400"] not directly available in MQL4
//+-----------------------------------------------------------------------------------------------------------+
input color            RROFColor   = clrDodgerBlue; // RROF Color
input color            SignalColor = clrRed;        // Signal Color
//+-----------------------------------------------------------------------------------------------------------+
input bool             ShowVolume  = false;         // Show Volume
input color            VolumeColor = clrMagenta;    // Volume Color
input ENUM_LINE_STYLE  VolumeStyle = STYLE_DOT;     // Volume Style
input bool             ShowPrice   = false;         // Show Price
input color            PriceColor  = clrDimGray;    // Price Color
input ENUM_LINE_STYLE  PriceStyle  = STYLE_DOT;     // Price Style
//+-----------------------------------------------------------------------------------------------------------+
input double           Level       = 40.0;          // Level
input ENUM_LINE_STYLE  LevelsStyle = STYLE_DOT;     // Levels Style
input color            LevelsColor = clrDimGray;    // Levels Color
//+-----------------------------------------------------------------------------------------------------------+

double VolaBuffer[];
double PriceaBuffer[];
double RROFBuffer[];
double SignalBuffer[];
double Bias[];
double Bv[];
double BarSpread_abs[];
double SrcShift_abs[];
double bulls[];
double bears[];
double RROF[];
double RROF_s[];

int maxPeriod;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int init()
{
   IndicatorBuffers(12);
   SetIndexBuffer(0, RROFBuffer);    SetIndexLabel(0,"RROF Smooth");       SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,1,RROFColor);
   SetIndexBuffer(1, SignalBuffer);  SetIndexLabel(1,"Signal Line");       SetIndexStyle(1,DRAW_LINE,STYLE_SOLID,1,SignalColor);
   SetIndexBuffer(2, VolaBuffer);    SetIndexLabel(2,"Volume Normalized"); SetIndexStyle(2,ShowVolume ? DRAW_LINE : DRAW_NONE,VolumeStyle,1,VolumeColor);
   SetIndexBuffer(3, PriceaBuffer);  SetIndexLabel(3,"Price Normalized");  SetIndexStyle(3,ShowPrice ? DRAW_LINE : DRAW_NONE,PriceStyle,1,PriceColor);
   SetIndexBuffer(4, Bias);          SetIndexLabel(4,"Bias");              SetIndexStyle(4,DRAW_NONE);
   SetIndexBuffer(5, Bv);            SetIndexLabel(5,"Bv");                SetIndexStyle(5,DRAW_NONE);
   SetIndexBuffer(6, BarSpread_abs); SetIndexLabel(6,"BarSpread");         SetIndexStyle(6,DRAW_NONE);
   SetIndexBuffer(7, SrcShift_abs);  SetIndexLabel(7,"SrcShift");          SetIndexStyle(7,DRAW_NONE);
   SetIndexBuffer(8, bulls);         SetIndexLabel(8,"bulls");             SetIndexStyle(8,DRAW_NONE);
   SetIndexBuffer(9, bears);         SetIndexLabel(9,"bears");             SetIndexStyle(9,DRAW_NONE);
   SetIndexBuffer(10,RROF);          SetIndexLabel(10,"RROF");             SetIndexStyle(10,DRAW_NONE);
   SetIndexBuffer(11,RROF_s);        SetIndexLabel(11,"RROF_s");           SetIndexStyle(11,DRAW_NONE);

   maxPeriod=MathMax(length,smooth);
   maxPeriod=MathMax(maxPeriod,sig_length);
   maxPeriod=MathMax(maxPeriod,lookback);
   maxPeriod=MathMax(maxPeriod,B_Length);

   IndicatorSetInteger(INDICATOR_LEVELS,3);
   IndicatorSetInteger(INDICATOR_LEVELCOLOR,LevelsColor);
   IndicatorSetInteger(INDICATOR_LEVELSTYLE,LevelsStyle);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,0,0);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,1,Level);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,2,-Level);

   IndicatorShortName("RedK EVEREX");
   return(0);
} 
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
{
   int i,counted_bars=IndicatorCounted();
   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
   int limit=fmin(Bars-counted_bars,Bars-maxPeriod);

   double Vola,Vola_n_pre,Vola_n;

   // Volume "effort" Calculation
   for(i=limit;i>=0;i--)
   {
      Bv[i]=(double)Volume[i];
   }
   for(i=limit;i>=0;i--)
   {
      Vola=iMAOnArray(Bv,0,length,0,MA_Type,i);

      Vola_n_pre = Normalize(Bv[i], Vola) * 100;
      Vola_n = Vola_n_pre; // Handle case of no volume data

      // Price "result" calculation
      double BarSpread = Close[i] - Open[i];
      double BarRange = High[i] - Low[i];
      double R2 = High[i+1] - Low[i+1];
      double SrcShift = Close[i] - Close[i+1];

      //double sign_shift = MathSign(SrcShift);
      double sign_shift; if(SrcShift<0){sign_shift=-1;}else{sign_shift=1;}
      
      
      //double sign_spread = MathSign(BarSpread);
      double sign_spread; if(BarSpread<0){sign_spread=-1;}else{sign_spread=1;}

      double barclosing = 2 * DivZero((Close[i] - Low[i]),BarRange) * 100 - 100;
      double s2r = DivZero(BarSpread,BarRange) * 100;
            BarSpread_abs[i] = MathAbs(BarSpread);
      
      double BarSpread_avg = iMAOnArray(BarSpread_abs, 0, lookback, 0, MA_Type, i);
      double BarSpread_ratio_n = Normalize(BarSpread_abs[i], BarSpread_avg) * 100 * sign_spread;

      double barclosing_2 = 2 * DivZero((Close[i] - Low[i+1]),R2) * 100 - 100;
      double Shift2Bar_toR2 = DivZero(SrcShift,R2) * 100;
            SrcShift_abs[i] = MathAbs(SrcShift);
      double srcshift_avg = iMAOnArray(SrcShift_abs, 0, lookback, 0, MA_Type, i);
      double srcshift_ratio_n = Normalize(SrcShift_abs[i], srcshift_avg) * 100 * sign_shift;

      double Pricea_n = (barclosing + s2r + BarSpread_ratio_n + barclosing_2 + Shift2Bar_toR2 + srcshift_ratio_n) / 6;

      double bar_flow = Pricea_n * Vola_n / 100;

      // Bulls and Bears calculation
            bulls[i] = MathMax(bar_flow, 0);
            bears[i] = -1 * MathMin(bar_flow, 0);
      double bulls_avg = iMAOnArray(bulls, 0, length, 0, MA_Type, i);
      double bears_avg = iMAOnArray(bears, 0, length, 0, MA_Type, i);
      double dx = DivZero(bulls_avg,bears_avg);
            RROF[i] = 2 * (100 - 100 / (1 + dx)) - 100;
            RROF_s[i] = iMAOnArray(RROF, 0, smooth, 0, MODE_SMA, i);

      // Signal line calculation
      double Signal = iMAOnArray(RROF_s, 0, sig_length, 0, S_Type, i);

      // Storing values in buffers
      VolaBuffer[i] = Vola_n;
      PriceaBuffer[i] = Pricea_n;
      RROFBuffer[i] = RROF_s[i]; 
      SignalBuffer[i] = Signal;

      if(RROFBuffer[i]>SignalBuffer[i])
      {
         if(RROFBuffer[i]>Level) Bias[i] = 4;
         else if(RROFBuffer[i]>0) Bias[i] = 3;
         else if(RROFBuffer[i]>-Level) Bias[i] = 2;
         else if(RROFBuffer[i]<-Level) Bias[i] = 1;
      }
      else if(RROFBuffer[i]<SignalBuffer[i])
      {
         if(RROFBuffer[i]<-Level) Bias[i] = -4;
         else if(RROFBuffer[i]>-Level) Bias[i] = -3;
         else if(RROFBuffer[i]>0) Bias[i] = -2;
         else if(RROFBuffer[i]>Level) Bias[i] = -1;
      }
      else Bias[i] = 0;
   }
   return(0);
}

//double GetAverage(double data[], int len, ENUM_MA_METHOD MAOption) {
//   double value = 0;
//   switch (MAOption) {
//      case MODE_SMA: value = iMA(NULL, 0, len, 0, MODE_SMA, PRICE_CLOSE, 0); break;
//      case MODE_EMA: value = iMA(NULL, 0, len, 0, MODE_EMA, PRICE_CLOSE, 0); break;
//      case MODE_SMMA: value = iMA(NULL, 0, len, 0, MODE_SMMA, PRICE_CLOSE, 0); break;
//      case MODE_LWMA: value = iMA(NULL, 0, len, 0, MODE_LWMA, PRICE_CLOSE, 0); break;
//   }
//   return value;
//}

double Normalize(double Value, double Avg) {
   double X = DivZero(Value,Avg);
   double Nor = 0.1; // Default value
   if (X > 1.50) Nor = 1.00;
   else if (X > 1.20) Nor = 0.90;
   else if (X > 1.00) Nor = 0.80;
   else if (X > 0.80) Nor = 0.70;
   else if (X > 0.60) Nor = 0.60;
   else if (X > 0.40) Nor = 0.50;
   else if (X > 0.20) Nor = 0.25;
   return (Nor);
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double DivZero(double n,double d)
{
//+------------------------------------------------------------------+
// Divides N by D, and returns 0 if the denominator (D) = 0
// Usage:   double x = DivZero(y,z)  sets x = y/z
// Use DivZero(y,z) instead of y/z to eliminate division by zero errors
   if(d == 0) return(0);  else return(1.0*n/d);
}
//+------------------------------------------------------------------+

//+--------------------------- END ----------------------------------+
