//------------------------------------------------------------------
//ConnorsRSI Alerts v1.1.mq4, previous version (without alerts) was ConnorsRSI.mq4
//alerts & arrows by http://forexBaron.net, 11.2013
#property copyright "mladen / alerts/arrows by forexBaron.net"
#property link      "www.forex-tsd.com"
//indicators-expert-systems-tools/14880-rsi-indicator-47.html#post626857
//------------------------------------------------------------------
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1  LimeGreen
#property indicator_level1  50.0//added
#property indicator_minimum 0 //added
#property indicator_maximum 100 //added

extern int RsiPeriod    = 3;
extern int UpDownPeriod = 2;
extern int ROCPeriod    = 100;
extern int Price        = PRICE_CLOSE;
//
extern string ahi="******* ALERT SETTINGS:";
extern int    AlertCandle            = 0;//0:current, 1:last bar, etc.
extern int    BuyAlertLevel          = 30;
extern int    SellAlertLevel         = 70;
extern bool   PopupAlerts            = true;
extern bool   EmailAlerts            = false;
extern bool   PushNotificationAlerts = false;
extern bool   SoundAlerts            = false;
extern string SoundFileLong          = "alert.wav";
extern string SoundFileShort         = "alert2.wav";
extern string arh=" --- Arrow settings: --- ";
extern bool   DisplayArrows = true;
extern int    UpArrowCode=233;//241;
extern int    DnArrowCode=234;//242;
extern color  UpArrowColor=Blue;
extern color  DnArrowColor=Red;
//
int cntUp=0,cntDn=0,arrowcnt;
int lastAlert=3;

