Indicators: MACD Divergence - page 4

 
Alain Verleyen:

You missed the point. The post you are referring to was about HOW to get the signal from an EA, you obviously can't have it by just getting the last 2 candles values, you need the third.

It's NOT possible to have an early signal because to detect a divergence you need a peak/trough and for that you need an additional candle which CLOSE. So when candle 0 just open, that means candle 1 is close, and it allow to confirm the peak/trough at candle 2. If someone want to modify the indicator to use unconfirmed peak/trough to have early signal, one can do it, but I will not help to that because it's a bad idea as you will get a lot of bad signals.

What could be done is to DRAW the signal on candle 1 or even candle 0, but that will change nothing, and I decided to draw the signal on the candle which actually show the peak/trough.

you might missed a point as well.

In the case of renko charts the current bar is (mostly) already closed so you would need one candle less. Or am I missing something?

 
Hi Alain, very good indicator, it works well even without adjusting the settings. It is good that it has got the Alerts, but the one thing that is missing for me is the ability to send push notifications to my phone. The same message which appears on the pop-up alert to have it send to my phone. Are you able to add this function to it? That would be very kind of you. 
 
Thank you Alain, this is an excellent indicator
 

Forum on trading, automated trading systems and testing trading strategies

macd divegence

ENEZA PETER MKIRAMWENI, 2021.09.12 12:26

hi help me with this indicator it display alert after three bar i want to display alert immediate after 1 bar


//+------------------------------------------------------------------+
//|                                              MACD_Divergence.mq5 |
//|                                                   Alain Verleyen |
//|                                             http://www.alamga.be |
//+------------------------------------------------------------------+
#property copyright     "Alain Verleyen (mql5) - Original author FX5 (mql4)"
#property link          "http://codebase.mql4.com/1115"
#property version       "1.01"
#property description   "The original indicator was totally rewrite to improve performance and"
#property description   "to correct a little bug. Also it's more funny that simply converting it."

#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots   4

//--- Plot 1 : Bullish 
#property indicator_type1   DRAW_ARROW
#property indicator_color1  clrGreen
#property indicator_label1  "Bullish divergence"
//--- Plot 2 : Bearish
#property indicator_type2   DRAW_ARROW
#property indicator_color2  clrRed
#property indicator_label2  "Bearish divergence"
//--- Plot 3 : MACD Main
#property indicator_type3   DRAW_LINE
#property indicator_style3  STYLE_SOLID
#property indicator_width3   2
#property indicator_color3  clrMagenta
#property indicator_label3  "Main"
//--- Plot 4 : MACD Signal
#property indicator_type4   DRAW_LINE
#property indicator_style4  STYLE_SOLID
#property indicator_width4   1
#property indicator_color4  clrNONE
#property indicator_label4  "Signal"
//--- input parameters
input string s1="-----------------------------------------------";      // ----------- MACD Settings ----------------------
input int    fastEMA                 = 12;
input int    slowEMA                 = 26;
input int    signalSMA               = 9;
input string s2="-----------------------------------------------";      // ----------- Indicator Settings -----------------
input bool   drawIndicatorTrendLines = true;
input bool   drawPriceTrendLines     = true;
input bool   displayAlert            = true;
//--- constants
#define OBJECT_PREFIX       "MACD_DivergenceLine"
#define ARROWS_DISPLACEMENT 0.0001
//--- buffers
double bullishDivergence[];
double bearishDivergence[];
double macdBuffer[];
double signalBuffer[];
//--- handles
int    macdHandle=INVALID_HANDLE;
//--- globals variables
static datetime lastAlertTime;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator handle 
   macdHandle=iMACD(NULL,0,fastEMA,slowEMA,signalSMA,PRICE_CLOSE);
   if(macdHandle==INVALID_HANDLE)
     {
      Print("The iMACD handle is not created: Error ",GetLastError());
      return(INIT_FAILED);
     }
//--- indicator buffers mapping
   SetIndexBuffer(0,bullishDivergence);
   SetIndexBuffer(1,bearishDivergence);
   SetIndexBuffer(2,macdBuffer);
   SetIndexBuffer(3,signalBuffer);
