#property indicator_chart_window #property strict #property indicator_buffers 5 #property indicator_color1 clrRed #property indicator_color2 clrLime #property indicator_color3 clrBlack #property indicator_color4 clrLime #property indicator_color5 clrRed #property indicator_width4 2 #property indicator_width5 2 #property indicator_label4 "Buy" #property indicator_label5 "Sell" enum ENUM_MODE{ Manual, Automatic }; enum TIMEFRAMES { PeriodCurrent = PERIOD_CURRENT, // Period Selection PeriodM1 = PERIOD_M1, // M1 PeriodM5 = PERIOD_M5, // M5 PeriodM15 = PERIOD_M15, // M15 PeriodM30 = PERIOD_M30, // M30 PeriodH1 = PERIOD_H1, // H1 PeriodH4 = PERIOD_H4, // H4 PeriodD1 = PERIOD_D1, // D1 PeriodW1 = PERIOD_W1, // W1 PeriodMN = PERIOD_MN1 // MN1 }; enum AlertBar { Current = 0, // Current Closed = 1 // Closed }; enum Mode { ReturnBars = -2, CalculateRSI = -1, Normal = 0 }; input ENUM_MODE SignalMode = Automatic; // Def = Manual input TIMEFRAMES i_ePeriod = PeriodH4; // TimeFrame input int RsiPeriod = 4; // RSI Period input ENUM_MA_METHOD MaType = MODE_EMA; // MA Type input int MaPeriod = 2; // MA Period input bool Interpolate = false; // Interpolate input string arrowsIdentifier = "SBNR arrows"; // arrowsIdentifier input color arrowsUpColor = clrLime; // arrowsUpColor input color arrowsDnColor = clrRed; // arrowsDnColor input AlertBar i_eAlertBar = Closed; // Alert Bar input bool alertsSound = FALSE; // Alert input bool alertsMessage = FALSE; // Push Notification input bool alertsEmail = FALSE; // Email Notification input int arrowDistance = 3; double RSIBuffer[]; double MABuffer[]; double StatusBuffer[]; double arrowUpBuffer[]; double arrowDownBuffer[]; string g_sIndicatorName; bool g_bCalculateRSI = FALSE; bool g_bReturnBars = FALSE; ENUM_TIMEFRAMES g_ePeriod; datetime g_dtLastBarTime; int OnInit() { g_ePeriod = (ENUM_TIMEFRAMES) i_ePeriod; if(i_ePeriod == PeriodCurrent) g_ePeriod = (ENUM_TIMEFRAMES) _Period; else { if(SignalMode==Automatic){ if(_Period==PERIOD_M1) g_ePeriod=PERIOD_M5; if(_Period==PERIOD_M5) g_ePeriod=PERIOD_M15; if(_Period==PERIOD_M15) g_ePeriod=PERIOD_H1; if(_Period==PERIOD_M30) g_ePeriod=PERIOD_H4; if(_Period==PERIOD_H1) g_ePeriod=PERIOD_H4; if(_Period==PERIOD_H4) g_ePeriod=PERIOD_D1; if(_Period==PERIOD_D1) g_ePeriod=PERIOD_W1; if(_Period==PERIOD_W1) g_ePeriod=PERIOD_MN1; if(_Period==PERIOD_MN1) g_ePeriod=PERIOD_MN1; } } IndicatorBuffers(5); SetIndexBuffer(0, RSIBuffer); SetIndexLabel(0, ""); SetIndexBuffer(1, MABuffer); SetIndexLabel(1, ""); SetIndexBuffer(2, StatusBuffer); SetIndexLabel(2, ""); SetIndexBuffer(3, arrowUpBuffer); SetIndexBuffer(4, arrowDownBuffer); SetIndexStyle(3, DRAW_ARROW, EMPTY); SetIndexArrow(3, 233); SetIndexStyle(4, DRAW_ARROW, EMPTY); SetIndexArrow(4, 234); if ((Mode) g_ePeriod == CalculateRSI) { g_bCalculateRSI = TRUE; return (INIT_SUCCEEDED); } if ((Mode) g_ePeriod == ReturnBars) { g_bReturnBars = TRUE; return (INIT_SUCCEEDED); } g_sIndicatorName = WindowExpertName(); IndicatorShortName("SBNR Arrow " + PeriodToString()); return (INIT_SUCCEEDED); } void OnDeinit(const int nReason) { RemoveAllArrows(); } 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[]) { int nOtherPeriodShift; if (prev_calculated < 0) return (0); int nStartBar = MathMin(Bars - prev_calculated, Bars - 1); if (g_bReturnBars) { RSIBuffer[0] = nStartBar + 1; return (rates_total); } if (g_ePeriod > Period()) nStartBar = (int) MathMax(nStartBar, MathMin(Bars - 1, iCustom(NULL, g_ePeriod, g_sIndicatorName, Manual, ReturnBars, 0, 0) * g_ePeriod / Period())); if (g_bCalculateRSI) { for (int i = 0; i < nStartBar; i++) RSIBuffer[i] = iRSI(NULL, 0, RsiPeriod, PRICE_CLOSE, i); for (int i = 0; i < nStartBar; i++) MABuffer[i] = iMAOnArray(RSIBuffer, 0, MaPeriod, 0, MaType, i); return (rates_total); } for (int i = nStartBar; i >= 0; i--) { if(i > Bars - 2) continue; nOtherPeriodShift = iBarShift(NULL, g_ePeriod, Time[i] - Time[i] % g_ePeriod, true)+1; if(nOtherPeriodShift == -1) continue; RSIBuffer[i] = iCustom(NULL, g_ePeriod, g_sIndicatorName, Manual, CalculateRSI, RsiPeriod, MaType, MaPeriod, 0, nOtherPeriodShift); MABuffer[i] = iCustom(NULL, g_ePeriod, g_sIndicatorName, Manual, CalculateRSI, RsiPeriod, MaType, MaPeriod, 1, nOtherPeriodShift); StatusBuffer[i] = StatusBuffer[i + 1]; if (RSIBuffer[i] > MABuffer[i]) StatusBuffer[i] = 1; if (RSIBuffer[i] < MABuffer[i]) StatusBuffer[i] = -1; RemoveArrow(Time[i]); if (StatusBuffer[i] != StatusBuffer[i + 1]) { if (StatusBuffer[i] == 1.0) //DrawArrow(i, arrowsUpColor, 233, 0); arrowUpBuffer[i] = Low[i] - (arrowDistance * Point); if (StatusBuffer[i] == -1.0) //DrawArrow(i, arrowsDnColor, 234, 1); arrowDownBuffer[i] = High[i] + (arrowDistance * Point); } if (g_ePeriod <= Period() || (i > 0 &&nOtherPeriodShift == iBarShift(NULL, g_ePeriod, Time[i - 1]))) continue; if (Interpolate) { datetime dtOlderBarTime = iTime(_Symbol, g_ePeriod, nOtherPeriodShift); int nFirstCurrBarInOlder; for (nFirstCurrBarInOlder = 1; i + nFirstCurrBarInOlder < Bars && Time[i + nFirstCurrBarInOlder] >= dtOlderBarTime; nFirstCurrBarInOlder++) { } double fTemp = 1.0 / nFirstCurrBarInOlder; for (int j = 1; j < nFirstCurrBarInOlder; j++) { RSIBuffer[i + j] = j * fTemp * (RSIBuffer[i + nFirstCurrBarInOlder]) + (1.0 - j * fTemp) * RSIBuffer[i]; MABuffer[i + j] = j * fTemp * (MABuffer[i + nFirstCurrBarInOlder]) + (1.0 - j * fTemp) * MABuffer[i]; } } } if (alertsMessage || alertsSound || alertsEmail) { int nAlertBar = (int) i_eAlertBar; if (StatusBuffer[nAlertBar] != StatusBuffer[nAlertBar + 1]) { if (StatusBuffer[nAlertBar] == 1.0) SendAlert("Trend UP"); if (StatusBuffer[nAlertBar] == -1.0) SendAlert("Trend DOWN"); } } return (rates_total); } void DrawArrow(int i, color cColor, int nArrowCode, bool bUp) { string sName = arrowsIdentifier + ":" + TimeToString(Time[i]); double fVerticalShift = 3.0 * iATR(NULL, 0, 20, i) / 4.0; ObjectCreate(sName, OBJ_ARROW, 0, Time[i], 0); ObjectSet(sName, OBJPROP_ARROWCODE, nArrowCode); ObjectSet(sName, OBJPROP_COLOR, cColor); if (bUp) { ObjectSet(sName, OBJPROP_PRICE1, High[i] + fVerticalShift); return; } ObjectSet(sName, OBJPROP_PRICE1, Low[i] - fVerticalShift); } void RemoveAllArrows() { string sName; string sPrefix = arrowsIdentifier + ":"; int nPrefixLen = StringLen(sPrefix); for (int i = ObjectsTotal() - 1; i >= 0; i--) { sName = ObjectName(i); if(StringSubstr(sName, 0, nPrefixLen) == sPrefix) ObjectDelete(sName); } } void RemoveArrow(datetime dtTime) { string sName = arrowsIdentifier + ":" + TimeToString(dtTime); ObjectDelete(sName); } void SendAlert(string sAlertMessage) { if (g_dtLastBarTime != Time[0]) { g_dtLastBarTime = Time[0]; string sMessage = StringConcatenate(Symbol(), " at ", TimeToStr(TimeLocal(), TIME_SECONDS), " Signal Arrow ", sAlertMessage); if(alertsMessage) Alert(sMessage); if(alertsEmail) SendMail(StringConcatenate(Symbol(), "Signal Arrow"), sMessage); if(alertsSound) PlaySound("alert2.wav"); } } string PeriodToString() { switch (g_ePeriod) { case PERIOD_M1: return ("M(1)"); case PERIOD_M5: return ("M(5)"); case PERIOD_M15: return ("M(15)"); case PERIOD_M30: return ("M(30)"); case PERIOD_H1: return ("H(1)"); case PERIOD_H4: return ("H(4)"); case PERIOD_D1: return ("D(1)"); case PERIOD_W1: return ("W(1)"); case PERIOD_MN1: return ("MN(1)"); } return ("Unknown timeframe"); }