From 0a59459e8d7b31075e692cb780dd278a8091b2d4 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Mon, 29 Sep 2025 19:43:49 +0330 Subject: [PATCH] last works on Testing XHK Zones ... --- Helpers/x-saherelm.xfima.helper.mq5 | 423 ++++++++++++++++++ .../x-saherelm.xfima.signaller.class.mq5 | 145 ++++-- 2 files changed, 531 insertions(+), 37 deletions(-) diff --git a/Helpers/x-saherelm.xfima.helper.mq5 b/Helpers/x-saherelm.xfima.helper.mq5 index 9c094d4a..75967c10 100644 --- a/Helpers/x-saherelm.xfima.helper.mq5 +++ b/Helpers/x-saherelm.xfima.helper.mq5 @@ -1966,6 +1966,244 @@ class XCXFIMAHelper : public XCBaseHelper return result; } + /** + * Extract Validated Zones ... + * + * @param zones: XBoxZone, collection reference to holds results ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFZones: int, required Number of Zones ... + * @param shadowMultiplier: double a Shadow Multiplier for Validation ... + * @param validationStrength: double, Minimum Strngth Multiplier in Point to Validate ... + * @param validationLength: int, Validation Length of Zones ... + * @param maxAllowedLoopbackLength: int, max Allowed Loopback Length ... + * + * @return ( int ) + */ + int ExtractHKZones( + XBoxZone &zones[], + int barIndex = 0, + int requiredNumberOFZones = 50, + double shadowMultiplier = 3, + double validationStrength = 1, + int validationLength = 21, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(zones); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 7); + shadowMultiplier = NormalizeDouble(shadowMultiplier, 1); + validationStrength = NormalizeDouble(validationStrength, 1); + requiredNumberOFZones = NormalizeInt(requiredNumberOFZones, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 100); + + // + // Reading Values ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + double minAllowedStrength = (validationStrength * GetPoints(symbol)); + + // + int count = 0; + XBoxZone zone; + double hkLows[]; + bool has = false; + double hkOpens[]; + double hkHighs[]; + double hkCloses[]; + int start = barIndex; + double up = EMPTY_VALUE; + double down = EMPTY_VALUE; + double body = EMPTY_VALUE; + double range = EMPTY_VALUE; + bool lowShadowPassed = false; + bool highShadowPassed = false; + double lowShadow = EMPTY_VALUE; + double highShadow = EMPTY_VALUE; + double startHKLow = EMPTY_VALUE; + double startHKOpen = EMPTY_VALUE; + double startHKHigh = EMPTY_VALUE; + double startHKClose = EMPTY_VALUE; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + int end = start + maxAllowedLoopbackLength; + for (int i = start; i < end; i++) + { + // + // Cleanup ... + zone.Clean(); + dir = X_DIRECTION_NONE; + + // + // Reading HK Buffesr ... + count = ReadHKBars( + hkOpens, + hkHighs, + hkLows, + hkCloses, + i, + 1 // + ); + has = IsValidSize(count); + if (!has) + { + continue; + } + + // + if (i == start) + { + // + startHKLow = hkLows[0]; + startHKOpen = hkOpens[0]; + startHKHigh = hkHighs[0]; + startHKClose = hkCloses[0]; + } + + // + // Check Direction ... + bool isBullish = hkOpens[0] < hkCloses[0]; + bool isBearish = hkOpens[0] > hkCloses[0]; + dir = + (isBullish && !isBearish) + ? X_DIRECTION_BULLISH + : (isBearish && !isBullish) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(dir); + if (!has) + { + continue; + } + + // + // Check High Shadows and Low Shadows ... + up = isBullish + ? hkCloses[0] + : hkOpens[0]; + down = isBullish + ? hkOpens[0] + : hkCloses[0]; + body = MathAbs(up - down); + range = hkHighs[0] - hkLows[0]; + highShadow = hkHighs[0] - up; + lowShadow = down - hkLows[0]; + + // + // Detecting Shadows ... + + // + // Low Shadow ... + lowShadowPassed = lowShadow >= (shadowMultiplier * highShadow); + + // + // High Shadow ... + highShadowPassed = highShadow >= (shadowMultiplier * lowShadow); + + // + has = (lowShadowPassed && !highShadowPassed) || + (highShadowPassed && !lowShadowPassed); + if (!has) + { + continue; + } + + // + // Filling Zone ... + + // + zone.symbol = symbol; + zone.period = period; + zone.from = GetBarTime( + zone.symbol, + zone.period, + i // + ); + zone.dir = lowShadowPassed + ? X_DIRECTION_BULLISH + : highShadowPassed + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + zone.upper = + IsXBullish(zone.dir) + ? down + : IsXBearish(zone.dir) + ? hkHighs[0] + : EMPTY_VALUE; + + // + zone.lower = + IsXBullish(zone.dir) + ? hkLows[0] + : IsXBearish(zone.dir) + ? up + : EMPTY_VALUE; + + // + zone.to = TimeCurrent(); + zone.type = "XHK_" + (IsXBullish(zone.dir) ? "Support" : IsXBearish(zone.dir) ? "Resistance" + : "") + + "_" + ToXString(TimeToSeconds(zone.from)); + + // + // Validate ... + has = + zone.IsValid() && + HasDirection(zone.dir) && + NotEmptyZero(zone.upper) && + NotEmptyZero(zone.lower) && + (zone.IsBullish() + ? startHKLow > zone.upper + : startHKHigh < zone.lower) && + ValidateHKZone(zone, validationLength) && + (zone.upper - zone.lower) >= minAllowedStrength; + if (has) + { + // + AddIfNotExists( + zone, + zones // + ); + } + + // + // Cleanup Resources ... + zone.Clean(); + + // + // Validating ... + result = ArraySize(zones); + has = IsValidSize(result) && + count >= requiredNumberOFZones; + if (has) + { + break; + } + } + + // + // Cleanup Resources ... + zone.Clean(); + SpecifiedClean(hkLows); + SpecifiedClean(hkOpens); + SpecifiedClean(hkHighs); + SpecifiedClean(hkCloses); + + // + return result; + } + // // Values Retrievers ... @@ -3957,6 +4195,191 @@ class XCXFIMAHelper : public XCBaseHelper maxAllowed // ); } + + // + // XHK Helper ... + + // + int ReadHKBars( + double &open[], + double &high[], + double &low[], + double &close[], + int barIndex = 0, + int count = 1 // + ) + { + // + int result = 0; + + // + // Normalize ... + count = NormalizeInt(count, 1); + barIndex = NormalizeInt(barIndex, 0); + + // + // Open ... + CopyBuffer( + mHandler, + XFIMA_HK_OPEN_LINE, + barIndex, + count, + open // + ); + + // + // High ... + CopyBuffer( + mHandler, + XFIMA_HK_HIGH_LINE, + barIndex, + count, + high // + ); + + // + // Low ... + CopyBuffer( + mHandler, + XFIMA_HK_LOW_LINE, + barIndex, + count, + low // + ); + + // + // Close ... + CopyBuffer( + mHandler, + XFIMA_HK_CLOSE_LINE, + barIndex, + count, + close // + ); + + // + // Min Number of Array Sizes ... + result = MathMin(ArraySize(open), ArraySize(high)); + result = MathMin(result, ArraySize(close)); + result = MathMin(result, ArraySize(low)); + + // + return result; + } + + // + bool ValidateHKZone( + XBoxZone &zone, + int validationLength = 1 // + ) + { + // + bool result = false; + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 1); + + // + // Validate ... + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + double low[]; + double open[]; + double high[]; + int count = 0; + double close[]; + + // + // Validating Before ... + int start = zone.FromIndex() + 1; + int end = start + validationLength; + for (int i = start; i < end; i++) + { + // + // Reading HK ... + count = ReadHKBars( + open, + high, + low, + close, + i, + 1 // + ); + + // + result = IsValidSize(count); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? low[0] > zone.upper + : high[0] < zone.lower; + if (!result) + { + break; + } + } + + // + // Validating After ... + if (result) + { + // + start = zone.ToIndex() + 1; + count = zone.FromIndex() - start; + end = start + count; + for (int i = 0; i < end; i++) + { + // + // Reading HK ... + count = ReadHKBars( + open, + high, + low, + close, + i, + 1 // + ); + + // + result = IsValidSize(count); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? low[0] > zone.lower + : high[0] < zone.upper; + if (!result) + { + break; + } + } + } + + // + // Cleanup Resource ... + SpecifiedClean(low); + SpecifiedClean(open); + SpecifiedClean(high); + SpecifiedClean(close); + + // + return result; + } + + // }; // \ No newline at end of file diff --git a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 index 563ff6a6..ce459323 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -631,7 +631,6 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller ENUM_X_PRICE iPriceType = X_PRICE_NONE; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; - ENUM_X_DIRECTION iHKSwitchedDir = X_DIRECTION_NONE; // XPivot pvPivots[]; @@ -684,41 +683,6 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller analyserConfig // ); - // - // TODO: Testing ... - - // - double cHKO = fimaConditions.hkOpenBuffer[0]; - double cHKH = fimaConditions.hkHighBuffer[0]; - double cHKL = fimaConditions.hkLowBuffer[0]; - double cHKC = fimaConditions.hkCloseBuffer[0]; - - // - double pHKO = fimaConditions.hkOpenBuffer[1]; - double pHKH = fimaConditions.hkHighBuffer[1]; - double pHKL = fimaConditions.hkLowBuffer[1]; - double pHKC = fimaConditions.hkCloseBuffer[1]; - - // - bool isCHKBullish = cHKO < cHKC; - bool isCHKBearish = cHKO > cHKC; - - // - bool isPHKBullish = pHKO < pHKC; - bool isPHKBearish = pHKO > pHKC; - - // - bool isCHKSwitchedToBullish = isCHKBullish && !isPHKBullish; - bool isCHKSwitchedToBearish = isCHKBearish && !isPHKBearish; - - // - // Add this as Param in Strategy Finders for Using it ... - iHKSwitchedDir = isCHKSwitchedToBullish - ? X_DIRECTION_BULLISH - : isCHKSwitchedToBullish - ? X_DIRECTION_BEARISH - : X_DIRECTION_NONE; - // // Collect Support and Resistance Zones and Validate by them ... @@ -1196,6 +1160,43 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller ); } + // + // Calling Without Candlestick Patterns Strategies ... + + // + // Testing HK Zones ... + XBoxZone hkZones[]; + int hkCounts = fima2Signaller.fimaHelper.ExtractHKZones( + hkZones, + 1, // Bar Index ... + 50, // Number of Zones ... + 5, // Shadow Multiplier ... + 1, // Strength ... + 21 // Validation Length ... + ); + if (IsValidSize(hkCounts)) + { + // + XCBoxObject *iObj; + for (int i = 0; i < hkCounts; i++) + { + // + iObj = NULL; + bool isCreated = fima2Signaller.poiDrawer.DrawBox( + hkZones[i], + iObj, + true, // Ignore At ... + hkZones[i].type // Name ... + ); + + // + ZeroMemory(iObj); + } + + // + Print("HK Zones Detected ..."); + } + // // Check Required Pattern Exists ... bool hasPinnedBar = HasDirection(structure.pinnedDir); @@ -1779,7 +1780,7 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller } /** - * Check Pattern Has Signal Based on Strategy 1 ... + * Check Pattern Has Signal Based on Strategy 2 ... * * @param bar: XOHCL, reference to Pattern Bar ... * @param iZone: XBoxZone, reference to holds affected zone ... @@ -1809,6 +1810,7 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller // // Prepare ... + iZone.Clean(); // // Validate ... @@ -1826,6 +1828,75 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller return result; } + /** + * Check Pattern Has Signal Based on Strategy 1 ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param iZone: XBoxZone, reference to holds affected zone ... + * @param supports: XBoxZone, array reference to Provide Exists Supports ... + * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... + * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * + * @return ( bool ) + */ + bool Strategy3HasSignal( + XOHCL &bar, + XBoxZone &iZone, + XBoxZone &supports[], + XBoxZone &resistances[], + XFIMAMarketStructure &structure, + XFIMAConditions &fimaConditions // + ) + { + // + bool result = false; + + // + // Prepare ... + iZone.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Reading XHK ... + + // + // Bar 1 ... + double cHKO = fimaConditions.hkOpenBuffer[0]; + double cHKH = fimaConditions.hkHighBuffer[0]; + double cHKL = fimaConditions.hkLowBuffer[0]; + double cHKC = fimaConditions.hkCloseBuffer[0]; + + // + // Bar 2 ... + double pHKO = fimaConditions.hkOpenBuffer[1]; + double pHKH = fimaConditions.hkHighBuffer[1]; + double pHKL = fimaConditions.hkLowBuffer[1]; + double pHKC = fimaConditions.hkCloseBuffer[1]; + + // + bool isCHKBullish = cHKO < cHKC; + bool isCHKBearish = cHKO > cHKC; + + // + bool isPHKBullish = pHKO < pHKC; + bool isPHKBearish = pHKO > pHKC; + + // + bool isCHKSwitchedToBullish = isCHKBullish && !isPHKBullish; + bool isCHKSwitchedToBearish = isCHKBearish && !isPHKBearish; + + // + return result; + } + // };