//--- arrow code see http://www.mql5.com/en/docs/constants/objectconstants/wingdings
   PlotIndexSetInteger(0,PLOT_ARROW,233);
   PlotIndexSetInteger(1,PLOT_ARROW,234);
//--- indicator properties
   string indicatorName=StringFormat("MACD_Divergence(%i, %i, %i)",fastEMA,slowEMA,signalSMA);
   PlotIndexSetInteger(3,PLOT_DRAW_BEGIN,signalSMA);
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits+2);
   IndicatorSetString(INDICATOR_SHORTNAME,indicatorName);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Cleaning of chart                                                |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectDeleteByName("MACD_DivergenceLine");
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//--- indicator updated only on new candle except total redraw
   static datetime lastCandleTime=0;
   if(lastCandleTime==time[rates_total-1])
      return(rates_total);
   else
      lastCandleTime=time[rates_total-1];
//--- first calculation or number of bars was changed
   int start;
   if(prev_calculated<=0)
     {
      start=slowEMA;
      ArrayInitialize(bullishDivergence,EMPTY_VALUE);   // divergence buffers must be initialized
      ArrayInitialize(bearishDivergence,EMPTY_VALUE);
     }
   else
     {
      start=prev_calculated-2;
      bullishDivergence[rates_total-1]=EMPTY_VALUE;
      bearishDivergence[rates_total-1]=EMPTY_VALUE;
     }
//--- data (macd buffers) count to copy     
   int toCopy=rates_total-prev_calculated+(prev_calculated<=0 ? 0 : 1);
//--- not all data may be calculated
   int calculated=BarsCalculated(macdHandle);
   if(calculated<rates_total)
     {
      Print("Not all data of macdHandle is calculated (",calculated,"bars ). Error",GetLastError());
      return(0);
     }
//--- get Main MACD buffer
   if(IsStopped()) return(0); //Checking for stop flag
   if(CopyBuffer(macdHandle,MAIN_LINE,0,toCopy,macdBuffer)<=0)
     {
      Print("Getting MACD Main is failed! Error : ",GetLastError());
      return(0);
     }
//--- get Signal MACD buffer
   if(IsStopped()) return(0); //Checking for stop flag
   if(CopyBuffer(macdHandle,SIGNAL_LINE,0,toCopy,signalBuffer)<=0)
     {
      Print("Getting MACD Signal is failed! Error : ",GetLastError());
      return(0);
     }
