//+------------------------------------------------------------------+ //|Based on TradersDynamicIndex.mq4 by Dean Malone | //| TradersDynamicIndex.mq5 | //| Copyright © 2015-2019, EarnForex.com | //| https://www.earnforex.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright © 2015-2019, www.EarnForex.com" #property link "https://www.earnforex.com/metatrader-indicators/Traders-Dynamic-Index/" #property version "1.03" #property description "Shows trend direction, strength, and volatility." #property description "Green line - RSI Price line." #property description "Red line - Trade Signal line." #property description "Blue lines - Volatility Band." #property description "Yellow line - Market Base line." #property indicator_separate_window #property indicator_buffers 8 #property indicator_plots 5 #property indicator_level1 32 #property indicator_level2 50 #property indicator_level3 68 #property indicator_levelcolor clrDimGray #property indicator_levelstyle STYLE_DOT #property indicator_levelwidth 1 #property indicator_color1 clrMediumBlue #property indicator_label1 "VB High" #property indicator_type1 DRAW_LINE #property indicator_width1 1 #property indicator_style1 STYLE_SOLID #property indicator_color2 clrYellow #property indicator_label2 "Market Base Line" #property indicator_type2 DRAW_LINE #property indicator_width2 2 #property indicator_style2 STYLE_SOLID #property indicator_color3 clrMediumBlue #property indicator_label3 "VB Low" #property indicator_type3 DRAW_LINE #property indicator_width3 1 #property indicator_style3 STYLE_SOLID #property indicator_color4 clrGreen #property indicator_label4 "RSI Price Line" #property indicator_type4 DRAW_LINE #property indicator_width4 2 #property indicator_style4 STYLE_SOLID #property indicator_color5 clrRed #property indicator_label5 "Trade Signal Line" #property indicator_type5 DRAW_LINE #property indicator_width5 2 #property indicator_style5 STYLE_SOLID input int RSI_Period = 13; // RSI_Period: 8-25 input ENUM_APPLIED_PRICE RSI_Price = PRICE_CLOSE; input int Volatility_Band = 34; // Volatility_Band: 20-40 input double StdDev = 1.6185; // Standard Deviations: 1-3 input int RSI_Price_Line = 2; input ENUM_MA_METHOD RSI_Price_Type = MODE_SMA; input int Trade_Signal_Line = 7; input ENUM_MA_METHOD Trade_Signal_Type = MODE_SMA; input bool AlertNative = false; // AlertNative: Alert popup inside platform. input bool AlertSound = false; // AlertSound: Play a sound on alert. input bool AlertEmail = false; // AlertEmail: Send an email on alert. input bool AlertNotification = false; // AlertNotification: Send a push notification on alert. double RSIBuf[], RSIBufPos[], RSIBufNeg[], UpZone[], MdZone[], DnZone[], MaBuf[], MbBuf[]; int MaxPeriod = 0; datetime AlertPlayed = 0; int RSI_handle; // #include #include // //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ void OnInit() { IndicatorSetString(INDICATOR_SHORTNAME, "TDI(" + IntegerToString(RSI_Period) + "," + IntegerToString(Volatility_Band) + "," + IntegerToString(RSI_Price_Line) + "," + IntegerToString(Trade_Signal_Line) + ")"); SetIndexBuffer(0, UpZone, INDICATOR_DATA); SetIndexBuffer(1, MdZone, INDICATOR_DATA); SetIndexBuffer(2, DnZone, INDICATOR_DATA); SetIndexBuffer(3, MaBuf, INDICATOR_DATA); SetIndexBuffer(4, MbBuf, INDICATOR_DATA); SetIndexBuffer(5, RSIBuf, INDICATOR_CALCULATIONS); SetIndexBuffer(6, RSIBufPos, INDICATOR_CALCULATIONS); SetIndexBuffer(7, RSIBufNeg, INDICATOR_CALCULATIONS); ArraySetAsSeries(UpZone, true); ArraySetAsSeries(MdZone, true); ArraySetAsSeries(DnZone, true); ArraySetAsSeries(MaBuf, true); ArraySetAsSeries(MbBuf, true); ArraySetAsSeries(RSIBuf, true); ArraySetAsSeries(RSIBufPos, true); ArraySetAsSeries(RSIBufNeg, true); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0); PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0); PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, 0); PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, 0); PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, 0); IndicatorSetInteger(INDICATOR_DIGITS, 1); //RSI_handle = iRSI(Symbol(), Period(), RSI_Period, RSI_Price); //RSI_handle = iCustom(_Symbol, _Period, "MedianRenko\\Indicators\\MedianRenko_RSI2", RSI_Period, RSI_Price ,true); // my debug environment // RSI_handle = iCustom(_Symbol, _Period, "MedianRenko\\MedianRenko_RSI2", RSI_Period, RSI_Price ,true); MaxPeriod = Volatility_Band + RSI_Period; PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MaxPeriod); PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MaxPeriod); PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, MaxPeriod); PlotIndexSetInteger(3, PLOT_DRAW_BEGIN, MaxPeriod + RSI_Price_Line); PlotIndexSetInteger(4, PLOT_DRAW_BEGIN, MaxPeriod + Trade_Signal_Line); customChartIndicator.SetGetTimeFlag(); customChartIndicator.SetUseAppliedPriceFlag(RSI_Price); } //+------------------------------------------------------------------+ //| Traders Dynamic Index | //+------------------------------------------------------------------+ 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[] ) { double MA, RSI[]; ArrayResize(RSI, Volatility_Band); ArraySetAsSeries(customChartIndicator.Time, true); // // Process data through MedianRenko indicator // if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,Time,close)) return(0); if(!customChartIndicator.BufferSynchronizationCheck(close)) return(0); int _prev_calculated = customChartIndicator.GetPrevCalculated(); int i; int counted_bars = _prev_calculated; // Too few bars to work with. if (rates_total < MaxPeriod) return(0); i = rates_total - counted_bars; if (i > rates_total - MaxPeriod - 1) i = rates_total - MaxPeriod - 1; // int RSI_bars = CopyBuffer(RSI_handle, 0, 0, rates_total, RSIBuf); // todo? // if (RSI_bars == -1) return(0); RsiOnBuffer(rates_total, _prev_calculated, counted_bars, RSI_Period, customChartIndicator.Price, RSIBuf, RSIBufPos, RSIBufNeg); // Calculate BB on RSI. while (i >= 0) { MA = 0; for (int x = i; x < i + Volatility_Band; x++) { RSI[x - i] = RSIBuf[x]; MA += RSIBuf[x] / Volatility_Band; } double SD = StdDev * StDev(RSI, Volatility_Band); UpZone[i] = MA + SD; DnZone[i] = MA - SD; MdZone[i] = (UpZone[i] + DnZone[i]) / 2; i--; } i = rates_total - counted_bars; if (i > rates_total - MaxPeriod - 1) i = rates_total - MaxPeriod - 1; // Calculate MAs of RSI. while (i >= 0) { MaBuf[i] = iMAOnArray(RSIBuf, 0, RSI_Price_Line, 0, RSI_Price_Type, i); MbBuf[i] = iMAOnArray(RSIBuf, 0, Trade_Signal_Line, 0, Trade_Signal_Type, i); i--; } if ((MbBuf[0] > MdZone[0]) && (MbBuf[1] <= MdZone[1]) && (AlertPlayed != customChartIndicator.Time[0])) { if (AlertNative) Alert("Bullish cross"); if (AlertSound) PlaySound("alert.wav"); if (AlertEmail) { SendMail("TDI Alert: BUY " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[0], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[0], 1) + "\nVB Low = " + DoubleToString(DnZone[0], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[0], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[0], 1)); } if (AlertNotification) SendNotification("TDI Alert: BUY " + _Symbol + " @ " + PeriodToString(_Period)); AlertPlayed = customChartIndicator.Time[0]; } if ((MbBuf[0] < MdZone[0]) && (MbBuf[1] >= MdZone[1]) && (AlertPlayed != customChartIndicator.Time[0])) { if (AlertNative) Alert("Bearish cross"); if (AlertSound) PlaySound("alert.wav"); if (AlertEmail) { SendMail("TDI Alert: SELL " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[0], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[0], 1) + "\nVB Low = " + DoubleToString(DnZone[0], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[0], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[0], 1)); } if (AlertNotification) SendNotification("TDI Alert: SELL " + _Symbol + " @ " + PeriodToString(_Period)); AlertPlayed = customChartIndicator.Time[0]; } return(rates_total); } // Standard Deviation function. double StDev(double& Data[], int Per) { return(MathSqrt(Variance(Data, Per))); } // Math Variance function. double Variance(double& Data[], int Per) { double sum = 0, ssum = 0; for (int i = 0; i < Per; i++) { sum += Data[i]; ssum += MathPow(Data[i], 2); } return((ssum * Per - sum * sum) / (Per * (Per - 1))); } //+------------------------------------------------------------------+ //| Based on http://www.mql5.com/en/articles/81 | //| Simplified SMA calculation. | //+------------------------------------------------------------------+ double iMAOnArray(double &Array[], int total, int iMAPeriod, int ma_shift, ENUM_MA_METHOD ma_method, int Shift) { double buf[]; if ((total > 0) && (total <= iMAPeriod)) return(0); if (total == 0) total = ArraySize(Array); if (ArrayResize(buf, total) < 0) return(0); switch(ma_method) { // Simplified SMA. No longer works with ma_shift parameter. case MODE_SMA: { double sum = 0; for (int i = Shift; i < Shift + iMAPeriod; i++) sum += Array[i] / iMAPeriod; return(sum); } case MODE_EMA: { double pr = 2.0 / (iMAPeriod + 1); int pos = total - 2; while (pos >= 0) { if (pos == total - 2) buf[pos + 1] = Array[pos + 1]; buf[pos] = Array[pos] * pr + buf[pos + 1] * (1 - pr); pos--; } return(buf[Shift + ma_shift]); } case MODE_SMMA: { double sum = 0; int i, k, pos; pos = total - iMAPeriod; while (pos >= 0) { if (pos == total - iMAPeriod) { for (i = 0, k = pos; i < iMAPeriod; i++, k++) { sum += Array[k]; buf[k] = 0; } } else sum = buf[pos + 1] * (iMAPeriod - 1) + Array[pos]; buf[pos] = sum / iMAPeriod; pos--; } return(buf[Shift + ma_shift]); } case MODE_LWMA: { double sum = 0.0, lsum = 0.0; double price; int i, weight = 0, pos = total - 1; for (i = 1; i <= iMAPeriod; i++, pos--) { price = Array[pos]; sum += price * i; lsum += price; weight += i; } pos++; i = pos + iMAPeriod; while (pos >= 0) { buf[pos] = sum / weight; if (pos == 0) break; pos--; i--; price = Array[pos]; sum = sum - lsum + price * iMAPeriod; lsum -= Array[i]; lsum += price; } return(buf[Shift + ma_shift]); } default: return(0); } return(0); } // For alerts. string PeriodToString(int per) { switch (per) { case 60: return("H1"); case 240: return("H4"); case 1440: return("D1"); case 10080: return("W1"); case 43200: return("MN1"); case 30: return("M30"); case 15: return("M15"); case 5: return("M5"); case 1: return("M1"); } return(""); } //+------------------------------------------------------------------+