//+------------------------------------------------------------------+ //| WRB-Hidden-Gap.mq4 | //| Copyright © 2010, Akif TOKUZ | //| akifusenet@gmail.com | //| Identifies Wide Range Bars and Hidden Gaps. | //| WRB and HG definitions are taken from the WRB Analysis Tutorial-1| //| by M.A.Perry from TheStrategyLab.com | //| | //| History: | //| 09.04.2014: Alerts and optimization. | //| 06.04.2010: Correction to make sure Hidden Gaps are not filled | //| with real gaps. | //| 03.04.2010: Initial release | //| | //+------------------------------------------------------------------+ #property copyright "Akif TOKUZ and EarnForex.com" #property link "http://www.earnforex.com" #property version "1.00" #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 "Alerts and optimization by Andriy Moraru." #property indicator_chart_window #property indicator_buffers 1 #property indicator_color1 clrAqua // WRB symbol #property indicator_width1 1 #define UNFILLED_PREFIX "HG_UNFILLED_" #define FILLED_PREFIX "HG_FILLED_" #define PREFIX "HG_" extern bool UseWholeBars = false; extern int WRB_LookBackBarCount = 3; extern int WRB_WingDingsSymbol = 115; extern color HGcolor1 = clrDodgerBlue; extern color HGcolor2 = clrBlue; extern ENUM_LINE_STYLE HGstyle = STYLE_SOLID; extern int StartCalculationFromBar = 100; extern bool HollowBoxes = false; extern bool DoAlerts = false; //---- buffers double WRB[]; int totalBarCount = -1; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { //---- indicators IndicatorBuffers(1); IndicatorShortName("WRB+HG"); SetIndexStyle(0, DRAW_ARROW); SetIndexArrow(0, WRB_WingDingsSymbol); SetIndexLabel(0, "WRB"); SetIndexBuffer(0, WRB); ArrayInitialize(WRB, EMPTY_VALUE); return(0); } //+------------------------------------------------------------------+ //| Delete all objects with given prefix | //+------------------------------------------------------------------+ void ObDeleteObjectsByPrefix(string Prefix) { int L = StringLen(Prefix); int i = 0; while(i < ObjectsTotal()) { string ObjName = ObjectName(i); if(StringSubstr(ObjName, 0, L) != Prefix) { i++; continue; } ObjectDelete(ObjName); } } //+------------------------------------------------------------------+ //| intersect: Check two bars intersect or not | //+------------------------------------------------------------------+ int intersect(double H1, double L1, double H2, double L2) { if ( (L1>H2) || (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: Check if the hidden gap is filled or not | //+------------------------------------------------------------------+ void checkHGFilled(int barNumber) { int j, i; string ObjectText; string Prefix = UNFILLED_PREFIX; double box_H, box_L; double HGFillPA_H, HGFillPA_L; datetime startTime; color objectColor; int L = StringLen(Prefix); i = 0; while(i < ObjectsTotal()) // loop over all unfilled boxes { string ObjName = ObjectName(i); if(StringSubstr(ObjName, 0, L) != Prefix) { i++; continue; } box_H=ObjectGet(ObjName, OBJPROP_PRICE1); // get HG high and low values box_L=ObjectGet(ObjName, OBJPROP_PRICE2); objectColor=ObjectGet(ObjName, OBJPROP_COLOR); startTime=ObjectGet(ObjName, OBJPROP_TIME1); HGFillPA_H = High[barNumber]; HGFillPA_L = Low[barNumber]; j = 0; while ( (intersect(High[barNumber+j], Low[barNumber+j], box_H, box_L)!=0) && (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_Lbody) { WRB_test = false; break; } } if (WRB_test) { if (UseWholeBars) WRB[i] = (High[i] + Low[i]) / 2; else WRB[i] = (Open[i] + Close[i]) / 2; } else WRB[i] = EMPTY_VALUE; return(WRB_test); } //+------------------------------------------------------------------+ //| checkHG: Checks HG status of the previous bar. | //+------------------------------------------------------------------+ void checkHG(int i) { string ObjectText; double H,L,H2,L2,H1,L1,A,B; int j; color HGcolor=HGcolor1; // 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 { H2 = High[i+2]; L2 = Low[i+2]; H1 = High[i]; L1 = Low[i]; if (UseWholeBars) { 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) { int Length = StringLen(UNFILLED_PREFIX); j = 0; while(j < ObjectsTotal()) // loop over all unfilled boxes { ObjectText = ObjectName(j); if(StringSubstr(ObjectText, 0, Length) != UNFILLED_PREFIX) { j++; continue; } // Switch colors if the new Hidden Gap is intersecting with previous Hidden Gap. if (intersect(ObjectGet(ObjectText, OBJPROP_PRICE1),ObjectGet(ObjectText, OBJPROP_PRICE2),A,B)!=0) { HGcolor = ObjectGet(ObjectText, OBJPROP_COLOR); if (HGcolor==HGcolor1) HGcolor=HGcolor2; else HGcolor=HGcolor1; break; } j++; } ObjectText = UNFILLED_PREFIX + TimeToStr(Time[i+1],TIME_DATE|TIME_MINUTES); ObjectCreate(ObjectText, OBJ_RECTANGLE, 0, Time[i+1], A, TimeCurrent() + 10 * 365 * 24 * 60 * 60, B); ObjectSet(ObjectText, OBJPROP_STYLE, HGstyle); ObjectSet(ObjectText, OBJPROP_COLOR, HGcolor); ObjectSet(ObjectText, OBJPROP_BACK, !HollowBoxes); } } //End of HG-Test } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ int deinit() { ObDeleteObjectsByPrefix(PREFIX); return(0); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ void start() { if (DoAlerts) CheckAlert(); // A new bar started. if (totalBarCount != Bars) { int begin = Bars - IndicatorCounted(); // Need at least WRB_LookBackBarCount bars from the end of the chart to work. if (begin > Bars - WRB_LookBackBarCount) begin = Bars - WRB_LookBackBarCount; // Maximum number of bars to calculate is StartCalculationFromBar. if (begin > StartCalculationFromBar) begin = StartCalculationFromBar; for (int i = begin; i > 0; i--) { checkWRB(i); checkHG(i); checkHGFilled(i); } totalBarCount = Bars; } // Additional check to see if current bar made the Hidden Gap filled. checkHGFilled(0); WRB[0] = EMPTY_VALUE; } void CheckAlert() { int total = ObjectsTotal(); // Loop over all unfilled boxes. for (int j = 0; j < total; j++) { string ObjectText = ObjectName(j); // Object marked as alerted. if (StringSubstr(ObjectText, StringLen(ObjectText) - 1, 1) == "A") { // Try to find a dupe object (could be result of a bug) and delete it. string ObjectNameWithoutA = StringSubstr(ObjectText, 0, StringLen(ObjectText) - 1); if (ObjectFind(ObjectNameWithoutA) >= 0) ObjectDelete(ObjectNameWithoutA); continue; } int Length = StringLen(UNFILLED_PREFIX); if (StringSubstr(ObjectText, 0, Length) != UNFILLED_PREFIX) continue; double Price1 = ObjectGet(ObjectText, OBJPROP_PRICE1); double Price2 = ObjectGet(ObjectText, OBJPROP_PRICE2); double bHigh = MathMax(Price1, Price2); double bLow = MathMin(Price1, Price2); // Current price above lower border if ((Ask > bLow) && (Bid < bHigh)) { Alert(Symbol() + ": " + "WRB rectangle breached."); PlaySound("alert.wav"); ObjectSetString(0, ObjectText, OBJPROP_NAME, ObjectText + "A"); return; } } } //+------------------------------------------------------------------+