//+------------------------------------------------------------------+
//|                     edited from     FX5_MACD_Divergence_V1.1.mq4 |
//|                                                                  |
//|Editor: GODFREYH (godfreyh@gmail.com)                             |
//+------------------------------------------------------------------+

#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1 Blue
#property indicator_color2 Red
#property indicator_color3 Magenta
#property indicator_width3 2
#property indicator_level1 0.7
#property indicator_level2 0
#property indicator_level3 -0.7
#property indicator_levelcolor DimGray
#property indicator_levelstyle 4
//----
#define arrowsDisplacement 0.0001

extern int Length=10;
extern int Smooth=3;
extern int PriceType=0;

extern string separator2 = "*** Indicator Settings ***";
extern bool   drawIndicatorTrendLines = true;
extern bool   drawPriceTrendLines = true;
extern bool   displayAlert = true;

extern color  ColorBearishTrendLines=Red;
extern color  ColorBullishTrendLines=Blue;
int TimeFrame=0;
//---- buffers
double bullishDivergence[];
double bearishDivergence[];
double macd[];
double signal[];
//----
static datetime lastAlertTime;
static string   indicatorName;
extern int minimum_diverg_bar = 5;



//+------------------------------------------------------------------+
//| Custom indicator timeframe function                              |
//+------------------------------------------------------------------+

string GetTimeFrameStr() {
   switch(TimeFrame)
   {
      case 1 : string TimeFrameStr2="M1"; break;
      case 5 : TimeFrameStr2="M5"; break;
      case 15 : TimeFrameStr2="M15"; break;
      case 30 : TimeFrameStr2="M30"; break;
      case 60 : TimeFrameStr2="H1"; break;
      case 240 : TimeFrameStr2="H4"; break;
      case 1440 : TimeFrameStr2="D1"; break;
      case 10080 : TimeFrameStr2="W1"; break;
      case 43200 : TimeFrameStr2="MN1"; break;
   } 
   return (TimeFrameStr2);
}
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0, DRAW_ARROW);
   SetIndexStyle(1, DRAW_ARROW);
   SetIndexStyle(2, DRAW_LINE);
   SetIndexStyle(3, DRAW_LINE);
//----   
   SetIndexBuffer(0, bullishDivergence);
   SetIndexBuffer(1, bearishDivergence);
   SetIndexBuffer(2, macd);
   SetIndexBuffer(3, signal);   
//----   
   SetIndexArrow(0, 233);
   SetIndexArrow(1, 234);
//----

   // Show regular timeframe string (HCY)
   if (TimeFrame == 0) {
      TimeFrame = Period();
      }
     indicatorName =Symbol()+" ("+GetTimeFrameStr()+"):  RSX_Divergence";
   SetIndexDrawBegin(3, Length);//signalSMA);
   IndicatorDigits(Digits + 2);
   IndicatorShortName(indicatorName);
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
   for(int i = ObjectsTotal() - 1; i >= 0; i--)
     {
       string label = ObjectName(i);
       if(StringSubstr(label, 0, 25) != "Stochastic_DivergenceLine")
           continue;
       ObjectDelete(label);   
     }
 //    ObjectsDeleteAll();
 //    ObjectDelete(label);
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int countedBars = IndicatorCounted();
   if(countedBars < 0)
       countedBars = 0;
   CalculateIndicator(countedBars);