//
double rsi[];
double prices[];
double updown[];
double roc[];
double BuyArrow[],SellArrow[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int init()
{
   IndicatorBuffers(4);
   //
   SetIndexBuffer(0,rsi); SetIndexLabel(0,"RSI");
   SetIndexStyle(0,DRAW_LINE); 
   //
   SetIndexBuffer(1,prices);
   SetIndexStyle(1,DRAW_NONE);
   //
   SetIndexBuffer(2,updown);
   SetIndexStyle(2,DRAW_NONE);
   //
   SetIndexBuffer(3,roc);
   SetIndexStyle(3,DRAW_NONE);
   //
   return(0);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int deinit()
{
 //delete arrows
 if (DisplayArrows) {
  for (arrowcnt=0;arrowcnt<=MathMax(cntUp,cntDn);arrowcnt++) {
   ObjectDelete ("UpArrowCRSI"+arrowcnt);
   ObjectDelete("DnArrowCRSI"+arrowcnt);
  }//for (...
 }//if (DisplayArrows) {
//
return(0);
}

int start()
{
   int counted_bars=IndicatorCounted();
     if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
           int limit=Bars-counted_bars;

   for(int i=limit; i>=0; i--)
   {
      prices[i] = iMA(NULL,0,1,0,MODE_SMA,Price,i);
         if (prices[i] == prices[i+1]) updown[i] = 0;
         if (prices[i] <  prices[i+1]) if (updown[i+1] > 0) updown[i] = -1; else updown[i] = updown[i+1]-1;
         if (prices[i] >  prices[i+1]) if (updown[i+1] < 0) updown[i] =  1; else updown[i] = updown[i+1]+1;
   }//for(int i=limit; i>=0; i--)
   
   for(i=limit; i>=0; i--)
   {   
      double trsi = iRSI(NULL,0,RsiPeriod,Price,i);
      double ursi = iRSIOnArray(updown,0,UpDownPeriod,i);
      roc[i]  = 0;
         if (prices[i+1]!=0) roc[i] = (prices[i]/prices[i+1]-1.0)*100.0;

         double ROC_Percent = 0;
          for (int k=1; k<=ROCPeriod; k++)
              if (roc[i] >= roc[i+k]) ROC_Percent++;
                                     ROC_Percent = (ROC_Percent / ROCPeriod) * 100;
         rsi[i] = (trsi + ursi + ROC_Percent) / 3.0;
   }////for(i=limit; i>=0; i--)
   
   for(i=limit; i>=0; i--)
   {
    if (DisplayArrows) {
     double range = (iHigh(NULL,0,i) + iLow(NULL,0,i))/2;
     //UpArrow:
     if (rsi[i] > BuyAlertLevel && rsi[i+1] < BuyAlertLevel) { 
      ObjectCreate("UpArrowCRSI"+cntUp,OBJ_ARROW,0,iTime(NULL,0,i),iLow(NULL,0,i)-2.5*(iHigh(NULL,0,i)-iLow(NULL,0,i))/3);
	   ObjectSet("UpArrowCRSI"+cntUp,OBJPROP_ARROWCODE,UpArrowCode);
	   ObjectSet("UpArrowCRSI"+cntUp,OBJPROP_WIDTH,1);
	   ObjectSet("UpArrowCRSI"+cntUp,OBJPROP_COLOR,UpArrowColor);
	   cntUp++;
	  }
	  //DnArrow:
	  if (rsi[i] < SellAlertLevel && rsi[i+1] > SellAlertLevel) {
	   ObjectCreate("DnArrowCRSI"+cntDn,OBJ_ARROW,0,iTime(NULL,0,i),iHigh(NULL,0,i)+2.5*(iHigh(NULL,0,i)-iLow(NULL,0,i))/3);
	   ObjectSet("DnArrowCRSI"+cntDn,OBJPROP_ARROWCODE,DnArrowCode);
	   ObjectSet("DnArrowCRSI"+cntDn,OBJPROP_WIDTH,1);
	   ObjectSet("DnArrowCRSI"+cntDn,OBJPROP_COLOR,DnArrowColor);
      cntDn++;
	  }
	 }//if (DisplayArrows) {
	 CheckForAlerts(i);
   }//for(i=limit; i>=0; i--)
            
   return(0);
}


//////////////////////////////////////////////////////////////////////
//added stuff by fxdaytrader:
void CheckForAlerts(int shift) {
 string msg="ConnorsRSI Alert on "+Symbol()+", period "+TFtoStr(Period())+": ";
 //Alerts:         
  if (rsi[AlertCandle] > BuyAlertLevel && rsi[AlertCandle+1] < BuyAlertLevel && lastAlert!=2) {
   doAlerts(msg+"BUY SIGNAL",SoundFileLong);
   lastAlert=2;
  }
  if (rsi[AlertCandle] < SellAlertLevel && rsi[AlertCandle+1] > SellAlertLevel && lastAlert!=1) {
   doAlerts(msg+"SELL SIGNAL",SoundFileShort);
   lastAlert=1;
  }
}

void doAlerts(string msg,string SoundFile) {
 string emailsubject="MT4 alert on acc. "+AccountNumber()+", "+WindowExpertName()+" - Alert on "+Symbol()+", period "+TFtoStr(Period());
  if (PopupAlerts) Alert(msg);
  if (EmailAlerts) SendMail(emailsubject,msg);
  if (PushNotificationAlerts) SendNotification(msg);
  if (SoundAlerts) PlaySound(SoundFile);

}//void doAlerts(string msg,string SoundFile) {

string TFtoStr(int period) {
 switch(period) {
  case 1     : return("M1");  break;
  case 5     : return("M5");  break;
  case 15    : return("M15"); break;
  case 30    : return("M30"); break;
  case 60    : return("H1");  break;
  case 240   : return("H4");  break;
  case 1440  : return("D1");  break;
  case 10080 : return("W1");  break;
  case 43200 : return("MN1"); break;
  default    : return(DoubleToStr(period,0));
 }
 return("UNKNOWN");
}//string TFtoStr(int period) {
//end stuff by fxdaytrader
//////////////////////////////////////////////////////////////////////