//------------------------------------------------------------------
#property copyright "www.forex-tsd.com"
#property link      "www.forex-tsd.com"
//------------------------------------------------------------------
#property indicator_separate_window
#property indicator_buffers 8

#property indicator_level4 20

#property indicator_level3 80
#property indicator_levelstyle STYLE_DOT
#property indicator_levelcolor DimGray
#property indicator_minimum 0
#property indicator_maximum 100
//
//
//
//
//
extern string TimeFrame        = "current time frame";
extern string Symbols         = "EURUSD;USDJPY;GBPUSD;USDCAD;USDCHF";
extern string SymbolsPrefix   = "";
extern string SymbolsSuffix   = "";
extern int    RsiPeriod       = 8;
extern int    RsiPrice        = PRICE_TYPICAL;
extern color  Color1          = HotPink;
extern color  Color2          = Magenta;
extern color  Color3          = Red;
extern color  Color4          = Lime;
extern color  Color5          = DodgerBlue;
extern color  Color6          = White;
extern color  Color7          = DodgerBlue;
extern color  Color8          = Pink;
extern int    LinesWidth      = 2;
extern double LevelUp         = 60;
extern double LevelDown       = 40;
extern bool   alertsOn        = false;
extern bool   alertsOnCurrent  = true;
extern bool   alertsOnBreakout = true;
extern bool   alertsOnRetrace  = true;
extern bool   alertsMessage    = true;
extern bool   alertsSound      = false;
extern bool   alertsEmail      = false;
extern string UniqueID         = " RSI";

//
//
//
//
//

double buffer0[];
double buffer1[];
double buffer2[];
double buffer3[];
double buffer4[];
double buffer5[];
double buffer6[];
double buffer7[];

//
//
//
//
//

string indicatorFileName;
bool   returnBars;
int    timeFrame;
string symbols[];
int    size;

//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
//
//
//
//

int init()
{
   SetIndexBuffer(0,buffer0);
   SetIndexBuffer(1,buffer1);
   SetIndexBuffer(2,buffer2);
   SetIndexBuffer(3,buffer3);
   SetIndexBuffer(4,buffer4);
   SetIndexBuffer(5,buffer5);
   SetIndexBuffer(6,buffer6);
   SetIndexBuffer(7,buffer7);

      //
      //
      //
      //
      //
      
      returnBars  = (Symbols ==  "returnBars"); if (returnBars) return(0);
      Symbols = StringTrimLeft(StringTrimRight(Symbols));
      if (StringSubstr(Symbols,StringLen(Symbols),1) != ";")
                       Symbols = StringConcatenate(Symbols,";");

         //
         //
         //
         //
         //                                   
            
         int s =  0;
         int i =  StringFind(Symbols,";",s);
         while (i > 0)
         {
            string current = StringSubstr(Symbols,s,i-s);
            ArrayResize(symbols,ArraySize(symbols)+1);
                        symbols[ArraySize(symbols)-1] = current;
            s = i + 1;
            i = StringFind(Symbols,";",s);
         }
         size = MathMin(ArraySize(symbols),8);
         
         //
         //
         //
         //
         //
         
         for (i=0; i<size; i++) symbols[i] = SymbolsPrefix+symbols[i]+SymbolsSuffix;
         timeFrame         = stringToTimeFrame(TimeFrame);
         indicatorFileName = WindowExpertName();
      
      //
      //
      //
      //
      //

   SetLevelValue(0,LevelUp);            
   SetLevelValue(1,LevelDown);            
  
   
   UniqueID = timeFrameToString(timeFrame)+" "+UniqueID;            
   IndicatorShortName(UniqueID);
 
   return(0);
}

//
//
//
//
//

int deinit()
{
   for(int i = 0; i < 8; i++) ObjectDelete(UniqueID+ i);
   return (0);
}

//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
//
//
//
//
//

