//------------------------------------------------------------------
#property copyright "mladen"
#property link      "www.forex-station.com"
//------------------------------------------------------------------
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_color1  DarkGray
#property indicator_color2  DarkGray
#property indicator_color3  DarkGray
#property indicator_color4  LimeGreen
#property indicator_color5  Orange
#property indicator_color6  Orange
#property indicator_width4  2
#property indicator_width5  2
#property indicator_width6  2
#property indicator_style1  STYLE_DOT
#property indicator_style2  STYLE_DOT
#property indicator_style3  STYLE_DOT

//
//
//
//
//

extern ENUM_TIMEFRAMES    TimeFrame    = PERIOD_CURRENT;
extern int                RsiPeriod    = 14;
extern double             FastEma      = 12;
extern double             SlowEma      = 26;
extern ENUM_APPLIED_PRICE Price        = PRICE_CLOSE;
extern int                MinMaxPeriod = 25;
extern int                overBought   = 70;
extern int                overSold     = 30;
extern bool               Interpolate  = true;

//
//
//
//
//

double bandu[];
double bandm[];
double bandd[];
double rsi[];
double buffer2[];
double buffer3[];
double macd[];
double trend[];

//
//
//
//
//

string indicatorFileName;
bool   returnBars;

//
//
//------------------------------------------------------------------
//
//------------------------------------------------------------------

int init()
{
   IndicatorBuffers(8);
   SetIndexBuffer(0,bandu);
   SetIndexBuffer(1,bandm);
   SetIndexBuffer(2,bandd);
   SetIndexBuffer(3,rsi);
   SetIndexBuffer(4,buffer2);
   SetIndexBuffer(5,buffer3);
   SetIndexBuffer(6,macd);
   SetIndexBuffer(7,trend);
      
      //
      //
      //
      //
      //
      
      indicatorFileName = WindowExpertName();
      returnBars        = TimeFrame==-99;
      TimeFrame         = MathMax(TimeFrame,_Period);
      
      //
      //
      //
      //
      //
               
   IndicatorShortName(timeFrameToString(TimeFrame)+"   RSI of MACD");
   return(0);
}
int deinit()
{
   return(0);
}


//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double work[][2];
#define _fastEma 0
#define _slowEma 1

int start() 
{
   int i,r,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) { bandu[0] = MathMin(limit+1,Bars-1); return(0); }
      
   //
   //
   //
   //
   //
   
   if (TimeFrame == Period())
   {
      if (trend[limit]==-1) CleanPoint(limit,buffer2,buffer3);
      if (ArrayRange(work,0)!=Bars) ArrayResize(work,Bars);
      double alphaF = 2.0/(1.0+FastEma);
      double alphaS = 2.0/(1.0+SlowEma);
      for(i=limit, r=Bars-i-1; i>=0; i--,r++)
      {
         double price = iMA(NULL,0,1,0,MODE_SMA,Price,i);
            work[r][_fastEma] = work[r-1][_fastEma]+alphaF*(price-work[r-1][_fastEma]);
            work[r][_slowEma] = work[r-1][_slowEma]+alphaS*(price-work[r-1][_slowEma]);
            macd[i] = work[r][_fastEma]-work[r][_slowEma];
      }
      for(i=limit; i>=0; i--)
      {
         double min   =  Low[ArrayMinimum(Low, MinMaxPeriod,i)];
         double max   = High[ArrayMaximum(High,MinMaxPeriod,i)];
         double range = max-min;
         double trsi  = iRSIOnArray(macd,0,RsiPeriod,i);
                bandm[i] = (max+min)/2;
                bandu[i] = (min+range*(overBought)/100);
                bandd[i] = (min+range*(overSold)/100);
                rsi[i]   = (min+range*(trsi)/100);
                buffer2[i] = EMPTY_VALUE;
                buffer3[i] = EMPTY_VALUE;
                trend[i]   = trend[i+1];
                if (rsi[i]>rsi[i+1]) trend[i] = 1;
                if (rsi[i]<rsi[i+1]) trend[i] =-1; 
                if (trend[i]==-1) PlotPoint(i,buffer2,buffer3,rsi);       
      }             
      return(0);
   }
   
   //
   //
   //
   //
   //

   limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,TimeFrame,indicatorFileName,-99,0,0)*TimeFrame/Period()));
   if (trend[limit]==-1) CleanPoint(limit,buffer2,buffer3);
   for (i=limit; i>=0; i--)
   {
      int y = iBarShift(NULL,TimeFrame,Time[i]);
         bandu[i] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,RsiPeriod,FastEma,SlowEma,Price,MinMaxPeriod,overBought,overSold,0,y);
         bandm[i] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,RsiPeriod,FastEma,SlowEma,Price,MinMaxPeriod,overBought,overSold,1,y);
         bandd[i] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,RsiPeriod,FastEma,SlowEma,Price,MinMaxPeriod,overBought,overSold,2,y);
         rsi[i]   = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,RsiPeriod,FastEma,SlowEma,Price,MinMaxPeriod,overBought,overSold,3,y);
         trend[i] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,RsiPeriod,FastEma,SlowEma,Price,MinMaxPeriod,overBought,overSold,7,y);
         buffer2[i] = EMPTY_VALUE;
         buffer3[i] = EMPTY_VALUE;
            if (!Interpolate || y==iBarShift(NULL,TimeFrame,Time[i-1])) continue;

            //
            //
            //
            //
            //

            datetime time = iTime(NULL,TimeFrame,y);
               for(int n = 1; i+n < Bars && Time[i+n] >= time; n++) continue;	
               for(int j = 1; j < n; j++)
               {
                  bandu[i+j] = bandu[i] + (bandu[i+n]-bandu[i])*j/n;
                  bandm[i+j] = bandm[i] + (bandm[i+n]-bandm[i])*j/n;
                  bandd[i+j] = bandd[i] + (bandd[i+n]-bandd[i])*j/n;
                  rsi[i+j] = rsi[i] + (rsi[i+n]-rsi[i])*j/n;
               }
   }
   for (i=limit;i>=0;i--) if (trend[i]==-1) PlotPoint(i,buffer2,buffer3,rsi);
   return(0);
}

//-------------------------------------------------------------------
//
//-------------------------------------------------------------------
//
//
//
//
//

void CleanPoint(int i,double& first[],double& second[])
{
   if ((second[i]  != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE))
        second[i+1] = EMPTY_VALUE;
   else
      if ((first[i] != EMPTY_VALUE) && (first[i+1] != EMPTY_VALUE) && (first[i+2] == EMPTY_VALUE))
          first[i+1] = EMPTY_VALUE;
}

//
//
//
//
//

void PlotPoint(int i,double& first[],double& second[],double& from[])
{
   if (first[i+1] == EMPTY_VALUE)
      {
         if (first[i+2] == EMPTY_VALUE) {
                first[i]   = from[i];
                first[i+1] = from[i+1];
                second[i]  = EMPTY_VALUE;
            }
         else {
                second[i]   =  from[i];
                second[i+1] =  from[i+1];
                first[i]    = EMPTY_VALUE;
            }
      }
   else
      {
         first[i]  = from[i];
         second[i] = EMPTY_VALUE;
      }
}

//-------------------------------------------------------------------
//
//-------------------------------------------------------------------
//
//
//
//
//

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("");
}