// // "00-RsiDiv_v100.mq4" -- Rsi Divergence // // Ver. 0.01 2008/12/10(Wed) initial version // // #property copyright "00 - 00mql4@gmail.com" #property link "http://www.mql4.com/" //---- defines #define DodgerBlue2 0xaa6014 #define Crimson2 0x280d93 //---- indicator settings #property indicator_separate_window #property indicator_level1 30 #property indicator_level2 70 #property indicator_buffers 6 #property indicator_color1 SlateBlue // 0: Rsi line #property indicator_color2 MediumOrchid // 1: Rsi smoothed line(T3) #property indicator_color3 DodgerBlue // 2: Long signal #property indicator_color4 Crimson // 3: Short signal #property indicator_color5 Crimson2 // 4: Top peak #property indicator_color6 DodgerBlue2 // 5: Bottom peak #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_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 //---- indicator parameters extern int timeFrame = 0; // time frame extern int nCheckBars = 120; // number of bars to check divergence extern int rsi_period = 8; // RSI period extern int div_mode = MODE_SIGNAL; // 0/MODE_MAIN:RSI value 1/MODE_SIGNAL:smoothed value(T3) extern double div_err = 0.3; // allowable error along divergence line extern int nMaxBars = 2000; // maximum number of bars to calculate, 0: no limit //---- indicator buffers double BufferRsiMain[]; // 0: Rsi main line double BufferRsiSignal[]; // 1: Rsi smoothed line double BufferLong[]; // 2: Long signal double BufferShort[]; // 3: Short signal double BufferTop[]; // 4: top peak double BufferBottom[]; // 5: bottom peak //---- vars string sIndicatorName; string sIndRsi = "00-RsiDiv_v100"; string sPrefix; int g_window; int markLong = 233; int markShort = 234; int markDot = 167; color colRegularLong = DodgerBlue; // ( 30, 144, 255)= 0x1e90ff color colRegularShort = Crimson; // (220, 20, 60)= 0xdc143c color colHiddenLong = DodgerBlue2; color colHiddenShort = Crimson2; int wRegular = 2; int wHidden = 2; double t3_curvature = 0.6180; double t3_e1, t3_e2, t3_e3, t3_e4, t3_e5, t3_e6; double t3_c1, t3_c2, t3_c3, t3_c4; double t3_w1, t3_w2, t3_b2, t3_b3; //---------------------------------------------------------------------- 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 = sIndRsi + "(" + tf + "," + div_mode + "," + rsi_period + ")"; sPrefix = sIndicatorName; IndicatorShortName(sIndicatorName); SetIndexBuffer(0, BufferRsiMain); SetIndexBuffer(1, BufferRsiSignal); SetIndexBuffer(2, BufferLong); SetIndexBuffer(3, BufferShort); SetIndexBuffer(4, BufferTop); SetIndexBuffer(5, BufferBottom); SetIndexLabel(0, "Rsi main"); SetIndexLabel(1, "Rsi signal"); SetIndexLabel(2, "Long signal"); SetIndexLabel(3, "Short signal"); SetIndexLabel(4, "Top peak"); SetIndexLabel(5, "Bottom peak"); SetIndexStyle(0, DRAW_LINE); SetIndexStyle(1, DRAW_LINE); SetIndexStyle(2, DRAW_ARROW); SetIndexStyle(3, DRAW_ARROW); SetIndexStyle(4, DRAW_ARROW); SetIndexStyle(5, DRAW_ARROW); SetIndexArrow(2, markLong); SetIndexArrow(3, markShort); SetIndexArrow(4, markDot); SetIndexArrow(5, markDot); int n = rsi_period; SetIndexDrawBegin(0, n); SetIndexDrawBegin(1, n); SetIndexDrawBegin(2, n); SetIndexDrawBegin(3, n); SetIndexDrawBegin(4, n); SetIndexDrawBegin(5, n); // setup for T3 t3_e1 = 0; t3_e2 = 0; t3_e3 = 0; t3_e4 = 0; t3_e5 = 0; t3_e6 = 0; t3_c1 = 0; t3_c2 = 0; t3_c3 = 0; t3_c4 = 0; t3_w1 = 0; t3_w2 = 0; t3_b2 = 0; t3_b3 = 0; t3_b2 = t3_curvature * t3_curvature; t3_b3 = t3_b2 * t3_curvature; t3_c1 = -t3_b3; t3_c2 = (3.0 * (t3_b2 + t3_b3)); t3_c3 = -3.0 * (2.0 * t3_b2 + t3_curvature + t3_b3); t3_c4 = (1.0 + 3 * t3_curvature + t3_b3 + 3.0 * t3_b2); double x = MathMax(rsi_period, 1); x = 1.0 + 0.5 * (x - 1.0); t3_w1 = 2.0 / (x + 1.0); t3_w2 = 1.0 - t3_w1; } //---------------------------------------------------------------------- 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 = true, 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); } //---------------------------------------------------------------------- double getRsi(int i) { if (div_mode == MODE_MAIN) { return(BufferRsiMain[i]); } return(BufferRsiSignal[i]); } //---------------------------------------------------------------------- void start() { g_window = WindowFind(sIndicatorName); int limit = Bars; if (nMaxBars > 0) { limit = MathMin(limit, nMaxBars); } if (timeFrame != Period()) { // MTF limit = MathMax(limit, timeFrame / Period()); for (int i = limit - 1; i >= 0; i--) { int x = iBarShift(NULL, timeFrame, Time[i]); BufferRsiMain[i] = iCustom(NULL, timeFrame, sIndRsi, 0, nCheckBars, rsi_period, div_mode, div_err, nMaxBars, 0, x); BufferRsiSignal[i] = iCustom(NULL, timeFrame, sIndRsi, 0, nCheckBars, rsi_period, div_mode, div_err, nMaxBars, 1, x); BufferLong[i] = iCustom(NULL, timeFrame, sIndRsi, 0, nCheckBars, rsi_period, div_mode, div_err, nMaxBars, 2, x); BufferShort[i] = iCustom(NULL, timeFrame, sIndRsi, 0, nCheckBars, rsi_period, div_mode, div_err, nMaxBars, 3, x); BufferTop[i] = iCustom(NULL, timeFrame, sIndRsi, 0, nCheckBars, rsi_period, div_mode, div_err, nMaxBars, 4, x); BufferBottom[i] = iCustom(NULL, timeFrame, sIndRsi, 0, nCheckBars, rsi_period, div_mode, div_err, nMaxBars, 5, x); } return; } // timeFrame == Period() double rsi1, rsi2, rsi3, rsi4; for (i = limit - 1; i >= 0; i--) { double rsi = iRSI(NULL, 0, rsi_period, PRICE_CLOSE, i); t3_e1 = t3_w1 * rsi + t3_w2 * t3_e1; t3_e2 = t3_w1 * t3_e1 + t3_w2 * t3_e2; t3_e3 = t3_w1 * t3_e2 + t3_w2 * t3_e3; t3_e4 = t3_w1 * t3_e3 + t3_w2 * t3_e4; t3_e5 = t3_w1 * t3_e4 + t3_w2 * t3_e5; t3_e6 = t3_w1 * t3_e5 + t3_w2 * t3_e6; BufferRsiMain[i] = rsi; BufferRsiSignal[i] = t3_c1 * t3_e6 + t3_c2 * t3_e5 + t3_c3 * t3_e4 + t3_c4 * t3_e3; BufferLong[i] = EMPTY_VALUE; BufferShort[i] = EMPTY_VALUE; BufferTop[i] = EMPTY_VALUE; BufferBottom[i] = EMPTY_VALUE; rsi4 = getRsi(i + 4); rsi3 = getRsi(i + 3); rsi2 = getRsi(i + 2); rsi1 = getRsi(i + 1); // top peak if (rsi4 <= rsi3 && rsi3 <= rsi2 && rsi2 > rsi1) { BufferTop[i + 2] = rsi2; } // bottom peak if (rsi4 > rsi3 && rsi3 > rsi2 && rsi2 <= rsi1) { BufferBottom[i + 2] = rsi2; } } // 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++) { rsi1 = getRsi(i1); double p1 = Close[i1]; int i2 = -1; for (int j = 1; j <= nCheckBars; j++) { x = i1 + j; if (BufferBottom[x] == EMPTY_VALUE) { continue; } rsi2 = getRsi(x); double p2 = Close[x]; if ((!hidden && (rsi2 > rsi1 || p2 < p1)) || (hidden && (rsi2 < rsi1 || p2 > p1))) { break; } bool bExceed = false; for (int k = i1 + 1; k < x; k++) { double s = getRsi(k); double pred = rsi1 + (rsi2 - rsi1) * (k - i1) / (i2 - i1); if (s < pred * (1.0 - div_err)) { bExceed = true; break; } } if (!bExceed) { i2 = x; } } if (i2 >= 0) { rsi1 = getRsi(i1); rsi2 = getRsi(i2); datetime ts = Time[i1]; datetime tsSig = Time[i1 - 2]; datetime te = Time[i2]; double os = getRsi(i1); double oe = getRsi(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; } 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); WindowRedraw(); BufferLong[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++) { rsi1 = getRsi(i1); p1 = Close[i1]; i2 = -1; for (j = 1; j <= nCheckBars; j++) { x = i1 + j; if (BufferTop[x] == EMPTY_VALUE) { continue; } rsi2 = getRsi(x); p2 = Close[x]; if ((!hidden && (rsi2 > rsi1 || p2 < p1)) || (hidden && (rsi2 < rsi1 || p2 > p1))) { break; } bExceed = false; for (k = i1 + 1; k < x; k++) { s = getRsi(k); pred = rsi1 + (rsi2 - rsi1) * (k - i1) / (i2 - i1); if (s > pred * (1.0 + div_err)) { bExceed = true; break; } } if (!bExceed) { i2 = x; } } if (i2 >= 0) { rsi1 = getRsi(i1); rsi2 = getRsi(i2); ts = Time[i1]; tsSig = Time[i1 - 2]; te = Time[i2]; os = getRsi(i1); oe = getRsi(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; } 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); WindowRedraw(); BufferShort[i1 - 2] = os; } } } }