//+------------------------------------------------------------------+ //| 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)) { 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 || p2p1))) { continue; } bool bExceed=false; // check div_oscErr for(int k=i1+1; k=div_oscErr*Point) { bExceed=true; break; } } // check div_priceErr for(k=i1+1; k=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 || p2p1))) { continue; } bExceed=false; // check div_oscErr for(k=i1+1; k=div_oscErr*Point) { bExceed=true; break; } } // check div_priceErr for(k=i1+1; k=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(); } //+------------------------------------------------------------------+