double values[8];
double trends[][8];
int start()
{
   int i,k,r,y,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) { buffer0[0] = limit+1; return(0); }
         
            //
            //
            //
            //
            //
            
            static bool initialized = false;
            if (!initialized)
            {
               initialized = true;
               int cur = 10; 
               int cuy = 10; 
               int st  = 16;
                  if (size>0) { sl(0,"~",cur,cuy,Color1,symbols[0]); cuy += st; }
                  if (size>1) { sl(1,"~",cur,cuy,Color2,symbols[1]); cuy += st; }
                  if (size>2) { sl(2,"~",cur,cuy,Color3,symbols[2]); cuy += st; }
                  if (size>3) { sl(3,"~",cur,cuy,Color4,symbols[3]); cuy += st; }
                  if (size>4) { sl(4,"~",cur,cuy,Color5,symbols[4]); cuy += st; }
                  if (size>5) { sl(5,"~",cur,cuy,Color6,symbols[5]); cuy += st; }
                  if (size>6) { sl(6,"~",cur,cuy,Color7,symbols[6]); cuy += st; }
                  if (size>7) { sl(7,"~",cur,cuy,Color8,symbols[7]); cuy += st; }
            }
            if (ArrayRange(trends,0) != Bars) ArrayResize(trends,Bars);

   //
   //
   //
   //
   //

  for (i=0; i<size; i++) if (symbols[i]!=Symbol() || timeFrame!=Period()) limit = MathMax(limit,MathMin(Bars-1,iCustom(symbols[i],timeFrame,indicatorFileName,"","returnBars",0,0)));
   for(i=limit, r=Bars-i-1; i>=0; i--,r++)
   {
      for (k=0; k<size; k++)
      {
         y = iBarShift(symbols[k],timeFrame,Time[i]); 
         double rsi = iRSI(symbols[k],timeFrame,RsiPeriod,RsiPrice,y);
         switch(k)
         {
            case 0 : buffer0[i] = rsi; break;
            case 1 : buffer1[i] = rsi; break;
            case 2 : buffer2[i] = rsi; break;
            case 3 : buffer3[i] = rsi; break;
            case 4 : buffer4[i] = rsi; break;
            case 5 : buffer5[i] = rsi; break;
            case 6 : buffer6[i] = rsi; break;
            case 7 : buffer7[i] = rsi; break;
         }            
         values[k] = rsi;
      }
      for (k=0;   k<size; k++)
      {
         trends[r][k] = 0;
           if (values[k]>LevelUp)   trends[r][k] =   1;
           if (values[k]<LevelDown) trends[r][k] =  -1;
      }
   }   
   manageAlerts();  
   return(0);
}

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

datetime times[8];
string   kinds[8];
void manageAlerts()
{
   if (alertsOn)
   {
      if (alertsOnCurrent)
           int whichBar = 0;
      else     whichBar = 1; whichBar = Bars-whichBar-1;
      
      //
      //
      //
      //
      //
      
      for (int k=0; k<size; k++)
         if (trends[whichBar][k] != trends[whichBar-1][k])
         {
            if (alertsOnBreakout)
            {
               if (trends[whichBar][k] ==  1) doAlert(k,symbols[k]+" rsi crossed "+DoubleToStr(LevelUp,2)  +" up");
               if (trends[whichBar][k] == -1) doAlert(k,symbols[k]+" rsi crossed "+DoubleToStr(LevelDown,2)+" down");
            }
            if (alertsOnRetrace)
            {
               if (trends[whichBar][k] == 0 && trends[whichBar-1][k] ==  1) doAlert(k,symbols[k]+" rsi crossed "+DoubleToStr(LevelUp,2)  +" down");
               if (trends[whichBar][k] == 0 && trends[whichBar-1][k] == -1) doAlert(k,symbols[k]+" rsi crossed "+DoubleToStr(LevelDown,2)+" up");
            }
         }         
   }
}

//
//
//
//
//

void doAlert(int forWhat, string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
   if (kinds[forWhat] != doWhat || times[forWhat] != Time[0]) {
       kinds[forWhat]  = doWhat;
       times[forWhat]  = Time[0];

       //
       //
       //
       //
       //

       message =  StringConcatenate(TimeToStr(TimeLocal(),TIME_SECONDS)," "+doWhat);
          if (alertsMessage) Alert(message);
          if (alertsEmail)   SendMail(StringConcatenate(Symbol(),"Multi symbols rsi"),message);
          if (alertsSound)   PlaySound("alert2.wav");
   }
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

void sl(int buffNo, string sym, int x, int y, color col, string buffLabel)
{
   int    window = WindowFind(UniqueID);
   string ID = UniqueID + buffNo;
   
      if(ObjectCreate(ID, OBJ_LABEL, window, 0, 0))
            ObjectSet(ID, OBJPROP_CORNER, 1);
            ObjectSet(ID, OBJPROP_XDISTANCE, x);
            ObjectSet(ID, OBJPROP_YDISTANCE, y);
            ObjectSetText(ID, buffLabel, 10, "Arial Bold", col);

   SetIndexStyle(buffNo,DRAW_LINE,STYLE_SOLID,LinesWidth,col);
   SetIndexLabel(buffNo,buffLabel);
}

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)
{
   tfs = stringUpperCase(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("");
}

//
//
//
//
//

string stringUpperCase(string str)
{
   string   s = str;

   for (int length=StringLen(str)-1; length>=0; length--)
   {
      int tchar = StringGetChar(s, length);
         if((tchar > 96 && tchar < 123) || (tchar > 223 && tchar < 256))
                     s = StringSetChar(s, length, tchar - 32);
         else if(tchar > -33 && tchar < 0)
                     s = StringSetChar(s, length, tchar + 224);
   }
   return(s);
}
