#property indicator_separate_window
#property indicator_buffers    5
#property indicator_color1     clrGreen
#property indicator_color2     clrAqua
#property indicator_color3     clrYellow
#property indicator_color4     clrLime
#property indicator_color5     clrRed
#property indicator_width1     1
#property indicator_width2     1
#property indicator_width3     1
#property indicator_width4     2
#property indicator_width5     2
#property indicator_levelcolor clrDimGray

//
//
//
//
//

extern int    RSIsmoothing           = 5;
extern int    RSIPeriod              = 6;
extern double WP                     = 4.236;
extern double UpperBound             = 60; 
extern double LowerBound             = 40; 

extern string _                      = "Alerts Settings";
extern bool   alertsOn               = true;
extern bool   alertsOnZeroCross      = false;
extern bool   alertsOnSignalCross    = true;
extern bool   alertsOnCurrent        = false;
extern bool   alertsMessage          = true;
extern bool   alertsSound            = true;
extern bool   alertsNotify           = false;
extern bool   alertsEmail            = false;
extern string soundFile              = "alert2.wav"; 

extern bool   arrowsVisible          = true;
extern string arrowsIdentifier       = "qqe Arrows1";
extern double arrowsDisplacement     = 1.0;

extern bool   arrowsOnZeroCross      = false;
extern color  arrowsUpZeroCrossColor = clrDeepSkyBlue;
extern color  arrowsDnZeroCrossColor = clrRed;
extern int    arrowsUpZeroCrossCode  = 233;
extern int    arrowsDnZeroCrossCode  = 234;
extern int    arrowsUpZeroCrossSize  = 1;
extern int    arrowsDnZeroCrossSize  = 1;

extern bool   arrowsOnSignalCross    = true;
extern color  arrowsUpSignalColor    = clrLime;
extern color  arrowsDnSignalColor    = clrRed;
extern int    arrowsUpSignalCode     = 241;
extern int    arrowsDnSignalCode     = 242;
extern int    arrowsUpSignalSize     = 3;
extern int    arrowsDnSignalSize     = 3;
extern string             button_note1          = "------------------------------";
extern ENUM_BASE_CORNER   btn_corner            = CORNER_RIGHT_LOWER;
extern string             btn_text              = "QQE";
extern string             btn_Font              = "Arial";
extern int                btn_FontSize          = 8;                            
extern color              btn_text_ON_color     = clrWhite;
extern color              btn_text_OFF_color    = clrRed;
extern string             btn_pressed           = "QQE off";            
extern string             btn_unpressed         = "QQE on";
extern color              btn_background_color  = clrDimGray;
extern color              btn_border_color      = clrDarkGray;
extern int                button_x              = 190;                                 
extern int                button_y              = 21;                                   
extern int                btn_Width             = 60;                                 
extern int                btn_Height            = 20;                                
extern string             soundBT               = "tick.wav";  
extern string             button_note2          = "------------------------------";

bool                      show_data             = true;
string IndicatorName, IndicatorObjPrefix ,buttonId ;
//
//
//
//
//

double RsiMa[];
double Trend[];
double HistoU[];
double HistoM[];
double HistoD[];
double trend1[];
double trend2[];
double work[][4];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//
string GenerateIndicatorName(const string target)
{
   string name = target;
   int try = 2;
   while (WindowFind(name) != -1)
   {
      name = target + " #" + IntegerToString(try++);
   }
   return name;
}
int init()
{
   IndicatorBuffers(7);
   SetIndexBuffer(0,HistoU); SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,HistoM); SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(2,HistoD); SetIndexStyle(2,DRAW_HISTOGRAM);
   SetIndexBuffer(3,RsiMa);  SetIndexLabel(0, "QQE");
   SetIndexBuffer(4,Trend);  SetIndexLabel(1, "QQE trend");
   SetIndexBuffer(5,trend1); 
   SetIndexBuffer(6,trend2); 
      SetLevelValue(0,UpperBound-50);
      SetLevelValue(1,LowerBound-50);
      SetLevelValue(2,0);
            IndicatorName = GenerateIndicatorName(btn_text);
   IndicatorObjPrefix = "__" + IndicatorName + "__";
 //  IndicatorShortName(WindowExpertName());
   IndicatorDigits(Digits);
      double val;
   if (GlobalVariableGet(IndicatorName + "_visibility", val))
   show_data = val != 0;

   ChartSetInteger(ChartID(), CHART_EVENT_MOUSE_MOVE, 1);
   buttonId = IndicatorObjPrefix+btn_text;
   createButton(buttonId, btn_text, btn_Width, btn_Height, btn_Font, btn_FontSize, btn_background_color, btn_border_color, btn_text_ON_color);
   ObjectSetInteger(ChartID(), buttonId, OBJPROP_YDISTANCE, button_y);
   ObjectSetInteger(ChartID(), buttonId, OBJPROP_XDISTANCE, button_x);
   
   return(0);
}

