MACD_Signal_Divergence

Author: Copyright 2018, MetaQuotes Software Corp.
Price Data Components
Indicators Used
MACD HistogramIndicator of the average true range
0 Views
0 Downloads
0 Favorites
MACD_Signal_Divergence
ÿþ//+------------------------------------------------------------------+

//|                                       MACD_Signal_Divergence.mq5 |

//|                        Copyright 2018, MetaQuotes Software Corp. |

//|                                                 https://mql5.com |

//+------------------------------------------------------------------+

#property copyright "Copyright 2018, MetaQuotes Software Corp."

#property link      "https://mql5.com"

#property version   "1.00"

#property indicator_separate_window

#property indicator_buffers 6

#property indicator_plots   5

//--- plot Arrow to up

#property indicator_label1  "Long signal"

#property indicator_type1   DRAW_ARROW

#property indicator_color1  clrBlue

#property indicator_style1  STYLE_SOLID

#property indicator_width1  1

//--- plot Arrow to down

#property indicator_label2  "Short signal"

#property indicator_type2   DRAW_ARROW

#property indicator_color2  clrRed

#property indicator_style2  STYLE_SOLID

#property indicator_width2  1

//--- plot divergence line to up

#property indicator_label3  "Line to up"

#property indicator_type3   DRAW_LINE

#property indicator_color3  clrGreen

#property indicator_style3  STYLE_SOLID

#property indicator_width3  1

//--- plot divergence line to down

#property indicator_label4  "Line to down"

#property indicator_type4   DRAW_LINE

#property indicator_color4  clrRed

#property indicator_style4  STYLE_SOLID

#property indicator_width4  1

//--- plot AO

#property indicator_label5  "MACD"

#property indicator_type5   DRAW_LINE

#property indicator_color5  clrGreen

#property indicator_style5  STYLE_SOLID

#property indicator_width5  1

//--- input parameters

input uint                 InpPeriodFastMA   =  12;            // Fast EMA

input uint                 InpPeriodSlowMA   =  26;            // Slow EMA

input uint                 InpPeriodSignal   =  9;             // MACD SMA

input ENUM_APPLIED_PRICE   InpAppliedPrice   =  PRICE_CLOSE;   // Applied price

input color                InpColorBullish   =  clrBlue;       // Bullish color

input color                InpColorBearish   =  clrRed;        // Bearish color

//--- indicator buffers

double         BufferArrowToUP[];

double         BufferLineToUP[];

double         BufferArrowToDN[];

double         BufferLineToDN[];

double         BufferSIGNAL[];

double         BufferATR[];

//--- global variables

string         prefix;

int            period_fast_ema;

int            period_slow_ema;

int            period_signal;

int            handle_macd;

int            handle_atr;

//+------------------------------------------------------------------+

//| Custom indicator initialization function                         |

//+------------------------------------------------------------------+

