//+------------------------------------------------------------------+
//|                                                 Zero_Lag_RSI.mq4 |
//|                               Copyright © 2015, Gehtsoft USA LLC |
//|                                            http://fxcodebase.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2015, Gehtsoft USA LLC"
#property link      "http://fxcodebase.com"

#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1  Green
#property indicator_color2  DarkGreen
#property indicator_color3  Red
#property indicator_color4  DarkRed

extern ENUM_TIMEFRAMES TimeFrame        = PERIOD_CURRENT;
extern int Smoothing1=15;
extern int Smoothing2=7;
extern double Factor1=0.05;
extern int RSI_Length1=8;
extern double Factor2=0.1;
extern int RSI_Length2=21;
extern double Factor3=0.16;
extern int RSI_Length3=34;
extern double Factor4=0.26;
extern int RSI_Length4=55;
extern double Factor5=0.43;
extern int RSI_Length5=89;
extern ENUM_APPLIED_PRICE Price=0;    // Applied price
extern bool            alertsOn        = true;
extern bool            alertsOnCurrent = false;
extern bool            alertsMessage   = true;
extern bool            alertsSound     = true;
extern bool            alertsNotify    = false;
extern bool            alertsEmail     = false;
extern string          soundFile       = "alert2.wav";


double UU[], UD[], DU[], DD[];
double FastTrend[], SlowTrend[], cross[];
double SmoothConst1, SmoothConst2;
string indicatorFileName;
bool   returnBars;


int init()
{
 IndicatorBuffers(7);
 SetIndexBuffer(0,UU); SetIndexStyle(0,DRAW_HISTOGRAM);
 SetIndexBuffer(1,UD); SetIndexStyle(1,DRAW_HISTOGRAM);
 SetIndexBuffer(2,DU); SetIndexStyle(2,DRAW_HISTOGRAM);
 SetIndexBuffer(3,DD); SetIndexStyle(3,DRAW_HISTOGRAM);
 SetIndexBuffer(4,FastTrend);
 SetIndexBuffer(5,SlowTrend);
 SetIndexBuffer(6,cross);
 
 SmoothConst1=(Smoothing1-1.)/Smoothing1;
 SmoothConst2=(Smoothing2-1.)/Smoothing2;
 indicatorFileName = WindowExpertName();
 returnBars        = TimeFrame==-99;
 TimeFrame         = MathMax(TimeFrame,_Period);
 IndicatorShortName(timeFrameToString(TimeFrame)+" ZeroLag RSI");

 return(0);
}

int deinit()
{

 return(0);
}

int start()
{
    int counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
            int limit = MathMin(Bars - counted_bars,Bars-1);
            if (returnBars)  { UU[0] = limit+1; return(0); } 
            
    //
   //
   //
   //
   //

   if (TimeFrame == Period())
   {  
      for(int pos=limit; pos>=0; pos--) 
      {
      double RSI1 = iRSI(NULL,0,RSI_Length1,Price,pos);
      double RSI2 = iRSI(NULL,0,RSI_Length2,Price,pos);
      double RSI3 = iRSI(NULL,0,RSI_Length3,Price,pos);
      double RSI4 = iRSI(NULL,0,RSI_Length4,Price,pos);
      double RSI5 = iRSI(NULL,0,RSI_Length5,Price,pos);
  
      double Osc1=Factor1*RSI1;
      double Osc2=Factor1*RSI2;
      double Osc3=Factor1*RSI3;
      double Osc4=Factor1*RSI4;
      double Osc5=Factor1*RSI5;
  
      FastTrend[pos]=Osc1+Osc2+Osc3+Osc4+Osc5;
      SlowTrend[pos]=FastTrend[pos]/Smoothing1+SlowTrend[pos+1]*SmoothConst1;
      UU[pos]=(FastTrend[pos]-SlowTrend[pos])/(Smoothing2*Point)+UU[pos+1]*SmoothConst2;
      
      UD[pos]=EMPTY_VALUE;
      DU[pos]=EMPTY_VALUE;
      DD[pos]=EMPTY_VALUE;
  
      cross[pos] = cross[pos+1];
      if (UU[pos]>0.)
      {
         cross[pos]=1;
         if (UU[pos]<UU[pos+1])
         {
            UD[pos]=UU[pos];
         }
      }
      else
      {
         cross[pos]=-1;
         if (UU[pos]>UU[pos+1])
         {
            DU[pos]=UU[pos];
         }
         else
         {
            DD[pos]=UU[pos];
         }
      }
   } 

   //
   //
   //
   //
   //
      
   if (alertsOn)
   {
      if (alertsOnCurrent)
           int whichBar = 0;
      else     whichBar = 1;
      Comment(cross[whichBar],"   ",cross[whichBar+1]);
      if (cross[whichBar] != cross[whichBar+1])
      if (cross[whichBar] == 1)
            doAlert("crossing zero line up");
      else  doAlert("crossing zero line down");       
   }
   return(0);
 }
 
 //
   //
   //
   //
   //
 
    limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,TimeFrame,indicatorFileName,-99,0,0)*TimeFrame/Period()));
    for(pos=limit; pos >= 0; pos--)  
    {
       int y = iBarShift(NULL,TimeFrame,Time[pos]);
          UU[pos] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,Smoothing1,Smoothing2,Factor1,RSI_Length1,Factor2,RSI_Length2,Factor3,RSI_Length3,Factor4,RSI_Length4,Factor5,RSI_Length5,Price,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsNotify,alertsEmail,soundFile,0,y);
          UD[pos] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,Smoothing1,Smoothing2,Factor1,RSI_Length1,Factor2,RSI_Length2,Factor3,RSI_Length3,Factor4,RSI_Length4,Factor5,RSI_Length5,Price,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsNotify,alertsEmail,soundFile,1,y); 
          DD[pos] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,Smoothing1,Smoothing2,Factor1,RSI_Length1,Factor2,RSI_Length2,Factor3,RSI_Length3,Factor4,RSI_Length4,Factor5,RSI_Length5,Price,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsNotify,alertsEmail,soundFile,2,y);
          DU[pos] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,Smoothing1,Smoothing2,Factor1,RSI_Length1,Factor2,RSI_Length2,Factor3,RSI_Length3,Factor4,RSI_Length4,Factor5,RSI_Length5,Price,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsNotify,alertsEmail,soundFile,3,y);                  
   }
return(0); 
}


//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

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 =  StringConcatenate(timeFrameToString(_Period)+" "+Symbol()," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," Zero lag rsi ",doWhat);
             if (alertsMessage) Alert(message);
             if (alertsNotify)  SendNotification(message);
             if (alertsEmail)   SendMail(StringConcatenate(Symbol()," Zero lag rsi "),message);
             if (alertsSound)   PlaySound(soundFile);
   }
}

//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
//
//
//
//
//

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("");
}

