//+------------------------------------------------------------------+ //| WRB-Hidden-Gap.mq5 | //| Copyright © 2014-2022, EarnForex | //| https://www.earnforex.com/ | //| Based on the indicator by Akif TOKUZ | //+------------------------------------------------------------------+ #property copyright "Copyright © 2014-2022, EarnForex © July 2022 Tankk, https://www.forexfactory.com" #property link "https://www.earnforex.com/metatrader-indicators/WRB-Hidden-Gap/" //#property version "1.03" //"4.44" #property description "Identifies Wide Range Bars and Hidden Gaps." #property description "WRB and HG definitions are taken from the WRB Analysis Tutorial-1" #property description "by M.A.Perry from TheStrategyLab.com." #property description "Conversion from MQL4 to MQL5, alerts and optimization by Andriy Moraru." #property indicator_chart_window #property indicator_plots 1 #property indicator_buffers 1 #property indicator_type1 DRAW_ARROW //#property indicator_label1 "WRB" #property indicator_color1 clrAqua #property indicator_width1 3 #property indicator_style1 STYLE_SOLID //+------------------------------------------------------------------+ //| WRB Hidden Gap v1,03 | //+------------------------------------------------------------------+ input int StartCalculationFromBar = 567; input ENUM_STO_PRICE UsedPrices = STO_CLOSECLOSE; input int WRB_LookBackBarCount = 3; input int WRB_WingDingsSymbol = 115; input bool HollowBoxes = false; input color HGcolor1 = clrSlateBlue; input color HGcolor2 = clrBlue; input ENUM_LINE_STYLE HGstyle = STYLE_SOLID; input bool EnableNativeAlerts = true; input bool EnableSoundAlerts = true; input bool EnableEmailAlerts = false; input bool EnablePushAlerts = false; input string SoundFile = "alert2.wav"; //"news.wav"; //"expert.wav"; // //"stops.wav" // input color buttColor = clrWhite; //Button text color input int buttSize = 10; //Button text width input color backColor = clrPurple; //Button background color input int axisX = 0; //Button X axis input int axisY = 444; //Button Y axis //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double WRB[]; int totalBarCount = -1; datetime TimeBar=0; string ObjectPrefix, UnfilledPrefix, FilledPrefix; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int aBars, xBars, MAX, StartCalcBar, LookBackBar; datetime xTime[1]; long xTick[1], xVolm[1]; int xSpred[1]; double xOpen[1], xHigh[1], xLow[1], xClos[1]; //--- void FirstRun() { totalBarCount = -1; LookBackBar = fmax(WRB_LookBackBarCount,1); StartCalcBar = fmax(StartCalculationFromBar,LookBackBar*2); //Percent = fmax(1,fmin(Percent,999)); MAX = 3+LookBackBar; aBars = iBars(NULL,0)-1; xBars = aBars-MAX; xTime[0] = iTime(NULL,0,0); xOpen[0] = iOpen(NULL,0,0); xHigh[0] = iHigh(NULL,0,0); xLow[0] = iLow(NULL,0,0); xClos[0] = iClose(NULL,0,0); xTick[0] = iTickVolume(NULL,0,0); xVolm[0] = iVolume(NULL,0,0); xSpred[0]= iSpread(NULL,0,0); } //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ void OnInit() { FirstRun(); IndicatorSetString(INDICATOR_SHORTNAME, "WRB+HG["+(string)UsedPrices+","+(string)WRB_LookBackBarCount+"]"); IndicatorSetInteger(INDICATOR_DIGITS,_Digits-_Digits%2); SetIndexBuffer(0, WRB, INDICATOR_DATA); PlotIndexSetInteger(0, PLOT_ARROW, WRB_WingDingsSymbol); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE); ObjectPrefix = "WRB'HG["+(string)StartCalculationFromBar+","+(string)UsedPrices+","+(string)WRB_LookBackBarCount+"]"; UnfilledPrefix = ObjectPrefix + "UNFILLED_"; FilledPrefix = ObjectPrefix + "FILLED_"; //------ рисуем Кнопку getGlobal(0,PrefBT); ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1); //Spred[0]=int(fabs(SymbolInfoDouble(_Symbol,SYMBOL_ASK)-SymbolInfoDouble(_Symbol,SYMBOL_BID))); //--- if (ObjectFind(0,PrefBT)!=0) DrawBUTTON(0,PrefBT,"WRB Hidden Gap", buttColor,backColor); } //+------------------------------------------------------------------+ //| Intersect: Checks whether two bars intersect or not. | //| Return codes are unused. 0 - no intersection. | //+------------------------------------------------------------------+ int intersect(double H1, double L1, double H2, double L2) { if ((L1 > H2) || (H1 < L2)) return 0; if ((H1 >= H2) && (L1 >= L2)) return 1; if ((H1 <= H2) && (L1 <= L2)) return 2; if ((H1 >= H2) && (L1 <= L2)) return 3; if ((H1 <= H2) && (L1 >= L2)) return 4; return 0; } //+------------------------------------------------------------------+ //| checkHGFilled: Checks if the hidden gap is filled or not. | //+------------------------------------------------------------------+ void checkHGFilled(int barNumber, const double &High[], const double &Low[], const datetime &Time[], int rates_total) { string Prefix = UnfilledPrefix; int L = StringLen(Prefix); int obj_total = ObjectsTotal(ChartID(), 0, OBJ_RECTANGLE); // Loop over all unfilled boxes for (int i = 0; i < obj_total && barNumber= 0) && (startTime < Time[barNumber - j])) { if (High[barNumber - j] > HGFillPA_H) HGFillPA_H = High[barNumber - j]; if (Low[barNumber - j] < HGFillPA_L) HGFillPA_L = Low[barNumber - j]; if ((HGFillPA_H > box_H) && (HGFillPA_L < box_L)) { ObjectDelete(0, ObjName); string ObjectText = FilledPrefix + TimeToString(startTime, TIME_DATE | TIME_MINUTES); ObjectCreate(0, ObjectText, OBJ_RECTANGLE, 0, startTime, box_H, Time[barNumber], box_L); ObjectSetInteger(0, ObjectText, OBJPROP_STYLE, HGstyle); ObjectSetInteger(0, ObjectText, OBJPROP_COLOR, objectColor); ObjectSetInteger(0, ObjectText, OBJPROP_FILL, !HollowBoxes); break; } j++; } } } //+------------------------------------------------------------------+ //| checkWRB: Check if the given bar is a WRB or not and sets | //| the buffer value. | //+------------------------------------------------------------------+ // If UseWholeBars = true, High[] and Low[] will be passed to this function. bool checkWRB(int i, const double &Open[], const double &Close[]) { double body, bodyPrior; body = MathAbs(Open[i] - Close[i]); for (int j = 1; j <= LookBackBar && j body) { WRB[i] = EMPTY_VALUE; return false; } } WRB[i] = (Open[i] + Close[i]) / 2; return true; } //+------------------------------------------------------------------+ //| checkHG: Checks HG status of the previous bar. | //+------------------------------------------------------------------+ void checkHG(int i, const double &High[], const double &Low[], const double &Open[], const double &Close[], const datetime &Time[]) { // HG-TEST (test the previous bar i + 1) if (WRB[i - 1] != EMPTY_VALUE) // First rule to become a HG is to become a WRB. { double H, L, A, B; double H2 = High[i - 2]; double L2 = Low[i - 2]; double H1 = High[i]; double L1 = Low[i]; if (UsedPrices<1) { H = High[i - 1]; L = Low[i - 1]; } else { if (Open[i - 1] > Close[i - 1]) { H = Open[i - 1]; L = Close[i - 1]; } else { H = Close[i - 1]; L = Open[i - 1]; } } // Older bar higher than the newer. if (L2 > H1) { A = MathMin(L2, H); B = MathMax(H1, L); } else if (L1 > H2) { A = MathMin(L1, H); B = MathMax(H2, L); } else return; if (A > B) { string ObjectText; color HGcolor = HGcolor1; int Length = StringLen(UnfilledPrefix); int obj_total = ObjectsTotal(ChartID(), 0, OBJ_RECTANGLE); // Loop over all unfilled boxes. for (int j = 0; j < obj_total; j++) { ObjectText = ObjectName(0, j, 0, OBJ_RECTANGLE); if (StringSubstr(ObjectText, 0, Length) != UnfilledPrefix) continue; // Switch colors if the new Hidden Gap is intersecting with previous Hidden Gap. if (intersect(ObjectGetDouble(0, ObjectText, OBJPROP_PRICE), ObjectGetDouble(0, ObjectText, OBJPROP_PRICE, 1), A, B) != 0) { HGcolor = (color)ObjectGetInteger(0, ObjectText, OBJPROP_COLOR); if (HGcolor == HGcolor1) HGcolor = HGcolor2; else HGcolor = HGcolor1; break; } } ObjectText = UnfilledPrefix + TimeToString(Time[i - 1], TIME_DATE | TIME_MINUTES); ObjectCreate(0, ObjectText, OBJ_RECTANGLE, 0, Time[i - 1], A, TimeCurrent() + 10 * 365 * 24 * 60 * 60, B); ObjectSetInteger(0, ObjectText, OBJPROP_STYLE, HGstyle); ObjectSetInteger(0, ObjectText, OBJPROP_COLOR, HGcolor); ObjectSetInteger(0, ObjectText, OBJPROP_FILL, !HollowBoxes); } } } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ //int deinit() { ALL_OBJ_DELETE(); Comment(""); return (0); } void OnDeinit(const int reason) { ALL_OBJ_DELETE(ObjectPrefix); Comment(""); //ObjectsDeleteAll(0,PREF,-1,-1); ObjectDelete(0,PrefBT); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //**************************************************************************** void ALL_OBJ_DELETE(string Pref) { string name; for (int s=ObjectsTotal(0,0,-1)-1; s>=0; s--) { name=ObjectName(0,s,0,-1); if (StringSubstr(name,0,StringLen(Pref))==Pref) ObjectDelete(0,name); } } //+------------------------------------------------------------------+ //| Custom Market Profile main iteration function | //+------------------------------------------------------------------+ 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[]) { if (!buttON[0]) { InitZero(0); return(0); } //--- if (EnableNativeAlerts || EnableEmailAlerts || EnablePushAlerts || EnableSoundAlerts) CheckAlert(); // A new bar started. if (totalBarCount != rates_total) { int start = prev_calculated; start--; // Need at least WRB_LookBackBarCount bars from the end of the chart to work. if (start