int OnInit()

  {

//--- setting global variables

   period_fast_ema=int(InpPeriodFastMA<1 ? 1 : InpPeriodFastMA);

   period_slow_ema=int((int)InpPeriodSlowMA<=period_fast_ema ? period_fast_ema+1 : InpPeriodSlowMA);

   period_signal=int(InpPeriodSignal<1 ? 1 : InpPeriodSignal);

   prefix="macdsigdiv";

//--- indicator buffers mapping

   SetIndexBuffer(0,BufferArrowToUP,INDICATOR_DATA);

   SetIndexBuffer(1,BufferArrowToDN,INDICATOR_DATA);

   SetIndexBuffer(2,BufferLineToUP,INDICATOR_DATA);

   SetIndexBuffer(3,BufferLineToDN,INDICATOR_DATA);

   SetIndexBuffer(4,BufferSIGNAL,INDICATOR_DATA);

   SetIndexBuffer(5,BufferATR,INDICATOR_CALCULATIONS);

//--- settings indicators parameters

   IndicatorSetInteger(INDICATOR_DIGITS,Digits());

   IndicatorSetString(INDICATOR_SHORTNAME,"MACD Signal Divergence");

//--- setting buffer arrays as timeseries

   ArraySetAsSeries(BufferArrowToUP,true);

   ArraySetAsSeries(BufferArrowToDN,true);

   ArraySetAsSeries(BufferLineToUP,true);

   ArraySetAsSeries(BufferLineToDN,true);

   ArraySetAsSeries(BufferSIGNAL,true);

   ArraySetAsSeries(BufferATR,true);

//--- setting plot buffer colors

   PlotIndexSetInteger(0,PLOT_ARROW,241);

   PlotIndexSetInteger(0,PLOT_LINE_COLOR,InpColorBullish);

   PlotIndexSetInteger(1,PLOT_ARROW,242);

   PlotIndexSetInteger(1,PLOT_LINE_COLOR,InpColorBearish);

   PlotIndexSetInteger(2,PLOT_LINE_COLOR,InpColorBullish);

   PlotIndexSetInteger(3,PLOT_LINE_COLOR,InpColorBearish);

//--- create MA and ATR handles

   ResetLastError();

   handle_macd=iMACD(Symbol(),PERIOD_CURRENT,period_fast_ema,period_slow_ema,period_signal,InpAppliedPrice);

   if(handle_macd==INVALID_HANDLE)

     {

      Print("The iMACD(",(string)period_fast_ema,",",(string)period_slow_ema,",",(string)period_signal,") object was not created: Error ",GetLastError());

      return INIT_FAILED;

     }

   ResetLastError();

   handle_atr=iATR(Symbol(),PERIOD_CURRENT,14);

   if(handle_atr==INVALID_HANDLE)

     {

      Print("The iATR object was not created: Error ",GetLastError());

      return INIT_FAILED;

     }

   return(INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| Custom indicator deinitialization function                       |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

  {

   ObjectsDeleteAll(0,prefix);

   ChartRedraw();

  }

//+------------------------------------------------------------------+

//| 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[])

  {

//--- @>25@:0 =0 <8=8<0;L=>5 :>;8G5AB2> 10@>2 4;O @0AGQB0

   if(rates_total<period_slow_ema+6 || Point()==0) return 0;

//--- #AB0=>2:0 8=45:A0F88 <0AA82>2 :0: B09<A5@89

   ArraySetAsSeries(high,true);

   ArraySetAsSeries(low,true);

   ArraySetAsSeries(time,true);

//--- @>25@:0 8 @0AGQB :>;8G5AB20 ?@>AG8BK205<KE 10@>2

   int limit=rates_total-prev_calculated;

   if(limit>1)

     {

      limit=rates_total-10;

      ArrayInitialize(BufferArrowToUP,EMPTY_VALUE);

      ArrayInitialize(BufferArrowToDN,EMPTY_VALUE);

      ArrayInitialize(BufferLineToUP,EMPTY_VALUE);

      ArrayInitialize(BufferLineToDN,EMPTY_VALUE);

      ArrayInitialize(BufferSIGNAL,EMPTY_VALUE);

     }

//--- >43>B>2:0 40==KE

   int copied=0,count=(limit==0 ? 1 : rates_total);

   copied=CopyBuffer(handle_macd,SIGNAL_LINE,0,count,BufferSIGNAL);

   if(copied!=count) return 0;

   copied=CopyBuffer(handle_atr,0,0,count,BufferATR);

   if(copied!=count) return 0;

//---  0AGQB 8=48:0B>@0

   for(int i=limit; i>=0 && !IsStopped(); i--)

     {

      BufferLineToUP[i]=BufferLineToDN[i]=BufferArrowToUP[i]=BufferArrowToDN[i]=EMPTY_VALUE;

      ProcessBullish(rates_total,high,low,time,i+2);

      ProcessBearish(rates_total,high,low,time,i+2);

     }

//--- return value of prev_calculated for next call

   return(rates_total);

  }

//+------------------------------------------------------------------+

//| I5B 2?048=C 8 2>72@0I05B D;03                                   |

//+------------------------------------------------------------------+

bool IsTrough(const int &rates_total,const int index)

  {

   if(BufferSIGNAL[index]<0 && BufferSIGNAL[index]<BufferSIGNAL[index+1] && BufferSIGNAL[index]<BufferSIGNAL[index-1])

     {

      for(int n=index+1 ;n<rates_total-2; n++)

        {

         if(BufferSIGNAL[n]>0)

            return true;

         else if(BufferSIGNAL[index]>BufferSIGNAL[n])

            return false;

        }

     }

   return false;

  }

//+------------------------------------------------------------------+

//| I5B ?@54K4CICN 2?048=C 8 2>72@0I05B D;03                        |

//+------------------------------------------------------------------+

int PrevTrough(const int &rates_total,const int index)

  {

   for(int n=index+5; n<rates_total-3; n++)

     {

      if(BufferSIGNAL[n]<=BufferSIGNAL[n+1] && BufferSIGNAL[n]<BufferSIGNAL[n+2] && BufferSIGNAL[n]<=BufferSIGNAL[n-1] && BufferSIGNAL[n]<BufferSIGNAL[n-2])

         return n;

     }

   return WRONG_VALUE;

  }

//+------------------------------------------------------------------+

//| >8A: 1KGL8E 4825@35=F89                                         |

//+------------------------------------------------------------------+

void ProcessBullish(const int &rates_total,const double &high[],const double &low[],const datetime &time[],const int index)

  {

   if(IsTrough(rates_total,index))

     {

      int curr=index;

      int prev=PrevTrough(rates_total,index);

      if(prev!=WRONG_VALUE)

        {

         if(BufferSIGNAL[curr]>BufferSIGNAL[prev] && low[curr]<low[prev])

            DrawDivergence(high,low,time,prev,curr,true);

         else if(BufferSIGNAL[curr]<BufferSIGNAL[prev] && low[curr]>low[prev])

            DrawDivergence(high,low,time,prev,curr,true);

        }

     }

  }

//+------------------------------------------------------------------+

//| I5B ?8: 8 2>72@0I05B D;03                                       |

//+------------------------------------------------------------------+

bool IsPeak(const int &rates_total,const int index)

  {

   if(BufferSIGNAL[index]>0 && BufferSIGNAL[index]>BufferSIGNAL[index+1] && BufferSIGNAL[index]>BufferSIGNAL[index-1])

     {

      for(int n=index+1; n<rates_total-2; n++)

        {

         if(BufferSIGNAL[n]<0)

            return true;

         else if(BufferSIGNAL[index]<BufferSIGNAL[n])

            return false;

        }

     }

   return false;

  }

//+------------------------------------------------------------------+

//| I5B ?@54K4CI89 ?8: 8 2>72@0I05B D;03                            |

//+------------------------------------------------------------------+

int PrevPeak(const int &rates_total,const int index)

  {

   for(int n=index+5; n<rates_total-3; n++)

     {

      if(BufferSIGNAL[n]>=BufferSIGNAL[n+1] && BufferSIGNAL[n]>BufferSIGNAL[n+2] && BufferSIGNAL[n]>=BufferSIGNAL[n-1] && BufferSIGNAL[n]>BufferSIGNAL[n-2])

         return n;

     }

   return WRONG_VALUE;

  }

//+------------------------------------------------------------------+

//| >8A: <54256L8E 4825@35=F89                                      |

//+------------------------------------------------------------------+

void ProcessBearish(const int &rates_total,const double &high[],const double &low[],const datetime &time[],const int index)

  {

   if(IsPeak(rates_total,index))

     {

      int curr=index;

      int prev=PrevPeak(rates_total,index);

      if(prev!=WRONG_VALUE)

        {

         if(BufferSIGNAL[curr]<BufferSIGNAL[prev] && high[curr]>high[prev])

            DrawDivergence(high,low,time,prev,curr,false);

         else if(BufferSIGNAL[curr]>BufferSIGNAL[prev] && high[curr]<high[prev])

            DrawDivergence(high,low,time,prev,curr,false);

        }

     }

  }

//+------------------------------------------------------------------+

//| B>1@0605B =0945==K5 4825@35=F88                                 |

//+------------------------------------------------------------------+

void DrawDivergence(const double &high[],const double &low[],const datetime &time[],const int first,const int second,const bool bull_flag)

  {

   string obj_name=prefix+(string)(long)time[first]+"_"+(string)(long)time[second];

   int wnd;

   if(ObjectFind(0,obj_name)<0)

     {

      wnd=ChartWindowFind();

      if(wnd!=WRONG_VALUE)

        {

         if(bull_flag)

           {

            BufferArrowToUP[second]=BufferSIGNAL[second];

            for(int j=first; j>=second; j--)

               BufferLineToUP[j]=EquationDirect(first,BufferSIGNAL[first],second,BufferSIGNAL[second],j);

            //---

            ObjectCreate(0,obj_name+"~",OBJ_TREND,0,time[first],low[first],time[second],low[second]);

            ObjectSetInteger(0,obj_name+"~",OBJPROP_HIDDEN,true);

            ObjectSetInteger(0,obj_name+"~",OBJPROP_SELECTABLE,false);

            ObjectSetInteger(0,obj_name+"~",OBJPROP_COLOR,InpColorBullish);

            ObjectSetString(0,obj_name+"~",OBJPROP_TOOLTIP,"\n");

            //---

            ObjectCreate(0,obj_name+"~A",OBJ_ARROW,0,time[second],low[second]);

            ObjectSetInteger(0,obj_name+"~A",OBJPROP_HIDDEN,true);

            ObjectSetInteger(0,obj_name+"~A",OBJPROP_SELECTABLE,false);

            ObjectSetInteger(0,obj_name+"~A",OBJPROP_COLOR,InpColorBullish);

            ObjectSetInteger(0,obj_name+"~A",OBJPROP_ARROWCODE,241);

            ObjectSetString(0,obj_name+"~A",OBJPROP_TOOLTIP,"Bullish signal: "+TimeToString(time[second]));

           }

         else

           {

            BufferArrowToDN[second]=BufferSIGNAL[second];

            for(int j=first; j>=second; j--)

               BufferLineToDN[j]=EquationDirect(first,BufferSIGNAL[first],second,BufferSIGNAL[second],j);

            //---

            ObjectCreate(0,obj_name+"~",OBJ_TREND,0,time[first],high[first],time[second],high[second]);

            ObjectSetInteger(0,obj_name+"~",OBJPROP_HIDDEN,true);

            ObjectSetInteger(0,obj_name+"~",OBJPROP_SELECTABLE,false);

            ObjectSetInteger(0,obj_name+"~",OBJPROP_COLOR,InpColorBearish);

            ObjectSetString(0,obj_name+"~",OBJPROP_TOOLTIP,"\n");

            //---

            ObjectCreate(0,obj_name+"~A",OBJ_ARROW,0,time[second],high[second]+BufferATR[second]);

            ObjectSetInteger(0,obj_name+"~",OBJPROP_HIDDEN,true);

            ObjectSetInteger(0,obj_name+"~",OBJPROP_SELECTABLE,false);

            ObjectSetInteger(0,obj_name+"~A",OBJPROP_COLOR,InpColorBearish);

            ObjectSetInteger(0,obj_name+"~A",OBJPROP_ARROWCODE,242);

            ObjectSetString(0,obj_name+"~A",OBJPROP_TOOLTIP,"Bearish signal: "+TimeToString(time[second]));

           }

         ObjectSetInteger(0,obj_name+"~",OBJPROP_RAY,false);

        }

     }

  }

//+------------------------------------------------------------------+

//| #@02=5=85 ?@O<>9                                                 |

//+------------------------------------------------------------------+

double EquationDirect(const int left_bar,const double left_price,const int right_bar,const double right_price,const int bar_to_search) 

  {

   return(right_bar==left_bar ? left_price : (right_price-left_price)/(right_bar-left_bar)*(bar_to_search-left_bar)+left_price);

  }

//+------------------------------------------------------------------+

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---