//+------------------------------------------------------------------+
//|                                              rsx on jurik smooth |
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_separate_window
#property indicator_buffers  3
#property indicator_color1   clrBlue
#property indicator_color2   clrMagenta
#property indicator_color3   clrGray
#property strict

//
//
//

input int                inpLength             = 35;                // Rsx length
input ENUM_APPLIED_PRICE inpPrice              = PRICE_CLOSE;       // Rsx price
input bool               Double                = false;             // Rsx double smooth
input bool               alertsOn              = true;              // Alerts?
input bool               alertsOnCurrent       = false;             // Alerts open bar?
input bool               alertsMessage         = true;              // Alerts popup message?
input bool               alertsSound           = false;             // Alerts sound?
input bool               alertsEmail           = false;             // Alerts email?
input bool               alertsNotify          = false;             // Alerts notification?

double UpH[],DnH[],val[],vals[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

int OnInit()
{
   IndicatorBuffers(4);
   SetIndexBuffer(0,UpH,INDICATOR_DATA);  SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,DnH,INDICATOR_DATA);  SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(2,val,INDICATOR_DATA);  SetIndexStyle(2,DRAW_LINE);
   SetIndexBuffer(3,vals); 
    
   IndicatorSetString(INDICATOR_SHORTNAME,"Rsx ("+(string)inpLength+")");
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)  { }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

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 i=rates_total-prev_calculated+1; if (i>=rates_total) i=rates_total-1;
   
   //
   //
   //
   
   for (; i>=0 && !_StopFlag; i--)
   {
      double prc = iMA(_Symbol,_Period,1,0,MODE_SMA,inpPrice,i);
      val[i]  = iRsx(iRsx(prc,inpLength,i,rates_total,0),inpLength,i,rates_total,1)-50;
      vals[i] = (i<rates_total-1) ? (val[i]>val[i+1]) ? 1 : (val[i]<val[i+1]) ? -1 : vals[i+1] : 0;  
      UpH[i] = (vals[i] == 1) ? val[i] : EMPTY_VALUE;
      DnH[i] = (vals[i] ==-1) ? val[i] : EMPTY_VALUE;
   }
   if (alertsOn)
   {
      int whichBar = 1; if (alertsOnCurrent) whichBar = 0;
      if (vals[whichBar] != vals[whichBar+1])
      if (vals[whichBar] == 1)
            doAlert("up");
      else  doAlert("down");       
   }     
return(rates_total);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

#define _rsxInstances      2
#define _rsxInstancesSize 13
double workRsi[][_rsxInstances*_rsxInstancesSize];
#define _price  0
//
//
//
double iRsx(double price,double period,int r,int bars,int instanceNo=0)
  {
   if(ArrayRange(workRsi,0)!=bars) ArrayResize(workRsi,bars); int z=instanceNo*_rsxInstancesSize; r = bars-r-1;
   
   //
   //
   //
   
   workRsi[r][z+_price]=price;
   double Kg=(3.0)/(2.0+period),Hg=1.0-Kg;
   if(r<period) { for(int k=1; k<13; k++) workRsi[r][k+z]=0; return(50); }
   
   //
   //
   //
   
   double mom = workRsi[r][_price+z]-workRsi[r-1][_price+z];
   double moa = fabs(mom);
   for(int k=0; k<3; k++)
   {
      int kk=k*2;
      workRsi[r][z+kk+1] = Kg*mom                + Hg*workRsi[r-1][z+kk+1];
      workRsi[r][z+kk+2] = Kg*workRsi[r][z+kk+1] + Hg*workRsi[r-1][z+kk+2]; mom = 1.5*workRsi[r][z+kk+1] - 0.5 * workRsi[r][z+kk+2];
      workRsi[r][z+kk+7] = Kg*moa                + Hg*workRsi[r-1][z+kk+7];
      workRsi[r][z+kk+8] = Kg*workRsi[r][z+kk+7] + Hg*workRsi[r-1][z+kk+8]; moa = 1.5*workRsi[r][z+kk+7] - 0.5 * workRsi[r][z+kk+8];
   }
return(fmax(fmin((mom/fmax(moa,DBL_MIN)+1.0)*50.0,100.00),0.00));
}           

//------------------------------------------------------------------
//                                                                  
//------------------------------------------------------------------

void doAlert(string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
      if (previousAlert != doWhat || previousTime != Time[0]) {
          previousAlert  = doWhat;
          previousTime   = Time[0];

          //
          //
          //
          //
          //

          message = timeFrameToString(_Period)+" "+_Symbol+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+" Rsx "+doWhat;
             if (alertsMessage) Alert(message);
             if (alertsNotify)  SendNotification(message);
             if (alertsEmail)   SendMail(_Symbol+" Rsx ",message);
             if (alertsSound)   PlaySound("alert2.wav");
      }
}

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}

