//+------------------------------------------------------------------+
//|                                              RSI_multimethod.mq4 |
//|                                                          k-matsu |
//|                               http://www.age.jp/~k-matsu/FX/MT4/ |
//+------------------------------------------------------------------+
#property copyright "k-matsu"
#property link      "http://www.age.jp/~k-matsu/FX/MT4/"

#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_buffers 1
#property indicator_color1 MediumVioletRed
#property  indicator_level1  70
#property  indicator_level2  50
#property  indicator_level3  30
#property indicator_width1 1
//---- input parameters
extern int       RSIPeriod=14;
extern string    RSIMethodHelp="0:SMA(Cutler's),1:EMA,2:SMMA(Wilder's),3:LWMA";
extern int       RSIMethod=MODE_SMMA;
//---- buffers
double RSIBuffer[];
//---- internal buffers
double UpBuffer[];
double DnBuffer[];
double UpMABuffer[];
double DnMABuffer[];
//---- indicator name
string shortname;
//---- internal variable
double alpha_e, alpha_d;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   IndicatorBuffers(5);
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,RSIBuffer);
   SetIndexDrawBegin(0,RSIPeriod);
   SetIndexBuffer(1,UpBuffer);
   SetIndexBuffer(2,DnBuffer);
   SetIndexBuffer(3,UpMABuffer);
   SetIndexBuffer(4,DnMABuffer);

   // parameter check
   if (RSIPeriod < 2) RSIPeriod = 2;
   if (RSIMethod < MODE_SMA) RSIMethod = MODE_SMA;
   if (RSIMethod > MODE_LWMA) RSIMethod = MODE_LWMA;

   string MethodName;
   switch(RSIMethod) {
    case MODE_SMA:
      shortname = StringConcatenate("Cutler's RSI(",RSIPeriod,")");
      break;
    case MODE_EMA:
      shortname = StringConcatenate("RSI_EMA(",RSIPeriod,")");
      alpha_e = 2.0; alpha_d = 1.0+RSIPeriod;
      break;
    case MODE_SMMA:
      shortname = StringConcatenate("Wilder's RSI(",RSIPeriod,")");
      alpha_e = 1.0; alpha_d = RSIPeriod;
      break;
    case MODE_LWMA:
      shortname = StringConcatenate("RSI_LWMA(",RSIPeriod,")");
   }
   IndicatorShortName(shortname);
   SetIndexLabel(0,shortname);

//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    counted_bars=IndicatorCounted();
//----
    int i;
    int limit = Bars - MathMax(counted_bars, 2);
    double dif, numerator, denominator;

    for (i = limit; i >= 0; i--) {
      dif =Close[i]-Close[i+1];
      if (dif >= 0) {
        UpBuffer[i] = dif;
        DnBuffer[i] = 0.0;
      } else {
        DnBuffer[i] = -dif;
        UpBuffer[i] = 0.0;
      }
    }

    int initidx = Bars - RSIPeriod - 1;
    limit = Bars - 1 - MathMax(counted_bars, RSIPeriod);
    if (limit == initidx) {
      if (RSIMethod == MODE_LWMA) {
        numerator = iMAOnArray(UpBuffer, 0, RSIPeriod, 0, RSIMethod, initidx);
        denominator = numerator+iMAOnArray(DnBuffer, 0, RSIPeriod, 0, RSIMethod, initidx);
      } else {
        UpMABuffer[initidx] = iMAOnArray(UpBuffer, 0, RSIPeriod, 0, MODE_SMA, initidx);
        DnMABuffer[initidx] = iMAOnArray(DnBuffer, 0, RSIPeriod, 0, MODE_SMA, initidx);
        numerator = UpMABuffer[initidx];
        denominator = numerator + DnMABuffer[initidx];
      }
      if (denominator > 0.0) {
        RSIBuffer[initidx] = 100.0*numerator/denominator;
      } else {
        RSIBuffer[initidx] = 0.0;
      }
      limit--;
    }
    for (i = limit; i >= 0; i--) {
      if (RSIMethod == MODE_SMA || RSIMethod == MODE_LWMA) {
        numerator = iMAOnArray(UpBuffer, 0, RSIPeriod, 0, RSIMethod, i);
        denominator = numerator+iMAOnArray(DnBuffer, 0, RSIPeriod, 0, RSIMethod, i);
      } else {
        UpMABuffer[i] = (alpha_e * UpBuffer[i] + (alpha_d-alpha_e)*UpMABuffer[i+1]) / alpha_d;
        DnMABuffer[i] = (alpha_e * DnBuffer[i] + (alpha_d-alpha_e)*DnMABuffer[i+1]) / alpha_d;
        numerator = UpMABuffer[i];
        denominator = numerator + DnMABuffer[i];
      }
      if (denominator > 0.0) {
        RSIBuffer[i] = 100.0*numerator/denominator;
      } else {
        RSIBuffer[i] = 0.0;
      }
    }

//----
   return(0);
  }
//+------------------------------------------------------------------+