void createButton(string buttonID,string buttonText,int width,int height,string font,int fontSize,color bgColor,color borderColor,color txtColor)
{
    //  ObjectDelete    (ChartID(),buttonID);
      ObjectCreate (ChartID(),buttonID,OBJ_BUTTON,WindowOnDropped(),0,0);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_COLOR,txtColor);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_BGCOLOR,bgColor);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_BORDER_COLOR,borderColor);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_XSIZE,width);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_YSIZE,height);
      ObjectSetString (ChartID(),buttonID,OBJPROP_FONT,font);
      ObjectSetString (ChartID(),buttonID,OBJPROP_TEXT,buttonText);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_FONTSIZE,fontSize);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_SELECTABLE,0);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_CORNER,btn_corner);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_HIDDEN,1);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_XDISTANCE,9999);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_YDISTANCE,9999);
}

int deinit() 
{  
ObjectsDeleteAll(0,"QQE");
   ObjectsDeleteAll(ChartID(), IndicatorObjPrefix);
   deleteArrows(); 
   
return(0); 
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
 bool recalc = true;
 void handleButtonClicks()
{
   if (ObjectGetInteger(ChartID(), buttonId, OBJPROP_STATE))
   {
      ObjectSetInteger(ChartID(), buttonId, OBJPROP_STATE, false);
      show_data = !show_data;
      GlobalVariableSet(IndicatorName + "_visibility", show_data ? 1.0 : 0.0);
      recalc = true;
      start();
   }
}
void OnChartEvent(const int id, 
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   handleButtonClicks();
   if (id==CHARTEVENT_OBJECT_CLICK && ObjectGet(sparam,OBJPROP_TYPE)==OBJ_BUTTON)
   {
   if (soundBT!="") PlaySound(soundBT);     
   }
}

//
//
//
//

#define iEma 0
#define iEmm 1
#define iQqe 2
#define iRsi 3
int start()
{
handleButtonClicks();
   recalc = false;
   
   
         SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexStyle(2,DRAW_HISTOGRAM);
    SetIndexStyle(3,DRAW_LINE);
    SetIndexStyle(4,DRAW_LINE);
   
   start2();
   
  
   
      
   
   if (show_data)
      {
      ObjectSetInteger(ChartID(),buttonId,OBJPROP_COLOR,btn_text_ON_color);
      ObjectSetString(ChartID(),buttonId,OBJPROP_TEXT,btn_unpressed);
     
      }
      else
      {
      ObjectSetInteger(ChartID(),buttonId,OBJPROP_COLOR,btn_text_OFF_color);
      ObjectSetString(ChartID(),buttonId,OBJPROP_TEXT,btn_pressed);
      
           SetIndexStyle(0,DRAW_NONE);
   SetIndexStyle(1,DRAW_NONE);
   SetIndexStyle(2,DRAW_NONE);
    SetIndexStyle(3,DRAW_NONE);
    SetIndexStyle(4,DRAW_NONE);
  
       
      
      
   
      //template code     
      }
       return(0);
      }
//
//
//
//
//

int start2()
{
   int counted_bars=IndicatorCounted();
   int i,r,limit;
   
   if(counted_bars < 0) return(-1);
   if(counted_bars > 0) counted_bars--;
           limit = MathMin(Bars-counted_bars,Bars-1);
           if (ArrayRange(work,0) != Bars) ArrayResize(work,Bars); 

   //
   //
   //
   //
   //

   double alpha1 = 2.0/(RSIsmoothing+1.0);
   double alpha2 = 2.0/(RSIPeriod*2.0);
      
   for (i=limit, r=Bars-i-1; i>=0; i--,r++)
   {  
      work[r][iRsi] = work[r-1][iRsi] + alpha1*(iRSI(NULL,0,RSIPeriod,PRICE_CLOSE,i)   - work[r-1][iRsi]);
      work[r][iEma] = work[r-1][iEma] + alpha2*(MathAbs(work[r-1][iRsi]-work[r][iRsi]) - work[r-1][iEma]);
      work[r][iEmm] = work[r-1][iEmm] + alpha2*(work[r][iEma] - work[r-1][iEmm]);

      //
      //
      //
      //
      //

         double rsi0 = work[r  ][iRsi];
         double rsi1 = work[r-1][iRsi];
         double dar  = work[r  ][iEmm]*WP;
         double tr   = work[r-1][iQqe];
         double dv   = tr;
   
            if (rsi0 < tr) { tr = rsi0 + dar; if ((rsi1 < dv) && (tr > dv)) tr = dv; }
            if (rsi0 > tr) { tr = rsi0 - dar; if ((rsi1 > dv) && (tr < dv)) tr = dv; }
         
      //
      //
      //
      //
      //
         
         work[r][iQqe] = tr;
         trend1[i]     = trend1[i+1];
         trend2[i]     = trend2[i+1];
         RsiMa[i]      = work[r][iRsi]-50;
         Trend[i]      = tr           -50;
         HistoU[i]     =  EMPTY_VALUE;
         HistoM[i]     =  EMPTY_VALUE;
         HistoD[i]     =  EMPTY_VALUE;
   
         if (RsiMa[i] > (UpperBound-50))                           HistoU[i] = RsiMa[i];
         if (RsiMa[i] < (LowerBound-50))                           HistoD[i] = RsiMa[i];
         if (HistoU[i] == EMPTY_VALUE && HistoD[i] == EMPTY_VALUE) HistoM[i] = RsiMa[i];

      //
      //
      //
      //
      //
               
         if (RsiMa[i] > 0)        trend1[i] =  1;
         if (RsiMa[i] < 0)        trend1[i] = -1;
         if (RsiMa[i] > Trend[i]) trend2[i] =  1;
         if (RsiMa[i] < Trend[i]) trend2[i] = -1;
         manageArrow(i); 
         
     }    
manageAlerts();   
return(0);
}

//
//
//
//
//

void manageAlerts()
{
   if (alertsOn)
   {
      if (alertsOnCurrent)
           int whichBar = 0;
      else     whichBar = 1; 

      //
      //
      //
      //
      //
            
      static datetime time1 = 0;
      static string   mess1 = "";
      if (alertsOnZeroCross && trend1[whichBar] != trend1[whichBar+1])
      {
         if (trend1[whichBar] ==  1) doAlert(time1,mess1,whichBar,"Crossed zero line up");
         if (trend1[whichBar] == -1) doAlert(time1,mess1,whichBar,"Crossed zero line down");
      }
      
      static datetime time2 = 0;
      static string   mess2 = "";
      if (alertsOnSignalCross && trend2[whichBar] != trend2[whichBar+1])
      {
         if (trend2[whichBar] ==  1) doAlert(time2,mess2,whichBar,"Signal cross up");
         if (trend2[whichBar] == -1) doAlert(time2,mess2,whichBar,"Signal cross down");
      }
      
   }
}

//
//
//
//
//

void doAlert(datetime& previousTime, string& previousAlert, int forBar, string doWhat)
{
   string message;
   
   if (previousAlert != doWhat || previousTime != Time[forBar]) {
       previousAlert  = doWhat;
       previousTime   = Time[forBar];

       //
       //
       //
       //
       //

       message =  Symbol()+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+" "+doWhat;
          if (alertsMessage) Alert(message);
          if (alertsNotify)  SendNotification(StringConcatenate(Symbol(), Period() ," " +" "+message));
          if (alertsEmail)   SendMail(StringConcatenate(Symbol()," "),message);
          if (alertsSound)   PlaySound(soundFile);
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

void manageArrow(int i)
{
   if (arrowsVisible)
   {
      deleteArrow(Time[i]);
      if (arrowsOnZeroCross && trend1[i] != trend1[i+1])
      {
         if (trend1[i] == 1) drawArrow(i,arrowsUpZeroCrossColor,arrowsUpZeroCrossCode,arrowsUpZeroCrossSize,false);
         if (trend1[i] ==-1) drawArrow(i,arrowsDnZeroCrossColor,arrowsDnZeroCrossCode,arrowsDnZeroCrossSize,true);
      }
      
      if (arrowsOnSignalCross && trend2[i]!= trend2[i+1])
      {
         if (trend2[i] == 1) drawArrow(i,arrowsUpSignalColor,arrowsUpSignalCode,arrowsUpSignalSize,false);
         if (trend2[i] ==-1) drawArrow(i,arrowsDnSignalColor,arrowsDnSignalCode,arrowsDnSignalSize,true);
      }
      
   }
}               

//
//
//
//
//

void drawArrow(int i,color theColor,int theCode,int theSize, bool up)
{
   string name = arrowsIdentifier+":"+Time[i];
   double gap  = iATR(NULL,0,20,i);   
   
      //
      //
      //
      //
      //
      
      ObjectCreate(name,OBJ_ARROW,0,Time[i],0);
         ObjectSet(name,OBJPROP_ARROWCODE,theCode );
         ObjectSet(name,OBJPROP_COLOR,    theColor);
         ObjectSet(name,OBJPROP_WIDTH,    theSize );      
         
         if (up)
               ObjectSet(name,OBJPROP_PRICE1,High[i] + arrowsDisplacement * gap);
         else  ObjectSet(name,OBJPROP_PRICE1, Low[i] - arrowsDisplacement * gap);
}

//
//
//
//
//

void deleteArrows()
{
   string lookFor       = arrowsIdentifier+":";
   int    lookForLength = StringLen(lookFor);
   for (int i=ObjectsTotal()-1; i>=0; i--)
   {
      string objectName = ObjectName(i);
         if (StringSubstr(objectName,0,lookForLength) == lookFor) ObjectDelete(objectName);
   }
}

//
//
//
//
//

void deleteArrow(datetime time)
{
   string lookFor = arrowsIdentifier+":"+time; ObjectDelete(lookFor);
}

