//------------------------------------------------------------------
#property copyright "www.forex-tsd.com"
#property link      "www.forex-tsd.com"
//------------------------------------------------------------------
#property indicator_separate_window
#property indicator_buffers 7
#property indicator_color5  PaleVioletRed
#property indicator_color6  DimGray
#property indicator_color7  LimeGreen
#property indicator_style5  STYLE_DOT
#property indicator_style6  STYLE_DOT
#property indicator_style7  STYLE_DOT

//
//
//
//
//

extern int    RsiPeriod       = 14;
extern int    RsiDepth        = 10;
extern bool   RsiFast         = false;
extern int    AtrPeriod       = 10;
extern double AtrMultiplier   = 2.0;
extern int    AtrAveragePrice = 0;
extern int    DrawBars        = 500;
extern color  WickColor       = Gray;
extern color  BodyUpColor     = LimeGreen;
extern color  BodyDownColor   = Orange;
extern int    BodyWidth       = 4;
extern bool   DrawAsBack      = true;
extern string UniqueID        = "RSI bars 2";

//
//
//
//
//

double open[];
double close[];
double high[];
double low[];
double atrup[];
double atrmi[];
double atrdn[];
double atr[];
int    window;

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int init()
{
   IndicatorBuffers(8);
   SetIndexBuffer(0,open);  SetIndexStyle(0,DRAW_NONE);
   SetIndexBuffer(1,close); SetIndexStyle(1,DRAW_NONE);
   SetIndexBuffer(2,high);  SetIndexStyle(2,DRAW_NONE);
   SetIndexBuffer(3,low);   SetIndexStyle(3,DRAW_NONE);
   SetIndexBuffer(4,atrup);
   SetIndexBuffer(5,atrmi);
   SetIndexBuffer(6,atrdn);
   SetIndexBuffer(7,atr);
	IndicatorShortName(UniqueID); 
   return(0);
}

//
//
//
//
//

int deinit()
{
   string lookFor       = UniqueID+":";
   int    lookForLength = StringLen(lookFor);
   for (int i=ObjectsTotal()-1; i>=0; i--)
   {
      string objectName = ObjectName(i); if (StringSubstr(objectName,0,lookForLength) == lookFor) ObjectDelete(objectName);
   }
   return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//

int start()
{
   int countedBars = IndicatorCounted();
      if (countedBars<0) return(-1);
      if (countedBars>0) countedBars--;
         int drawBars = DrawBars; if (drawBars<1) drawBars = Bars;
         int limit = MathMin(Bars-countedBars,Bars-1);
            window = WindowFind(UniqueID);

   //
   //
   //
   //
   //
   
   for (int i=limit; i>=0; i--)
   {
      double topen    = iCompRsi(iMA(NULL,0,1,0,MODE_SMA,PRICE_OPEN ,i),RsiPeriod,RsiDepth,RsiFast,i,0);
      double tclose   = iCompRsi(iMA(NULL,0,1,0,MODE_SMA,PRICE_CLOSE,i),RsiPeriod,RsiDepth,RsiFast,i,1);
      double thigh    = iCompRsi(iMA(NULL,0,1,0,MODE_SMA,PRICE_HIGH ,i),RsiPeriod,RsiDepth,RsiFast,i,2);
      double tlow     = iCompRsi(iMA(NULL,0,1,0,MODE_SMA,PRICE_LOW  ,i),RsiPeriod,RsiDepth,RsiFast,i,3);
             open[i]  = topen;
             close[i] = tclose;
             high[i]  = MathMax(MathMax(thigh,tlow),MathMax(topen,tclose));
             low[i]   = MathMin(MathMin(thigh,tlow),MathMin(topen,tclose));
             atr[i]   = MathMax(high[i],close[i+1])-MathMin(low[i],close[i+1]);
             if (i<drawBars)
             {
                  drawCandle(i);
                  if (AtrPeriod>1)
                  {
                     double avga = atr[i];
                     double avgp = getPrice(AtrAveragePrice,i);
                     for (int k=1; k<AtrPeriod && (i+k)<Bars; k++)
                     {
                        avga += atr[i+k];
                        avgp += getPrice(AtrAveragePrice,i+k);
                     }
                     avga /= (k*1.0);                     
                     avgp /= (k*1.0);                     
                     atrmi[i] = avgp;
                     atrup[i] = avgp+avga*AtrMultiplier;
                     atrdn[i] = avgp-avga*AtrMultiplier;
                  }                     
             }
   }
   return(0);
}


//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double getPrice(int type, int i)
{
   switch (type)
   {
      case 0:   return(close[i]);
      case 1:   return(open[i]);
      case 2:   return(high[i]);
      case 3:   return(low[i]);
      case 4:   return((high[i]+low[i])/2.0);
      case 5:   return((high[i]+low[i]+close[i])/3.0);
      case 6:   return((high[i]+low[i]+close[i]+close[i])/4.0);
   }
   return(close[i]);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double workCompRsi[][104];

//
//
//
//
//

double iCompRsi(double price, double period, int depth, bool fast, int i, int instanceNo=0)
{
   if (ArrayRange(workCompRsi,0) !=Bars) ArrayResize(workCompRsi,Bars);
   if (!fast)
        double alpha = 2.0/(1.0 + period);
   else        alpha = 2.0/(2.0 + (period-1.0)/2.0);
   instanceNo *= 26; i = Bars-i-1;
   
   //
   //
   //
   //
   //
   
   double CU = 0;
   double CD = 0;
   for (int k=0; k<=depth; k++)
   {
      if (i == 0)
            workCompRsi[i][instanceNo+k] = price;
      else  workCompRsi[i][instanceNo+k] = workCompRsi[i-1][instanceNo+k]+alpha*(price-workCompRsi[i-1][instanceNo+k]);

      //
      //
      //
      //
      //
         
      price = workCompRsi[i][k+instanceNo];
      if (k>0)
         if (workCompRsi[i][instanceNo+k-1] >= workCompRsi[i][instanceNo+k])
              CU += workCompRsi[i][instanceNo+k-1] - workCompRsi[i][instanceNo+k  ];
         else CD += workCompRsi[i][instanceNo+k  ] - workCompRsi[i][instanceNo+k-1];
   }
   double rsi = 0; if (CU + CD != 0) rsi = CU / (CU + CD); 
   return(rsi);
}



//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
  
void drawCandle(int i)
{
   datetime time = Time[i];
   string   name = UniqueID+":"+time+":";
   
      ObjectCreate(name,OBJ_TREND,window,0,0,0,0);
         ObjectSet(name,OBJPROP_COLOR,WickColor);
         ObjectSet(name,OBJPROP_TIME1,time);
         ObjectSet(name,OBJPROP_TIME2,time);
         ObjectSet(name,OBJPROP_PRICE1,high[i]);
         ObjectSet(name,OBJPROP_PRICE2,low[i]);
         ObjectSet(name,OBJPROP_RAY ,false);
         ObjectSet(name,OBJPROP_BACK,DrawAsBack);
      
   //
   //
   //
   //
   //
         
   name = name+"body";
      ObjectCreate(name,OBJ_TREND,window,0,0,0,0);
         ObjectSet(name,OBJPROP_TIME1,time);
         ObjectSet(name,OBJPROP_TIME2,time);
         ObjectSet(name,OBJPROP_PRICE1,open[i]);
         ObjectSet(name,OBJPROP_PRICE2,close[i]);
         ObjectSet(name,OBJPROP_WIDTH,BodyWidth);
         ObjectSet(name,OBJPROP_RAY  ,false);
         ObjectSet(name,OBJPROP_BACK,DrawAsBack);
         if (open[i]<close[i])
               ObjectSet(name,OBJPROP_COLOR,BodyUpColor);
         else  ObjectSet(name,OBJPROP_COLOR,BodyDownColor);
}