//------------------------------------------------------------------
// original idea for this indicator from Godfreyh
// this version by mladen
//------------------------------------------------------------------
#property indicator_separate_window
#property indicator_buffers    4
#property indicator_levelcolor DarkOrchid


extern string TimeFrame       = "Current time frame";
extern int    RsiPeriod       = 14;
extern double levelOb         = 80;
extern double levelOs         = 20;
extern bool   alertsOn        = true;
extern bool   alertsOnCurrent = false;
extern bool   alertsMessage   = true;
extern bool   alertsSound     = false;
extern bool   alertsEmail     = false;
extern color  WickColor       = Snow;
extern color  BodyUpColor     = LimeGreen;
extern color  BodyDownColor   = PaleVioletRed;
extern int    BodyWidth       = 4;
extern bool   DrawAsBack      = false;
extern string UniqueID        = "Rsi bars 1";
extern bool   HistoOnFirst    = false;

//
//
//
//
//

double trend[];
double open[];
double close[];
double high[];
double low[];

string shortName;
string indicatorFileName;
bool   calculateValue;
bool   returnBars;
int    timeFrame;
int    window;

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int init()
{
   IndicatorBuffers(5);
   SetIndexBuffer(0,open);  SetIndexStyle(0,DRAW_LINE,EMPTY,EMPTY,clrNONE);
   SetIndexBuffer(1,close); SetIndexStyle(1,DRAW_LINE,EMPTY,EMPTY,clrNONE);
   SetIndexBuffer(2,high);  SetIndexStyle(2,DRAW_LINE,EMPTY,EMPTY,clrNONE);
   SetIndexBuffer(3,low);   SetIndexStyle(3,DRAW_LINE,EMPTY,EMPTY,clrNONE);
   SetIndexBuffer(4,trend);
   SetLevelValue(0,levelOb);
   SetLevelValue(1,levelOs);
   
     //
     //
     //
     //
     //
      
     indicatorFileName = WindowExpertName();
     returnBars        = (TimeFrame=="returnBars");     if (returnBars)     return(0);
     calculateValue    = (TimeFrame=="calculateValue"); 
     if (calculateValue)
     {
         int s = StringFind(UniqueID,":",0);
               shortName = UniqueID;
               UniqueID  = StringSubstr(UniqueID,0,s);
               return(0);
     } 
     timeFrame = stringToTimeFrame(TimeFrame); 
            
     //
     //
     //
     //
     //

   shortName = UniqueID+": "+timeFrameToString(timeFrame)+ "  rsi bar chart";
   IndicatorShortName(shortName);
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 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)  { open[0] = limit+1; return(0); }
           window = WindowFind(shortName);

   //
   //
   //
   //
   //
   
   if (calculateValue || timeFrame == Period())
   {
     for (int i=limit; i>=0; i--)
     {
        open[i]  = iRSI(NULL,0,RsiPeriod,PRICE_OPEN ,i);
        close[i] = iRSI(NULL,0,RsiPeriod,PRICE_CLOSE,i);
        high[i]  = iRSI(NULL,0,RsiPeriod,PRICE_HIGH ,i);
        low[i]   = iRSI(NULL,0,RsiPeriod,PRICE_LOW  ,i);
        drawCandle(i);
        trend[i] = trend[i+1];
            if (close[i] < levelOs) trend[i] =  1;
            if (close[i] > levelOb) trend[i] = -1;    
         
      }
      manageAlerts();
      return(0);
   }
   
   //
   //
   //
   //
   //
   
   int displace = -1; if (HistoOnFirst) displace = 1;
   limit = MathMax(limit,MathMin(Bars,iCustom(NULL,timeFrame,indicatorFileName,"returnBars",0,0)*timeFrame/Period()));
   for(i = limit; i >= 0; i--)
   {
      int y = iBarShift(NULL,timeFrame,Time[i]);
      int x = iBarShift(NULL,timeFrame,Time[i+displace]);
         trend[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",RsiPeriod,levelOb,levelOs,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,5,y); 
         if (x!=y)
         { 
           open[i]  = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",RsiPeriod,levelOb,levelOs,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,0,y);
           close[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",RsiPeriod,levelOb,levelOs,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,1,y);
           high[i]  = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",RsiPeriod,levelOb,levelOs,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,2,y);
           low[i]   = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",RsiPeriod,levelOb,levelOs,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,3,y);
           drawCandle(i);
         }
   }
   return(0);         
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

int stringToTimeFrame(string tfs)
{
   StringToUpper(tfs);
   for (int i=ArraySize(iTfTable)-1; i>=0; i--)
         if (tfs==sTfTable[i] || tfs==""+iTfTable[i]) return(MathMax(iTfTable[i],Period()));
                                                      return(Period());
}
string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}

//
//
//
//
//

void manageAlerts()
{
   if (alertsOn)
   {
      if (alertsOnCurrent)
           int whichBar = 0;
      else     whichBar = 1;
      if (trend[whichBar] != trend[whichBar+1])
      {
         if (trend[whichBar] == 1) doAlert(whichBar,"buy");
         if (trend[whichBar] ==-1) doAlert(whichBar,"sell");
      }         
   }
}   

//
//
//
//
//

void doAlert(int forBar, string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
   if (previousAlert != doWhat || previousTime != Time[forBar]) {
       previousAlert  = doWhat;
       previousTime   = Time[forBar];

       //
       //
       //
       //
       //

       message =  StringConcatenate(Symbol()," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," - ",timeFrameToString(_Period)+" Rsi bar chart  ",doWhat);
          if (alertsMessage) Alert(message);
          if (alertsEmail)   SendMail(StringConcatenate(Symbol()," Rsi bar chart "),message);
          if (alertsSound)   PlaySound("alert2.wav");
   }
}


  
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
  
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,MathMax(high[i],MathMin(close[i],open[i])));
         ObjectSet(name,OBJPROP_PRICE2,MathMin(low[i] ,MathMax(close[i],open[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);
}