//---- 
   return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CalculateIndicator(int countedBars)
  {
   for(int i = Bars - countedBars; i >= 0; i--)
     {
       CalculateMACD(i);
       CatchBullishDivergence(i + 2);
       CatchBearishDivergence(i + 2);
     }              
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CalculateMACD(int i)
  {
   macd[i]=iCustom(NULL,0,"JJRSX",Length,Smooth,PriceType,0,i);
   
 //  signal[i] = iCustom(NULL,0,"RSX",Length,0,i);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CatchBullishDivergence(int shift)
  {
   if(IsIndicatorTrough(shift) == false)
       return;  
   int currentTrough = shift;
   int lastTrough = GetIndicatorLastTrough(shift);
//   static bool turn_alarm = true;
//----   
   if(macd[currentTrough] >= macd[lastTrough] && 
      Low[currentTrough] <= Low[lastTrough])
     {
       bullishDivergence[currentTrough] = macd[currentTrough] - 
                                          arrowsDisplacement;
       //----
       if(drawPriceTrendLines == true)
           DrawPriceTrendLine(Time[currentTrough], Time[lastTrough], 
                              Low[currentTrough], 
                             Low[lastTrough], ColorBullishTrendLines, STYLE_SOLID);
       //----
       if(drawIndicatorTrendLines == true)
          DrawIndicatorTrendLine(Time[currentTrough], 
                                 Time[lastTrough], 
                                 macd[currentTrough],
                                 macd[lastTrough], 
                                 ColorBullishTrendLines, STYLE_SOLID);
       //----
       if(displayAlert == true)
          DisplayAlert("RSX Classical bullish divergence on: ", 
                        currentTrough);  
                        
       //----
/*       if(alert_ON == true)
       {  
         Alert ("Classical bullish divergence on ",Symbol(),"-",TimeFrame);
         PlaySound("timeout.wav"); 
         turn_alarm=false;
       }*/
     }
//----   
   if(macd[currentTrough] <= macd[lastTrough] && 
      Low[currentTrough] >= Low[lastTrough])
     {
       bullishDivergence[currentTrough] = macd[currentTrough] - 
                                          arrowsDisplacement;
       //----
       if(drawPriceTrendLines == true)
           DrawPriceTrendLine(Time[currentTrough], Time[lastTrough], 
                              Low[currentTrough], 
                              Low[lastTrough], ColorBullishTrendLines, STYLE_DOT);
       //----
       if(drawIndicatorTrendLines == true)                            
           DrawIndicatorTrendLine(Time[currentTrough], 
                                  Time[lastTrough], 
                                  macd[currentTrough],
                                  macd[lastTrough], 
                                  ColorBullishTrendLines, STYLE_DOT);
       //----
       if(displayAlert == true)
           DisplayAlert("RSX Hidden bullish divergence on: ", 
                        currentTrough);  
       
       //----
/*       if(alert_ON == true)
       {  
         Alert ("Hidden bullish divergence on ",Symbol(),"-",TimeFrame);
         PlaySound("timeout.wav"); 
         turn_alarm=false;
       }                 */
              
     }      
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CatchBearishDivergence(int shift)
  {
   if(IsIndicatorPeak(shift) == false)
       return;
   int currentPeak = shift;
   int lastPeak = GetIndicatorLastPeak(shift);
   static bool turn_alarm = true;
//----   
   if(macd[currentPeak] <= macd[lastPeak] && 
      High[currentPeak] >= High[lastPeak])
     {
       bearishDivergence[currentPeak] = macd[currentPeak] + 
                                        arrowsDisplacement;
      
       if(drawPriceTrendLines == true)
           DrawPriceTrendLine(Time[currentPeak], Time[lastPeak], 
                              High[currentPeak], 
                              High[lastPeak], ColorBearishTrendLines, STYLE_SOLID);
                            
       if(drawIndicatorTrendLines == true)
           DrawIndicatorTrendLine(Time[currentPeak], Time[lastPeak], 
                                  macd[currentPeak],
                                  macd[lastPeak], ColorBearishTrendLines, STYLE_SOLID);

       if(displayAlert == true)
           DisplayAlert("RSX Classical bearish divergence on: ", 
                        currentPeak);  
       
/*       if(alert_ON == true)
       {  
         Alert ("Classical bearish divergence on ",Symbol(),"-",TimeFrame);
         PlaySound("timeout.wav"); 
         turn_alarm=false;
       }*/
     }
   if(macd[currentPeak] >= macd[lastPeak] && 
      High[currentPeak] <= High[lastPeak])
     {
       bearishDivergence[currentPeak] = macd[currentPeak] + 
                                        arrowsDisplacement;
       //----
       if(drawPriceTrendLines == true)
           DrawPriceTrendLine(Time[currentPeak], Time[lastPeak], 
                              High[currentPeak], 
                              High[lastPeak], ColorBearishTrendLines, STYLE_DOT);
       //----
       if(drawIndicatorTrendLines == true)
           DrawIndicatorTrendLine(Time[currentPeak], Time[lastPeak], 
                                  macd[currentPeak],
                                  macd[lastPeak], ColorBearishTrendLines, STYLE_DOT);
       //----
       if(displayAlert == true)
           DisplayAlert("RSX Hidden bearish divergence on: ", 
                        currentPeak);  
                        
/*       if(alert_ON == true)
       {  
         Alert ("Hidden bearish divergence on ",Symbol(),"-",TimeFrame);
         PlaySound("timeout.wav"); 
         turn_alarm=false;
       } */
     }   
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsIndicatorPeak(int shift)
  {
   if(macd[shift] >= macd[shift+1] && macd[shift] > macd[shift+2] && 
      macd[shift] > macd[shift-1])
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsIndicatorTrough(int shift)
  {
   if(macd[shift] <= macd[shift+1] && macd[shift] < macd[shift+2] && 
      macd[shift] < macd[shift-1])
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int GetIndicatorLastPeak(int shift)
  {
   for(int i = shift + minimum_diverg_bar; i < Bars; i++)
     {
       if(signal[i] >= signal[i+1] && signal[i] >= signal[i+2] &&
          signal[i] >= signal[i-1] && signal[i] >= signal[i-2])
         {
           for(int j = i; j < Bars; j++)
             {
               if(macd[j] >= macd[j+1] && macd[j] > macd[j+2] &&
                  macd[j] >= macd[j-1] && macd[j] > macd[j-2])
                   return(j);
             }
         }
     }
   return(-1);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int GetIndicatorLastTrough(int shift)
  {
    for(int i = shift + minimum_diverg_bar; i < Bars; i++)
      {
        if(signal[i] <= signal[i+1] && signal[i] <= signal[i+2] &&
           signal[i] <= signal[i-1] && signal[i] <= signal[i-2])
          {
            for (int j = i; j < Bars; j++)
              {
                if(macd[j] <= macd[j+1] && macd[j] < macd[j+2] &&
                   macd[j] <= macd[j-1] && macd[j] < macd[j-2])
                    return(j);
              }
          }
      }
    return(-1);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void DisplayAlert(string message, int shift)
  {
   if(shift <= 2 && Time[shift] != lastAlertTime)
     {
       lastAlertTime = Time[shift];
       Alert(message, Symbol(), " , ", /*Period()==*/TimeFrame, " minutes chart");
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void DrawPriceTrendLine(datetime x1, datetime x2, double y1, 
                        double y2, color lineColor, double style)
  {
   string label = "Stochastic_DivergenceLine_v1.0# " + DoubleToStr(x1, 0) + TimeFrame;
   ObjectDelete(label);
   ObjectCreate(label, OBJ_TREND, 0, x1, y1, x2, y2, 0, 0);
   ObjectSet(label, OBJPROP_RAY, 0);
   ObjectSet(label, OBJPROP_COLOR, lineColor);
   ObjectSet(label, OBJPROP_STYLE, style);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void DrawIndicatorTrendLine(datetime x1, datetime x2, double y1, 
                            double y2, color lineColor, double style)
  {
   int indicatorWindow = WindowFind(indicatorName);
   if(indicatorWindow < 0)
       return;
   string label = "Stochastic_DivergenceLine_v1.0$# " + DoubleToStr(x1, 0) + TimeFrame;
   ObjectDelete(label);
   ObjectCreate(label, OBJ_TREND, indicatorWindow, x1, y1, x2, y2, 
                0, 0);
   ObjectSet(label, OBJPROP_RAY, 0);
   ObjectSet(label, OBJPROP_COLOR, lineColor);
   ObjectSet(label, OBJPROP_STYLE, style);
  }
//+------------------------------------------------------------------+