//--- main loop of calculations
   for(int shift=start; shift<rates_total-2; shift++)
     {
      int currentExtremum,lastExtremum;
      bool isBullishDivergence,isBearishDivergence;
      string divergenceMsg;
      ENUM_LINE_STYLE divergenceStyle=0;

      //--- Catch Bullish Divergence
      isBullishDivergence=false;

      if(macdBuffer[shift]<=macdBuffer[shift-1] && 
         macdBuffer[shift]<macdBuffer[shift-2] && 
         macdBuffer[shift]<macdBuffer[shift+1])
         //--- if current macd main is a bottom (lower than 2 previous and 1 next)
        {
         currentExtremum=shift;
         lastExtremum=GetIndicatorLastTrough(shift);
         //--- 
         if(macdBuffer[currentExtremum]>macdBuffer[lastExtremum] && 
            low[currentExtremum]<low[lastExtremum])
           {
            isBullishDivergence=true;
            divergenceMsg="Classical bullish divergence on: ";
            divergenceStyle=STYLE_SOLID;
           }
         //---   
         if(macdBuffer[currentExtremum]<macdBuffer[lastExtremum] && 
            low[currentExtremum]>low[lastExtremum])
           {
            isBullishDivergence=true;
            divergenceMsg="Reverse bullish divergence on: ";
            divergenceStyle=STYLE_DOT;
           }
         //--- Bullish divergence is found
         if(isBullishDivergence)
           {
            bullishDivergence[currentExtremum]=macdBuffer[currentExtremum]-ARROWS_DISPLACEMENT;
            //---
            if(drawPriceTrendLines==true)
               DrawTrendLine(TRENDLINE_MAIN,time[currentExtremum],time[lastExtremum],low[currentExtremum],low[lastExtremum],Green,divergenceStyle);
            //---
            if(drawIndicatorTrendLines==true)
               DrawTrendLine(TRENDLINE_INDICATOR,time[currentExtremum],time[lastExtremum],macdBuffer[currentExtremum],macdBuffer[lastExtremum],Green,divergenceStyle);
            //---
            if(displayAlert==true && shift>=rates_total-3 && time[currentExtremum]!=lastAlertTime)
               DisplayAlert(divergenceMsg,time[currentExtremum]);
           }
        }
      //--- Catch Bearish Divergence
      isBearishDivergence=false;

      if(macdBuffer[shift]>=macdBuffer[shift-1] && 
         macdBuffer[shift]>macdBuffer[shift-2] && 
         macdBuffer[shift]>macdBuffer[shift+1])
         //--- if current macd main is a top (higher than 2 previous and 1 next)
        {
         currentExtremum=shift;
         lastExtremum=GetIndicatorLastPeak(shift);
         //---   
         if(macdBuffer[currentExtremum]<macdBuffer[lastExtremum] && 
            high[currentExtremum]>high[lastExtremum])
           {
            isBearishDivergence=true;
            divergenceMsg="Classical bearish divergence on: ";
            divergenceStyle=STYLE_SOLID;
           }
         if(macdBuffer[currentExtremum]>macdBuffer[lastExtremum] && 
            high[currentExtremum]<high[lastExtremum])
           {
            isBearishDivergence=true;
            divergenceMsg="Reverse bearish divergence on: ";
            divergenceStyle=STYLE_DOT;
           }
         //--- Bearish divergence is found
         if(isBearishDivergence)
           {
            bearishDivergence[currentExtremum]=macdBuffer[currentExtremum]+ARROWS_DISPLACEMENT;
            //---
            if(drawPriceTrendLines==true)
               DrawTrendLine(TRENDLINE_MAIN,time[currentExtremum],time[lastExtremum],high[currentExtremum],high[lastExtremum],Red,STYLE_SOLID);
            //---
            if(drawIndicatorTrendLines==true)
               DrawTrendLine(TRENDLINE_INDICATOR,time[currentExtremum],time[lastExtremum],macdBuffer[currentExtremum],macdBuffer[lastExtremum],Red,STYLE_SOLID);
            //---
            if(displayAlert==true && shift>=rates_total-3 && time[currentExtremum]!=lastAlertTime)
               DisplayAlert(divergenceMsg,time[currentExtremum]);
           }
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Search last trough                                               |
//+------------------------------------------------------------------+
int GetIndicatorLastTrough(int shift)
  {
   for(int i=shift-5; i>=2; i--)
     {
      if(signalBuffer[i] <= signalBuffer[i-1] && signalBuffer[i] <= signalBuffer[i-2] &&
         signalBuffer[i] <= signalBuffer[i+1] && signalBuffer[i] <= signalBuffer[i+2])
        {
         for(int j=i; j>=2; j--)
           {
            if(macdBuffer[j] <= macdBuffer[j-1] && macdBuffer[j] < macdBuffer[j-2] &&
               macdBuffer[j] <= macdBuffer[j+1] && macdBuffer[j] < macdBuffer[j+2])
               return(j);
           }
        }
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| Search last peak                                                 |
//+------------------------------------------------------------------+
int GetIndicatorLastPeak(int shift)
  {
   for(int i=shift-5; i>=2; i--)
     {
      if(signalBuffer[i] >= signalBuffer[i-1] && signalBuffer[i] >= signalBuffer[i-2] &&
         signalBuffer[i] >= signalBuffer[i+1] && signalBuffer[i] >= signalBuffer[i+2])
        {
         for(int j=i; j>=2; j--)
           {
            if(macdBuffer[j] >= macdBuffer[j-1] && macdBuffer[j] > macdBuffer[j-2] &&
               macdBuffer[j] >= macdBuffer[j+1] && macdBuffer[j] > macdBuffer[j+2])
               return(j);
           }
        }
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| ENUM_TRENDLINE_TYPE used by DrawTrendLine                        |
//+------------------------------------------------------------------+
enum ENUM_TRENDLINE_TYPE
  {
   TRENDLINE_MAIN,
   TRENDLINE_INDICATOR
  };
//+------------------------------------------------------------------+
//| Draw a trend line on main chart or on indicator                  |
//+------------------------------------------------------------------+
void DrawTrendLine(ENUM_TRENDLINE_TYPE window,datetime x1,datetime x2,double y1,double y2,color lineColor,ENUM_LINE_STYLE style)
  {
   string label=OBJECT_PREFIX+"#"+IntegerToString(window)+DoubleToString(x1,0);
   int subwindow=(window==TRENDLINE_MAIN) ? 0 : ChartWindowFind();
   ObjectDelete(0,label);
   ObjectCreate(0,label,OBJ_TREND,subwindow,x1,y1,x2,y2,0,0);
   ObjectSetInteger(0,label,OBJPROP_RAY,false);
   ObjectSetInteger(0,label,OBJPROP_COLOR,lineColor);
   ObjectSetInteger(0,label,OBJPROP_STYLE,style);
  }
//+------------------------------------------------------------------+
//| Display alert when divergence is found                           |
//+------------------------------------------------------------------+
void DisplayAlert(string message,const datetime alertTime)
  {
   lastAlertTime=alertTime;
   Alert(message,Symbol()," , ",EnumToString(Period())," minutes chart");
  }
//+------------------------------------------------------------------+
//| Delete all objects drawn by the indicator                        |
//+------------------------------------------------------------------+
void ObjectDeleteByName(string prefix)
  {
   int total=ObjectsTotal(0),
   length=StringLen(prefix);

//--- Deletion of all objects used by indicator
   for(int i=total-1; i>=0; i--)
     {
      string objName=ObjectName(0,i);
      if(StringSubstr(objName,0,length)==prefix)
        {
         ObjectDelete(0,objName);
        }
     }
  }
//+------------------------------------------------------------------+



 

Forum on trading, automated trading systems and testing trading strategies

Indicators: MACD Divergence

Alain Verleyen, 2013.11.05 19:14

So friendly.

The signal is given at closing of a candle, 1 candle in the past (2 if you count open candle and not 3). It's normal and it's how it have to work. Divergence is based on research of extremum (top/bottom). If you have a way to detect an extremum on the current candle, I suggest you to learn programming and provide us, for free, this great innovation.

Thank you for your input.


 
Hi Alain. Very good indicator. It makes correct signals.
BTW  in part    "//--- Bearish divergence is found"   it was supposed to be   "divergenceStyle"  instead of "STYLE_SOLID" .

Indicator totaly not redraw. For my purpose I decide to make a little modification to make the last bar of indicator redrawable as well as divergence signal.
It will show divergence signal on previous bar, redrawable signal for sure. It will be helpfull on fast timeframes to use signal jast before close a bar.

I made changes:

-  removed all part   "//--- indicator updated only on new candle except total redraw"
-  "start=prev_calculated-2;" was changed to "start=prev_calculated-1;"
-  In part  "//--- main loop of calculations"    "for(int shift=start; shift<rates_total-2; shift++)"  was changed to  "for(int shift=start; shift<rates_total-1; shift++)"

Divergence signal now appears on the previous bar, but it freezes at the moment of appearance and not follow the indicator line on this bar.
Can you help me to solve this?
 

I changed this part and solved it. May be it could be done better and simpler but it works. Arrows moved ahead 1 bar. Lines without arrows are uncomfirmed signals.

//--- indicator updated only on new candle except total redraw
 //  static datetime lastCandleTime=0;
 //  if(lastCandleTime==time[rates_total-1])
 //     return(rates_total);
 //  else
 //     lastCandleTime=time[rates_total-1];
//--- first calculation or number of bars was changed
   int start;
   if(prev_calculated<=0)
     {
      start=slowEMA;
      ArrayInitialize(bullishDivergence,EMPTY_VALUE);   // divergence buffers must be initialized
      ArrayInitialize(bearishDivergence,EMPTY_VALUE);
     }
   else
     { 
      start=prev_calculated-1;
      bullishDivergence[rates_total-1]=EMPTY_VALUE;
      bearishDivergence[rates_total-1]=EMPTY_VALUE;
     }
//--- data (macd buffers) count to copy     
   int toCopy=rates_total-prev_calculated+(prev_calculated<=0 ? 0 : 1);
//--- not all data may be calculated
   int calculated=BarsCalculated(macdHandle);
   if(calculated<rates_total)
     {
      Print("Not all data of macdHandle is calculated (",calculated,"bars ). Error",GetLastError());
      return(0);
     }
//--- get Main MACD buffer
   if(IsStopped()) return(0); //Checking for stop flag
   if(CopyBuffer(macdHandle,MAIN_LINE,0,toCopy,macdBuffer)<=0)
     {
      Print("Getting MACD Main is failed! Error : ",GetLastError());
      return(0);
     }
//--- get Signal MACD buffer
   if(IsStopped()) return(0); //Checking for stop flag
   if(CopyBuffer(macdHandle,SIGNAL_LINE,0,toCopy,signalBuffer)<=0)
     {
      Print("Getting MACD Signal is failed! Error : ",GetLastError());
      return(0);
     }
//--- main loop of calculations
   for(int shift=start; shift<rates_total; shift++)
     {
      int currentExtremum,lastExtremum;
      bool isBullishDivergence,isBearishDivergence;
      string divergenceMsg;
      ENUM_LINE_STYLE divergenceStyle=0;
      
      //--- Catch Bullish Divergence
      isBullishDivergence=false;
               
      if(macdBuffer[shift-1]<=macdBuffer[shift-2] && 
         macdBuffer[shift-1]<macdBuffer[shift-3] && 
         macdBuffer[shift-1]<macdBuffer[shift])
         //--- if current macd main is a bottom (lower than 2 previous and 1 next)
        {
         currentExtremum=shift;
         lastExtremum=GetIndicatorLastTrough(shift);
         //--- 
         if(macdBuffer[currentExtremum-1]>macdBuffer[lastExtremum] && 
            low[currentExtremum-1]<low[lastExtremum])
           {
            isBullishDivergence=true;
            divergenceMsg="Classical bullish divergence on: ";
            divergenceStyle=STYLE_SOLID;
           }
         //---   
         if(macdBuffer[currentExtremum-1]<macdBuffer[lastExtremum] && 
            low[currentExtremum-1]>low[lastExtremum])
           {
            isBullishDivergence=true;
            divergenceMsg="Reverse bullish divergence on: ";
            divergenceStyle=STYLE_DOT;
           }
         //--- Bullish divergence is found
         if(isBullishDivergence)
           {
            bullishDivergence[currentExtremum]=macdBuffer[currentExtremum]-ARROWS_DISPLACEMENT;
            //---
            if(drawPriceTrendLines==true)
               DrawTrendLine(TRENDLINE_MAIN,time[currentExtremum-1],time[lastExtremum],low[currentExtremum-1],low[lastExtremum],Green,divergenceStyle);
            //---
            if(drawIndicatorTrendLines==true)
               DrawTrendLine(TRENDLINE_INDICATOR,time[currentExtremum-1],time[lastExtremum],macdBuffer[currentExtremum-1],macdBuffer[lastExtremum],Green,divergenceStyle);
            //---
            if(displayAlert==true && shift>=rates_total-3 && time[currentExtremum-1]!=lastAlertTime)
               DisplayAlert(divergenceMsg,time[currentExtremum-1]);
           }
        }
      //--- Catch Bearish Divergence
      isBearishDivergence=false;

      if(macdBuffer[shift-1]>=macdBuffer[shift-2] && 
         macdBuffer[shift-1]>macdBuffer[shift-3] && 
         macdBuffer[shift-1]>macdBuffer[shift])
         //--- if current macd main is a top (higher than 2 previous and 1 next)
        {
         currentExtremum=shift;
         lastExtremum=GetIndicatorLastPeak(shift);
         //---   
         if(macdBuffer[currentExtremum-1]<macdBuffer[lastExtremum] && 
            high[currentExtremum-1]>high[lastExtremum])
           {
            isBearishDivergence=true;
            divergenceMsg="Classical bearish divergence on: ";
            divergenceStyle=STYLE_SOLID;
           }
         if(macdBuffer[currentExtremum-1]>macdBuffer[lastExtremum] && 
            high[currentExtremum-1]<high[lastExtremum])
           {
            isBearishDivergence=true;
            divergenceMsg="Reverse bearish divergence on: ";
            divergenceStyle=STYLE_DOT;
           }
         //--- Bearish divergence is found
         if(isBearishDivergence)
           {
            bearishDivergence[currentExtremum]=macdBuffer[currentExtremum]+ARROWS_DISPLACEMENT;
            //---
            if(drawPriceTrendLines==true)
               DrawTrendLine(TRENDLINE_MAIN,time[currentExtremum-1],time[lastExtremum],high[currentExtremum-1],high[lastExtremum],Red,divergenceStyle);
            //---
            if(drawIndicatorTrendLines==true)
               DrawTrendLine(TRENDLINE_INDICATOR,time[currentExtremum-1],time[lastExtremum],macdBuffer[currentExtremum-1],macdBuffer[lastExtremum],Red,divergenceStyle);
            //---
            if(displayAlert==true && shift>=rates_total-3 && time[currentExtremum-1]!=lastAlertTime)
               DisplayAlert(divergenceMsg,time[currentExtremum-1]);
           }
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Search last trough                                               |
//+------------------------------------------------------------------+
int GetIndicatorLastTrough(int shift)
  {
   for(int i=shift-6; i>=2; i--)
     {
      if(signalBuffer[i] <= signalBuffer[i-1] && signalBuffer[i] <= signalBuffer[i-2] &&
         signalBuffer[i] <= signalBuffer[i+1] && signalBuffer[i] <= signalBuffer[i+2])
        {
         for(int j=i; j>=2; j--)
           {
            if(macdBuffer[j] <= macdBuffer[j-1] && macdBuffer[j] < macdBuffer[j-2] &&
               macdBuffer[j] <= macdBuffer[j+1] && macdBuffer[j] < macdBuffer[j+2])
               return(j);
           }
        }
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| Search last peak                                                 |
//+------------------------------------------------------------------+
int GetIndicatorLastPeak(int shift)
  {
   for(int i=shift-6; i>=2; i--)
     {
      if(signalBuffer[i] >= signalBuffer[i-1] && signalBuffer[i] >= signalBuffer[i-2] &&
         signalBuffer[i] >= signalBuffer[i+1] && signalBuffer[i] >= signalBuffer[i+2])
        {
         for(int j=i; j>=2; j--)
           {
            if(macdBuffer[j] >= macdBuffer[j-1] && macdBuffer[j] > macdBuffer[j-2] &&
               macdBuffer[j] >= macdBuffer[j+1] && macdBuffer[j] > macdBuffer[j+2])
               return(j);
           }
        }
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| ENUM_TRENDLINE_TYPE used by DrawTrendLine                        |
//+------------------------------------------------------------------+
 
Vladimir Karputov #:

when divergence zero line below also price formation HL bottom ( price if not made again LL) histogram any other 5 30 60 240 tf 3 tf signed to fruitful

 

Hello Alain,

Thank you very much for this great indicator!

I am trying to use the Data Window values of this indicator inside an EA. (Please see attachment)

I use the same logic for all four indexes but I am able to get the correct values only for the last two (Main and Signal).


For the first two I see always a fix number

when, for the example attached, one should have a correct value and the other should be 0/blank


do you know why I have this problem?


Thank you

Files:
Screenshot.PNG  85 kb
Reason: