MACD_Divergence_v2

Indicators Used
MACD HistogramIndicator of the average true range
Miscellaneous
Implements a curve of type %1It plays sound alertsIt issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
MACD_Divergence_v2
//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2012, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#property  copyright  "MACD Divergence"
#property  link       "MACD Divergence"

//---- defines
#define DodgerBlue2  0xaa6014
#define Crimson2     0x280d93

//---- indicator settings
#property  indicator_separate_window

#property  indicator_buffers  8

#property  indicator_color1  Yellow       // 0: Macd main line
#property  indicator_color2  Orange       // 1: Macd signal line
#property  indicator_color3  Gray         // 2: Macd OsMA line
#property  indicator_color4  DodgerBlue   // 3: Long signal
#property  indicator_color5  Crimson      // 4: Short signal
#property  indicator_color6  Crimson2     // 5: Top peak
#property  indicator_color7  DodgerBlue2  // 6: Bottom peak
#property  indicator_color8  White        // 7: Macd signal (main/signal cross)

#property  indicator_width1  1
#property  indicator_width2  1
#property  indicator_width3  1
#property  indicator_width4  1
#property  indicator_width5  1
#property  indicator_width6  1
#property  indicator_width7  1
#property  indicator_width8  1

#property  indicator_style1  STYLE_SOLID
#property  indicator_style2  STYLE_DOT
#property  indicator_style3  STYLE_SOLID
#property  indicator_style4  STYLE_SOLID
#property  indicator_style5  STYLE_SOLID
#property  indicator_style6  STYLE_SOLID
#property  indicator_style7  STYLE_SOLID
#property  indicator_style8  STYLE_SOLID

//---- indicator parameters
extern int    timeFrame     = 0;      // time frame
extern int    nCheckBars    = 120;    // number of bars to check divergence
extern int    macd_fast     = 12;     // fast EMA
extern int    macd_slow     = 26;     // slow EMA
extern int    macd_signal   = 9;      // signal SMA
extern int    div_mode      = 2;      // 0:MODE_MAIN 1:MODE_SIGNAL 2:OsMA
extern double div_oscErr    = 4.0;    // allowable error along divergence line (oscilator)
extern double div_priceErr  = 0.4;    // allowable error along divergence line (PPS), iATR(nCheckBars)*err
extern bool   bAlertDiv     = false;  // PlaySound() on divergence
extern bool   bAlertCross   = false;  // PlaySound() on Macd main/signal cross
extern bool   bAlertDialog  = false;  // display dialog on alert
extern bool   bDrawObj      = true;   // draw lines on chart/window
extern int    window        = 0;      // specify indicator window explicitly, 0: auto
extern int    nMaxBars      = 20000;  // maximum number of bars to calculate, 0: no limit

//---- indicator buffers
double BufferMacdMain[];    // 0: Macd main line
double BufferMacdSignal[];  // 1: Macd signal line
double BufferMacdOsMA[];    // 2: Macd signal line
double BufferLongDiv[];     // 3: Long signal
double BufferShortDiv[];    // 4: Short signal
double BufferTop[];         // 5: top peak
double BufferBottom[];      // 6: bottom peak
double BufferCross[];       // 7: Macd main/signal cross

//---- vars
string   sIndicatorName;
string   sIndSelf="00-MacdDiv_v104";
string   sPrefix;
int      g_window;
int      markLong        = 233;
int      markShort       = 234;
int      markDot         = 167;
int      markCross       = 167;
color    colRegularLong  = DodgerBlue;  // ( 30, 144, 255)= 0x1e90ff
color    colRegularShort = Crimson;     // (220,  20,  60)= 0xdc143c
color    colHiddenLong   = DodgerBlue2;
color    colHiddenShort  = Crimson2;
int      wRegular        = 1;
int      wHidden         = 1;
datetime tAlertLast      = 0;
//----------------------------------------------------------------------
string TimeFrameToStr(int timeFrame)
  {
   switch(timeFrame) 
     {
      case 1:     return("M1");
      case 5:     return("M5");
      case 15:    return("M15");
      case 30:    return("M30");
      case 60:    return("H1");
      case 240:   return("H4");
      case 1440:  return("D1");
      case 10080: return("W1");
      case 43200: return("MN");
     }

   return("??");
  }
//----------------------------------------------------------------------
void init()
  {
   if(timeFrame==0) 
     {
      timeFrame=Period();
     }

   string tf=TimeFrameToStr(timeFrame);
   sIndicatorName=sIndSelf+"("+tf+","+div_mode+","+macd_fast+","+macd_slow+","+macd_signal+")";
   sPrefix=sIndicatorName;

   IndicatorShortName(sIndicatorName);

   SetIndexBuffer(0,BufferMacdMain);
   SetIndexBuffer(1,BufferMacdSignal);
   SetIndexBuffer(2,BufferMacdOsMA);
   SetIndexBuffer(3,BufferLongDiv);
   SetIndexBuffer(4,BufferShortDiv);
   SetIndexBuffer(5,BufferTop);
   SetIndexBuffer(6,BufferBottom);
   SetIndexBuffer(7,BufferCross);

   SetIndexLabel(0,"Macd main");
   SetIndexLabel(1,"Macd signal");
   SetIndexLabel(2,"Macd OsMA");
   SetIndexLabel(3,"Long signal, divergence");
   SetIndexLabel(4,"Short signal, divergence");
   SetIndexLabel(5,"Top peak");
   SetIndexLabel(6,"Bottom peak");
   SetIndexLabel(7,"Macd main/signal cross");

   SetIndexStyle(0,DRAW_LINE);
   SetIndexStyle(1,DRAW_LINE);
   SetIndexStyle(2,DRAW_HISTOGRAM);
   SetIndexStyle(3,DRAW_ARROW);
   SetIndexStyle(4,DRAW_ARROW);
   SetIndexStyle(5,DRAW_ARROW);
   SetIndexStyle(6,DRAW_ARROW);
   SetIndexStyle(7,DRAW_ARROW);

   SetIndexArrow(3,markLong);
   SetIndexArrow(4,markShort);
   SetIndexArrow(5,markDot);
   SetIndexArrow(6,markDot);
   SetIndexArrow(7,markCross);

   int n=MathMax(macd_fast,macd_slow)+macd_signal;

   SetIndexDrawBegin(0,n);
   SetIndexDrawBegin(1,n);
   SetIndexDrawBegin(2,n);
   SetIndexDrawBegin(3,n);
   SetIndexDrawBegin(4,n);
   SetIndexDrawBegin(5,n);
   SetIndexDrawBegin(6,n);
   SetIndexDrawBegin(7,n);

   SetLevelValue(0,0.0);
  }
//----------------------------------------------------------------------
void deinit()
  {
   int n=ObjectsTotal();
   for(int i=n-1; i>=0; i--) 
     {
      string sName=ObjectName(i);
      if(StringFind(sName,sPrefix)==0) 
        {
         ObjectDelete(sName);
        }
     }
  }
//----------------------------------------------------------------------
void objLine(string sName,int win,datetime ts,double ps,datetime te,double pe,color col,
             int width=1,int style=STYLE_SOLID,bool bBack=false,bool bRay=false)
  {
   ObjectCreate(sName,OBJ_TREND,win,0,0);
   ObjectSet(sName,OBJPROP_TIME1,ts);
   ObjectSet(sName,OBJPROP_PRICE1,ps);
   ObjectSet(sName,OBJPROP_TIME2,te);
   ObjectSet(sName,OBJPROP_PRICE2,pe);
   ObjectSet(sName,OBJPROP_COLOR,col);
   ObjectSet(sName,OBJPROP_WIDTH,width);
   ObjectSet(sName,OBJPROP_STYLE,style);
   ObjectSet(sName,OBJPROP_BACK,bBack);
   ObjectSet(sName,OBJPROP_RAY,bRay);
  }
//----------------------------------------------------------------------
void objArrow(string sName,int win,datetime t,double p,int arrow,color col,int width=1)
  {
   ObjectCreate(sName,OBJ_ARROW,win,0,0);
   ObjectSet(sName,OBJPROP_TIME1,t);
   ObjectSet(sName,OBJPROP_PRICE1,p);
   ObjectSet(sName,OBJPROP_ARROWCODE,arrow);
   ObjectSet(sName,OBJPROP_COLOR,col);
   ObjectSet(sName,OBJPROP_WIDTH,width);
  }
//----------------------------------------------------------------------
string divModeToStr(int divMode)
  {
   switch(div_mode) 
     {

      case MODE_MAIN:
         return("MAIN");

      case MODE_SIGNAL:
         return("SIGNAL");
     }

   return("OsMA");
  }
//----------------------------------------------------------------------
double getVal(int i)
  {
   switch(div_mode) 
     {

      case MODE_MAIN:
         return(BufferMacdMain[i]);

      case MODE_SIGNAL:
         return(BufferMacdSignal[i]);
     }

   return(BufferMacdOsMA[i]);
  }
//----------------------------------------------------------------------
double getLowerPrice(int i)
  {
   double hi = High[i];
   double lo = Low[i];

   return(MathMin(hi,lo));
  }
//----------------------------------------------------------------------
double getHigherPrice(int i)
  {
   double hi = High[i];
   double lo = Low[i];

   return(MathMax(hi,lo));
  }
//----------------------------------------------------------------------
double macdDiv(bool bDrawObj,int mode,int x)
  {
   double v=iCustom(NULL,timeFrame,sIndSelf,
                    0,
                    nCheckBars,
                    macd_fast,
                    macd_slow,
                    macd_signal,
                    div_mode,
                    div_oscErr,
                    div_priceErr,
                    false,
                    false,
                    false,
                    bDrawObj,
                    window,
                    nMaxBars,
                    mode,x);

   return(v);
  }
//----------------------------------------------------------------------
void checkAlert()
  {
   if(bAlertDiv || bAlertCross) 
     {
      bool bLongDiv=(BufferLongDiv[0]!=EMPTY_VALUE);
      bool bShortDiv=(BufferShortDiv[0] != EMPTY_VALUE);
      bool bFireDiv =(bLongDiv|| bShortDiv);
      bool bFireCross=(BufferCross[0]!=EMPTY_VALUE);
      bool bFire=((bAlertDiv && bFireDiv) || 
                  (bAlertCross && bFireCross));
      if(bFire && tAlertLast!=Time[0]) 
        {
         if(!bAlertDialog) 
           {
            PlaySound("alert.wav");
              } else {
            string s="";
            if(bFireDiv) 
              {
               string sMode=divModeToStr(div_mode);
               if(bLongDiv) 
                 {
                  s=s+"MACD("+sMode+") divergence, Long";
                    } else if(bShortDiv) {
                  s=s+"MACD("+sMode+") divergence, Short";
                 }
              }
            if(bFireCross) 
              {
               if(s !="") 
                 {
                  s=s+", ";
                 }
               if(BufferMacdMain[1]>=BufferMacdSignal[1]) 
                 {
                  s=s+"MACD Golden Cross";
                    } else {
                  s=s+"MACD Dead Cross";
                 }
              }
            Alert("["+sIndSelf+"] "+s);
           }
         tAlertLast=Time[0];
        }
     }
  }
//----------------------------------------------------------------------
void start()
  {
   if(window>0) 
     {
      g_window=window;
        } else {
      g_window=WindowFind(sIndicatorName);
     }

   int counted_bars=IndicatorCounted();
   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
   int limit=Bars-counted_bars;
   if(counted_bars==0) limit-=1+MathMax(nCheckBars,3);

   int limit0=limit;

// clear beyond limits
   for(int i=limit0-1; i>=limit; i--) 
     {
      BufferMacdMain[i]   = 0;
      BufferMacdSignal[i] = 0;
      BufferMacdOsMA[i]   = 0;
      BufferLongDiv[i]    = EMPTY_VALUE;
      BufferShortDiv[i]   = EMPTY_VALUE;
      BufferTop[i]        = EMPTY_VALUE;
      BufferBottom[i]     = EMPTY_VALUE;
      BufferCross[i]      = 0;
     }

   if(timeFrame!=Period()) 
     {
      // MTF
      limit =MathMax(limit, timeFrame / Period());
      for(i=limit-1; i>=0; i--) 
        {
         int x=iBarShift(NULL,timeFrame,Time[i]);
         BufferMacdMain[i]   = macdDiv(bDrawObj,  0, x);
         BufferMacdSignal[i] = macdDiv(false, 1, x);
         BufferMacdOsMA[i]   = macdDiv(false, 2, x);
         BufferLongDiv[i]    = macdDiv(false, 3, x);
         BufferShortDiv[i]   = macdDiv(false, 4, x);
         BufferTop[i]        = macdDiv(false, 5, x);
         BufferBottom[i]     = macdDiv(false, 6, x);
         BufferCross[i]      = macdDiv(false, 7, x);
        }

      checkAlert();

      return;
     }

// timeFrame == Period()

   double val1,val2,val3,val4;
   for(i=limit-1; i>=0; i--) 
     {
      BufferMacdMain[i]   = iMACD(NULL, 0, macd_fast, macd_slow, macd_signal, PRICE_CLOSE, MODE_MAIN, i);
      BufferMacdSignal[i] = iMACD(NULL, 0, macd_fast, macd_slow, macd_signal, PRICE_CLOSE, MODE_SIGNAL, i);
      BufferMacdOsMA[i]   = BufferMacdMain[i] - BufferMacdSignal[i];
      BufferTop[i]        = EMPTY_VALUE;
      BufferBottom[i]     = EMPTY_VALUE;
      BufferCross[i]      = EMPTY_VALUE;

      double main2 = BufferMacdMain[i + 2];
      double main1 = BufferMacdMain[i + 1];
      double sig2  = BufferMacdSignal[i + 2];
      double sig1  = BufferMacdSignal[i + 1];

      if((main1>=sig1 && main2<sig2) || 
         (main1<sig1 && main2>=sig2)) 
        {
         BufferCross[i]=(main1+main2+sig1+sig2) * 0.25;
        }

      // check top/bottom peak
      val4 = getVal(i + 4);
      val3 = getVal(i + 3);
      val2 = getVal(i + 2);
      val1 = getVal(i + 1);

      // top peak
      if(val4<=val3 && val3<=val2 && val2>val1) 
        {
         BufferTop[i+2]=val2;
        }

      // bottom peak
      if(val4>val3 && val3>val2 && val2<=val1) 
        {
         BufferBottom[i+2]=val2;
        }
     }

// search divergence on bottom
   for(int i1= limit-1; i1>= 0; i1--) 
     {
      if(BufferBottom[i1] == EMPTY_VALUE) 
        {
         continue;
        }

      for(int hidden=0; hidden<=1; hidden++) 
        {
         val1=getVal(i1);
         double p1=Close[i1];
         int i2=-1;
         for(int j=1; j<=nCheckBars; j++) 
           {
            x=i1+j;
            if(BufferBottom[x]==EMPTY_VALUE) 
              {
               continue;
              }
            val2=getVal(x);
            double p2=Close[x];
            if((!hidden && (val2>val1 || p2<p1)) || 
               (hidden && (val2<val1 || p2>p1))) 
              {
               continue;
              }
            bool bExceed=false;
            // check div_oscErr
            for(int k=i1+1; k<x; k++) 
              {
               double s=getVal(k);
               double pred=val1 +(val2 -val1) *(k -i1)/(x -i1);
               if(pred-s>=div_oscErr*Point) 
                 {
                  bExceed=true;
                  break;
                 }
              }
            // check div_priceErr
            for(k=i1+1; k<x; k++) 
              {
               s= getLowerPrice(k);
               pred=p1+(p2-p1) *(k-i1)/(x-i1);
               if(pred-s>=iATR(NULL,0,nCheckBars,k)*div_priceErr) 
                 {
                  bExceed=true;
                  break;
                 }
              }
            if(!bExceed) 
              {
               i2=x;
              }
           }
         if(i2>=0) 
           {
            val1 = getVal(i1);
            val2 = getVal(i2);
            datetime ts=Time[i1];
            datetime tsSig=Time[i1-2];
            datetime te=Time[i2];
            double os = getVal(i1);
            double oe = getVal(i2);
            double ps = Close[i1];
            double psSig=Open[i1-2];
            double pe=Close[i2];
            color colLine,colArrow;
            int w;
            if(!hidden) 
              {
               colLine=colRegularLong;
               colArrow=colRegularLong;
               w=wRegular;
                 } else {
               colLine=colHiddenLong;
               colArrow=colRegularLong;
               w=wHidden;
              }
            if(bDrawObj) 
              {
               objLine(sPrefix+"line bo"+ts,g_window,ts,os,te,oe,colLine,w);
               objLine(sPrefix+"line bp"+ts,0,ts,ps,te,pe,colLine,w);
               objArrow(sPrefix+"arrow bp"+tsSig,0,tsSig,psSig-Point,markLong,colArrow);
              }
            BufferLongDiv[i1-2]=os;
           }
        }
     }

// search divergence on top
   for(i1 = limit-1; i1>= 0; i1--) 
     {
      if(BufferTop[i1] == EMPTY_VALUE) 
        {
         continue;
        }

      for(hidden=0; hidden<=1; hidden++) 
        {
         val1=getVal(i1);
         p1 = Close[i1];
         i2 = -1;
         for(j=1; j<=nCheckBars; j++) 
           {
            x=i1+j;
            if(BufferTop[x]==EMPTY_VALUE) 
              {
               continue;
              }
            val2=getVal(x);
            p2=Close[x];
            if((!hidden && (val2>val1 || p2<p1)) || 
               (hidden && (val2<val1 || p2>p1))) 
              {
               continue;
              }
            bExceed=false;
            // check div_oscErr
            for(k=i1+1; k<x; k++) 
              {
               s= getVal(k);
               pred=val1+(val2-val1) *(k-i1)/(x-i1);
               if(s-pred>=div_oscErr*Point) 
                 {
                  bExceed=true;
                  break;
                 }
              }
            // check div_priceErr
            for(k=i1+1; k<x; k++) 
              {
               s= getHigherPrice(k);
               pred=p1+(p2-p1) *(k-i1)/(x-i1);
               if(s-pred>=iATR(NULL,0,nCheckBars,k)*div_priceErr) 
                 {
                  bExceed=true;
                  break;
                 }
              }
            if(!bExceed) 
              {
               i2=x;
              }
           }
         if(i2>=0) 
           {
            val1 = getVal(i1);
            val2 = getVal(i2);
            ts=Time[i1];
            tsSig=Time[i1-2];
            te = Time[i2];
            os = getVal(i1);
            oe = getVal(i2);
            ps = Close[i1];
            psSig=Open[i1-2];
            pe=Close[i2];
            if(!hidden) 
              {
               colLine=colRegularShort;
               colArrow=colRegularShort;
               w=wRegular;
                 } else {
               colLine=colHiddenShort;
               colArrow=colRegularShort;
               w=wHidden;
              }
            if(bDrawObj) 
              {
               objLine(sPrefix+"line to"+ts,g_window,ts,os,te,oe,colLine,w);
               objLine(sPrefix+"line tp"+ts,0,ts,ps,te,pe,colLine,w);
               objArrow(sPrefix+"arrow tp"+tsSig,0,tsSig,psSig+Point,markShort,colArrow);
              }
            BufferShortDiv[i1-2]=os;
           }
        }
     }

   checkAlert();
  }
//+------------------------------------------------------------------+

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 ---