From fb03a1c88ad97bad7e48e9f86ea146aad846fc12 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Tue, 6 Jan 2026 02:20:25 +0330 Subject: [PATCH] last ... --- Documents/Diagrams/MQL5.X121XKI.Board.kanban | 21 +- Libraries/x-saherelm.x-poi.lib.mq5 | 162 +++++ X121XKIEA/Backup/Strategy1.XAUUSD.bkp.mq5 | 621 ++++++++++++++++++ .../x-saherelm.x121.xki.signaller.class.mq5 | 171 ++++- ...saherelm.x121.xki.x-poi.detector.class.mq5 | 520 ++++++++++++++- 5 files changed, 1467 insertions(+), 28 deletions(-) create mode 100644 X121XKIEA/Backup/Strategy1.XAUUSD.bkp.mq5 diff --git a/Documents/Diagrams/MQL5.X121XKI.Board.kanban b/Documents/Diagrams/MQL5.X121XKI.Board.kanban index 3f349bdc..09313d18 100644 --- a/Documents/Diagrams/MQL5.X121XKI.Board.kanban +++ b/Documents/Diagrams/MQL5.X121XKI.Board.kanban @@ -8,7 +8,17 @@ { "id": "61ca33e6-05e4-4b44-b88d-3bc8ae5cba86", "title": "To Do", - "cards": [] + "cards": [ + { + "id": "a59a73f4-1ab4-477b-893e-b2dfb71fe6ea", + "listId": "61ca33e6-05e4-4b44-b88d-3bc8ae5cba86", + "title": "Add Support for PV in XKI Indicator.", + "description": "", + "labels": [], + "checkboxes": [], + "comments": [] + } + ] }, { "id": "6f8db3d6-fcaa-4522-bee5-0e3e38c96e73", @@ -38,6 +48,15 @@ } ], "comments": [] + }, + { + "id": "bad677c0-a119-4f44-be8b-185fc4c996c7", + "listId": "6f8db3d6-fcaa-4522-bee5-0e3e38c96e73", + "title": "add Targets in strategy 1", + "description": "use Guards Instead of Targets.", + "labels": [], + "checkboxes": [], + "comments": [] } ] }, diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index 080fae90..e085a15e 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -318,6 +318,101 @@ int GetAllBarPatters(ENUM_X_BAR_PATTERN &dest[]) return ArraySize(dest); } +/** + * Get All Available Valid Bar Patterns ... + * + * @param dest: ENUM_X_BAR_PATTERN, collection reference to Fill Patterns ... + * @param dir: ENUM_X_DIRECTION, collection reference to Fill Directions ... + * @param forDir: ENUM_X_DIRECTION, Force Patterns Direction ... + * + * @return ( int ) + */ +int GetAllBarPatters( + ENUM_X_BAR_PATTERN &dest[], + ENUM_X_DIRECTION &dir[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // +) +{ + // + XClean(dest); + XClean(dir); + + // + Add(X_BAR_PATTERN_HIGH, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_LOW, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_MOMENTUM, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_ENGULFED, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_TRUE_GAPED, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_PINNED, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_STAR, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_PIERCING, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_RISING, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_FLAG, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_SIGNALKEY, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_OB, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_FVG, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_SUPPORT, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_RESISTANCE, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_PULLBACK, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_CONSOLIDATION, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_LEG, dest); + Add(forDir, dir); + + // + return ArraySize(dest); +} + /** * Fill Required Candlestick Patters ... * @@ -352,6 +447,73 @@ int GetCandlestickPatterns(ENUM_X_BAR_PATTERN &dest[]) return result; } +/** + * Fill Required Candlestick Patters ... + * + * @param dest: ENUM_X_BAR_PATTERN, collection reference to Fill Patterns ... + * @param dir: ENUM_X_DIRECTION, collection reference to Fill Directions ... + * @param forDir: ENUM_X_DIRECTION, Force Patterns Direction ... + * + * @return ( int ) + */ +int GetCandlestickPatterns( + ENUM_X_BAR_PATTERN &dest[], + ENUM_X_DIRECTION &dir[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // +) +{ + // + int result = 0; + + // + // Prepare ... + XClean(dest); + XClean(dir); + + // + Add(X_BAR_PATTERN_STAR, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_FLAG, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_PINNED, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_RISING, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_MOMENTUM, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_ENGULFED, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_PIERCING, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_SIGNALKEY, dest); + Add(forDir, dir); + + // + Add(X_BAR_PATTERN_TRUE_GAPED, dest); + Add(forDir, dir); + + + // + result = ArraySize(dest); + + // + return result; +} + // // Structures ... diff --git a/X121XKIEA/Backup/Strategy1.XAUUSD.bkp.mq5 b/X121XKIEA/Backup/Strategy1.XAUUSD.bkp.mq5 new file mode 100644 index 00000000..cbc969e9 --- /dev/null +++ b/X121XKIEA/Backup/Strategy1.XAUUSD.bkp.mq5 @@ -0,0 +1,621 @@ + /** + * Check Bar Has Signal Based on Strategy 1 ... + * POI ... + * + * @param bar: XOHCL, reference to Bar ... + * @param zone: XBoxZone, reference to holds affected zone ... + * @param targets: XTarget, reference to detected Signal's Targets collections ... + * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int scoreBullish = 0; + int scoreBearish = 0; + bool isBullish = false; + bool isBearish = false; + int barIndex = bar.Index() + 1; + + // + // Initialize Indexed Bar ... + XOHCL iBar; + result = iBar.Init(bar.symbol, bar.period, barIndex); + if (!result) + { + return result; + } + + // #region Reading Conditions and Scoring ... + // + // ATR ... + bool isATRUp = kiParser.IsVolatilityHigh(barIndex) || + kiParser.IsVolatilitySwitchdToHigh(barIndex); + + // #region KI ... + // + bool isKIReadyForBullish = ((kiParser.IsKIFastBearish(barIndex) || + (kiParser.IsKIFastBullish(barIndex) && + iBar.IsRejected(kiHelper.GetKIFast(barIndex), X_DIRECTION_BULLISH))) && + kiParser.IsKISlowBullish(barIndex)); + + // + bool isKIReadyForBearish = ((kiParser.IsKIFastBullish(barIndex) || + (kiParser.IsKIFastBearish(barIndex) && + iBar.IsRejected(kiHelper.GetKIFast(barIndex), X_DIRECTION_BEARISH))) && + kiParser.IsKISlowBearish(barIndex)); + + // + bool isKIBandBullish = (kiHelper.GetKIUpper(barIndex) > kiHelper.GetKIUpper(barIndex + 1) || + kiHelper.GetKILower(barIndex) > kiHelper.GetKILower(barIndex + 1)); + + // + bool isKIBandBearish = (kiHelper.GetKIUpper(barIndex) < kiHelper.GetKIUpper(barIndex + 1) || + kiHelper.GetKILower(barIndex) < kiHelper.GetKILower(barIndex + 1)); + + // + bool isKIBullish = (kiParser.IsKIFastBullish(barIndex) || + kiParser.IsKIFastSwitchedToBullish(barIndex)) && + (kiParser.IsKISlowBullish(barIndex) || + kiParser.IsKISlowSwitchedToBullish(barIndex)); + if (isKIBullish) + { + scoreBullish++; + } + + // + bool isKIBearish = (kiParser.IsKIFastBearish(barIndex) || + kiParser.IsKIFastSwitchedToBearish(barIndex)) && + (kiParser.IsKISlowBearish(barIndex) || + kiParser.IsKISlowSwitchedToBearish(barIndex)); + if (isKIBearish) + { + scoreBearish++; + } + // #endregion + + // #region KI Wave ... + // + bool isKIWaveBullish = kiParser.IsKIWaveBullish(barIndex) || + kiParser.IsKIWaveSwitchedToBullish(barIndex); + if (isKIWaveBullish) + { + scoreBullish++; + } + + // + bool isKIWaveBearish = kiParser.IsKIWaveBearish(barIndex) || + kiParser.IsKIWaveSwitchedToBearish(barIndex); + if (isKIWaveBearish) + { + scoreBearish++; + } + // #endregion + + // #region MA ... + // + bool isMaBullish = kiParser.IsMACrossoverBullish(barIndex) || + kiParser.IsMACrossoverSwitchedToBullish(barIndex); + if (isMaBullish) + { + scoreBullish++; + } + + // + bool isMaBearish = kiParser.IsMACrossoverBearish(barIndex) || + kiParser.IsMACrossoverSwitchedToBearish(barIndex); + if (isMaBearish) + { + scoreBearish++; + } + // #endregion + + // #region LowerTF Candlstick ... + // + bool isLowerTFBullish = IsTFBullishPattern(barIndex, PERIOD_M5); + if (isLowerTFBullish) + { + scoreBullish++; + } + + // + bool isLowerTFBearish = IsTFBearishPattern(barIndex, PERIOD_M5); + if (isLowerTFBearish) + { + scoreBearish++; + } + // #endregion + + // #region Candlestick ... + // + bool isCandlestickBullish = poiDetector.HasCandlestickDirection( + iBar, + X_DIRECTION_BULLISH // + ); + if (isCandlestickBullish) + { + scoreBullish++; + } + + // + bool isCandlestickBearish = poiDetector.HasCandlestickDirection( + iBar, + X_DIRECTION_BEARISH // + ); + if (isCandlestickBearish) + { + scoreBearish++; + } + // #endregion + // #endregion + + // #region Summarize Directional Conditions ... + // + isBullish = + isATRUp && + isLowerTFBullish && + isKIReadyForBullish && + isCandlestickBullish && + scoreBullish >= 2 && + (isKIBullish || + isMaBullish || + isKIWaveBullish || + isKIBandBullish); + + // + isBearish = + isATRUp && + isLowerTFBearish && + isKIReadyForBearish && + isCandlestickBearish && + scoreBearish >= 2 && + (isKIBearish || + isMaBearish || + isKIWaveBearish || + isKIBandBearish); + // #endregion + + // + // Validate Conditions ... + result = isBullish || isBearish; + if (!result) + { + // + iBar.Clean(); + + // + return result; + } + + // + // Select Operational Zone ... + if (isBullish) + { + // + // Looking Bar Patterns to Detect Zone ... + poiDetector.HasRecentPatternTouched(zone, iBar.close, barIndex, 5, 5, iBar.period, X_DIRECTION_BULLISH); + } + else if (isBearish) + { + // + // Looking Bar Patterns to Detect Zone ... + poiDetector.HasRecentPatternTouched(zone, iBar.close, barIndex, 5, 5, iBar.period, X_DIRECTION_BEARISH); + } + + // + // Refactor Result ... + result = result && + zone.IsValid(); + if (result) + { + // + // Refine Zone ... + poiDetector.RefineZone(zone); + + // + // SL Refactoring ... + + // + XOHCL toBar; + if (zone.ToBar(toBar)) + { + // + int to = zone.ToIndex(); + int from = zone.FromIndex(); + int length = from - to; + double iValue = + isBullish + ? toBar.FindLowest(length, MODE_LOW) + : isBearish + ? toBar.FindHighest(length, MODE_HIGH) + : EMPTY_VALUE; + if (NotEmptyZero(iValue)) + { + // + if (isBullish) + { + zone.lower = MathMin(zone.lower, iValue); + } + + // + if (isBearish) + { + zone.upper = MathMax(zone.upper, iValue); + } + } + } + toBar.Clean(); + } + + // + // Do Directional Validation ... + if (result) + { + // + // Bullish ... + if (isBullish) + { + // + isBullish = + isBullish && + isLowerTFBullish && + isCandlestickBullish; + } + + // + // Bearish ... + if (isBearish) + { + // + isBearish = + isBearish && + isLowerTFBearish && + isCandlestickBearish; + } + + // + result = isBullish || isBearish; + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Validate Result ... + if (!result) + { + // + iBar.Clean(); + + // + return result; + } + + // + // Draws ... + bool draw = true; + if (draw && result) + { + // + int drawn = 0; + + // + XPOIDrawConfig config; + config.Default(); + + // + if (zone.IsValid()) + { + // + drawn++; + + // + config.zonesWidth = 3; + config.bullishColor = clrYellow; + config.bearishColor = clrOrange; + + // + poiDrawer.DrawZone(zone, config); + + // + config.Default(); + } + + // + config.Clean(); + + // + if (drawn > 0) + { + // DebugBreak(); + } + } + + // + // Check and Prepare Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = result && + HasDirection(dir); + if (!result) + { + // + iBar.Clean(); + + // + return result; + } + + // + // Prepare Zone ... + double entry = GetEntry(iBar.symbol, dir); + if (result) + { + // + double upper = isBullish + ? entry + : zone.upper; + double lower = isBullish + ? zone.lower + : entry; + datetime to = bar.time; + datetime from = isBullish + ? zone.from + : zone.from; + result = zone.Init( + iBar.symbol, + iBar.period, + upper, + lower, + from, + to, + dir, + "XS1" // + ); + } + + // + // Cleanup Resources ... + iBar.Clean(); + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + +bool HasRecentPatternTouched( + XBoxZone &zone, + double price, + int barIndex = 0, + int loopback = 5, + int threshold = 5, + ENUM_TIMEFRAMES forPeriod = NULL, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + zone.Clean(); + + // + // Validate ... + result = NotEmptyZero(price); + if (!result) + { + return result; + } + + // + // Normalize ... + loopback = NormalizeInt(loopback, 2); + barIndex = kiParser.NormalizeBarIndex(barIndex); + if (IsXValid(forPeriod)) + { + forPeriod = period; + } + + // + XOHCL iBar; + bool has = false; + int iBullishIDX = -1; + int iBearishIDX = -1; + bool isBullish = false; + bool isBearish = false; + XBoxZone iBullishZones[]; + XBoxZone iBearishZones[]; + XPatternAnalysis iAnalysis; + XPatternAnalysisConfig iConfig; + + // + // Preparing Pattern Analysis Config ... + iConfig.Default(); + + // + // Customize Patterns ... + // iConfig.FullPattern(); + + // + // iConfig.AddPattern(X_BAR_PATTERN_OB); + // iConfig.AddPattern(X_BAR_PATTERN_PINNED); + // iConfig.AddPattern(X_BAR_PATTERN_ENGULFED); + // iConfig.AddPattern(X_BAR_PATTERN_SIGNALKEY); + + // + // iConfig.AddPattern(X_BAR_PATTERN_FVG); + // iConfig.AddPattern(X_BAR_PATTERN_PIERCING); + + // + // iConfig.AddPattern(X_BAR_PATTERN_STAR); + // iConfig.AddPattern(X_BAR_PATTERN_RISING); + // iConfig.AddPattern(X_BAR_PATTERN_MOMENTUM); + // iConfig.AddPattern(X_BAR_PATTERN_CONSOLIDATION); + // iConfig.AddPattern(X_BAR_PATTERN_LOW, X_DIRECTION_BULLISH); + // iConfig.AddPattern(X_BAR_PATTERN_HIGH, X_DIRECTION_BEARISH); + // iConfig.AddPattern(X_BAR_PATTERN_SUPPORT); + // iConfig.AddPattern(X_BAR_PATTERN_RESISTANCE); + + // + // XAUUSD ... + iConfig.AddPattern(X_BAR_PATTERN_FVG); + iConfig.AddPattern(X_BAR_PATTERN_PIERCING); + + // + // Looping Back ... + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Initialize Bar ... + has = iBar.Init(symbol, forPeriod, i); + if (!has) + { + continue; + } + + // + // Analyse Patterns ... + has = AnalyseBarPatterns(iBar, iAnalysis, iConfig); + if (!has) + { + // + iBar.Clean(); + continue; + } + + // + // Bullish ... + has = iAnalysis.Count(X_DIRECTION_BULLISH) > 0; + if (has) + { + // + iAnalysis.GetPatterns(iBullishZones, X_DIRECTION_BULLISH); + has = HasChild(iBullishZones); + if (has) + { + // + has = HasNearZone( + iBullishIDX, + price, + threshold, + iBullishZones // + ); + if (has) + { + isBullish = true; + } + } + } + + // + // Bearish ... + has = iAnalysis.Count(X_DIRECTION_BEARISH) > 0; + if (has) + { + // + iAnalysis.GetPatterns(iBearishZones, X_DIRECTION_BEARISH); + has = HasChild(iBearishZones); + if (has) + { + // + has = HasNearZone( + iBearishIDX, + price, + threshold, + iBearishZones // + ); + if (has) + { + isBearish = true; + } + } + } + + // + // Summarizing Result ... + has = + HasDirection(forDir) + ? (isBullish && !isBearish && IsXBullish(forDir)) || + (isBearish && !isBullish && IsXBearish(forDir)) + : (isBullish && !isBearish) || (isBearish && !isBullish); + if (has) + { + // + // Fill Zones ... + if (isBullish) + { + zone = iBullishZones[iBullishIDX]; + } + else + { + zone = iBearishZones[iBearishIDX]; + } + break; + } + + // + // Cleanup Resource ... + iBar.Clean(); + iAnalysis.Clean(); + XClean(iBullishZones); + XClean(iBearishZones); + } + + // + // Cleanup Resources ... + iBar.Clean(); + iConfig.Clean(); + iAnalysis.Clean(); + XClean(iBullishZones); + XClean(iBearishZones); + + // + return result; + } + + +// +// XAUUSD ... + +// // +// // FVG ... +// Add(X_BAR_PATTERN_FVG, patterns); +// Add(X_DIRECTION_NONE, patternsDir); + +// // +// // Piercing ... +// Add(X_BAR_PATTERN_PIERCING, patterns); +// Add(X_DIRECTION_NONE, patternsDir); + diff --git a/X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5 b/X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5 index 234fae86..5f6d407a 100644 --- a/X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5 +++ b/X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5 @@ -988,6 +988,29 @@ class XCX121XKIStrategy1Signaller : public XCX121XKIBaseSignaller return result; } + // #region Swings/OrderFlow ... + // + // Swings ... + XBoxZone swingLow; + XBoxZone swingHigh; + bool hasSwings = poiDetector.DetectRecentSwings( + swingHigh, + swingLow, + barIndex // + ); + + // + // Order Flow ... + + // + XBoxZone bullishOrderFlow[]; + result = poiDetector.HasOrderFlow(bullishOrderFlow, barIndex, 4, X_DIRECTION_BULLISH, 15); + + // + XBoxZone bearishOrderFlow[]; + result = poiDetector.HasOrderFlow(bearishOrderFlow, barIndex, 4, X_DIRECTION_BEARISH, 15); + // #endregion + // #region Reading Conditions and Scoring ... // // ATR ... @@ -1150,24 +1173,96 @@ class XCX121XKIStrategy1Signaller : public XCX121XKIBaseSignaller } // - if (result) - { - // DebugBreak(); - } + // Select Operational Zone ... + ENUM_X_DIRECTION patternsDir[]; + ENUM_X_BAR_PATTERN patterns[]; // - // Select Operational Zone ... + GetAllBarPatters(patterns, patternsDir); + + // + // XAUUSD ... + + // // + // // FVG ... + // Add(X_BAR_PATTERN_FVG, patterns); + // Add(X_DIRECTION_NONE, patternsDir); + + // // + // // Piercing ... + // Add(X_BAR_PATTERN_PIERCING, patterns); + // Add(X_DIRECTION_NONE, patternsDir); + + // + // EURUSD ... + + // + // Add(X_BAR_PATTERN_STAR, patterns); + // Add(X_DIRECTION_NONE, patternsDir); + + // // + // Add(X_BAR_PATTERN_SUPPORT, patterns); + // Add(X_DIRECTION_NONE, patternsDir); + + // // + // Add(X_BAR_PATTERN_RESISTANCE, patterns); + // Add(X_DIRECTION_NONE, patternsDir); + + // + // Add(X_BAR_PATTERN_SIGNALKEY, patterns); + // Add(X_DIRECTION_NONE, patternsDir); + + // + int nearestOrderFlowIDX = -1; if (isBullish) { // // Looking Bar Patterns to Detect Zone ... - poiDetector.HasRecentPatternTouched(zone, iBar.close, barIndex, 5, 5, iBar.period, X_DIRECTION_BULLISH); + isBullish = + isBullish && + HasChild(bullishOrderFlow) && + poiDetector.HasNearZone( + nearestOrderFlowIDX, + iBar.close, + 5, + bullishOrderFlow // + ) && + poiDetector.HasRecentPatternTouched( + zone, + patterns, + patternsDir, + iBar.close, + barIndex, + 5, + 5, + iBar.period, + X_DIRECTION_BULLISH // + ); } else if (isBearish) { // // Looking Bar Patterns to Detect Zone ... - poiDetector.HasRecentPatternTouched(zone, iBar.close, barIndex, 5, 5, iBar.period, X_DIRECTION_BEARISH); + isBearish = + isBearish && + HasChild(bearishOrderFlow) && + poiDetector.HasNearZone( + nearestOrderFlowIDX, + iBar.close, + 5, + bearishOrderFlow // + ) && + poiDetector.HasRecentPatternTouched( + zone, + patterns, + patternsDir, + iBar.close, + barIndex, + 5, + 5, + iBar.period, + X_DIRECTION_BEARISH // + ); } // @@ -1293,13 +1388,45 @@ class XCX121XKIStrategy1Signaller : public XCX121XKIBaseSignaller } // - config.Clean(); + if (swingLow.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(swingLow, config); + } + + // + if (swingHigh.IsValid()) + { + // + drawn++; + poiDrawer.DrawZone(swingHigh, config); + } + + // + if (HasChild(bullishOrderFlow)) + { + // + drawn += ArraySize(bullishOrderFlow); + poiDrawer.DrawZones(bullishOrderFlow, config); + } + + // + if (HasChild(bearishOrderFlow)) + { + // + drawn += ArraySize(bearishOrderFlow); + poiDrawer.DrawZones(bearishOrderFlow, config); + } // if (drawn > 0) { // DebugBreak(); } + + // + config.Clean(); } // @@ -1311,20 +1438,12 @@ class XCX121XKIStrategy1Signaller : public XCX121XKIBaseSignaller : X_DIRECTION_NONE; result = result && HasDirection(dir); - if (!result) - { - // - iBar.Clean(); - - // - return result; - } - - // - // Prepare Zone ... - double entry = GetEntry(iBar.symbol, dir); if (result) { + // + // Prepare Zone ... + double entry = GetEntry(iBar.symbol, dir); + // double upper = isBullish ? entry @@ -1348,12 +1467,15 @@ class XCX121XKIStrategy1Signaller : public XCX121XKIBaseSignaller ); } - // #region Preparing Target ... - // #endregion - // // Cleanup Resources ... iBar.Clean(); + swingLow.Clean(); + XClean(patterns); + swingHigh.Clean(); + XClean(patternsDir); + XClean(bullishOrderFlow); + XClean(bearishOrderFlow); // result = @@ -1371,7 +1493,8 @@ class XCX121XKIStrategy1Signaller : public XCX121XKIBaseSignaller * * @return ( bool ) */ - bool Strategy2HasSignal( + bool + Strategy2HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], diff --git a/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5 b/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5 index 09271821..c3edc7bb 100644 --- a/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5 +++ b/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5 @@ -1863,6 +1863,64 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector XClean(tmpResistances); } + bool HasStructure( + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forMinorPeriod = NULL, + ENUM_TIMEFRAMES forMajorPeriod = NULL, + int loopback = 50, + int minorValidation = 7, + int majorValidation = 14, + int minimumRetests = 2, + double retestThreshold = 10, + int retestLoopback = 100 // + ) + { + // + XBoxZone supports[]; + XBoxZone resistances[]; + XBoxZone minorSupport; + XBoxZone majorSupport; + XBoxZone minorResistance; + XBoxZone majorResistance; + + // + GetCurrentStructure( + supports, + resistances, + minorSupport, + majorSupport, + minorResistance, + majorResistance, + barIndex, + forSymbol, + forMinorPeriod, + forMajorPeriod, + loopback, + minorValidation, + majorValidation, + minimumRetests, + retestThreshold, + retestLoopback // + ); + + // + bool result = + majorSupport.IsValid() && + majorResistance.IsValid(); + + // + XClean(supports); + XClean(resistances); + minorSupport.Clean(); + majorSupport.Clean(); + minorResistance.Clean(); + majorResistance.Clean(); + + // + return result; + } + void RefineStructure( XBoxZone &supports[], XBoxZone &resistances[], @@ -2164,6 +2222,427 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector zone.from = zone.breakAt; } } + + bool DetectRecentSwings( + XBoxZone &swingHigh, + XBoxZone &swingLow, + int barIndex = 0, + int swingsValidationLength = 50, + int loopback = 500, + ENUM_TIMEFRAMES forPeriod = NULL, + bool forceRefineZones = true // + ) + { + // + swingLow.Clean(); + swingHigh.Clean(); + + // + loopback = NormalizeInt(loopback, 5); + barIndex = kiParser.NormalizeBarIndex(barIndex); + swingsValidationLength = NormalizeInt(swingsValidationLength, 5); + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + + // + XOHCL iBar; + int iIDX = -1; + double low = 0; + double high = 0; + int lowIDX = -1; + int highIDX = -1; + bool has = false; + double iValue = 0; + datetime lowAt = NULL; + datetime highAt = NULL; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + has = iBar.Init(symbol, forPeriod, i); + if (!has) + { + continue; + } + + // + iIDX = iBar.FindLowestIndex(swingsValidationLength, MODE_LOW); + has = IsValidIndex(iIDX); + if (has) + { + // + iValue = iLow(iBar.symbol, iBar.period, iIDX); + + // + // Check Can Set Low ... + has = (!NotEmptyZero(low) || + (NotEmptyZero(low) && iValue < low)) && + IsValidSwing( + iValue, + iIDX, + barIndex, + iBar.symbol, + iBar.period, + X_SWING_LOW // + ); + if (has) + { + // + low = iValue; + lowIDX = iIDX; + lowAt = iBar.time; + } + } + + // + iIDX = iBar.FindHighestIndex(swingsValidationLength, MODE_HIGH); + has = IsValidIndex(iIDX); + if (has) + { + // + iValue = iHigh(iBar.symbol, iBar.period, iIDX); + + // + // Check Can Set High ... + has = (!NotEmptyZero(high) || + (NotEmptyZero(high) && iValue > high)) && + IsValidSwing( + iValue, + iIDX, + barIndex, + iBar.symbol, + iBar.period, + X_SWING_HIGH // + ); + if (has) + { + // + high = iValue; + highIDX = iIDX; + highAt = iBar.time; + } + } + + // + iBar.Clean(); + } + + // + // Recent Low Swing ... + has = + IsXValid(lowAt) && + NotEmptyZero(low) && + IsValidIndex(lowIDX); + if (has) + { + // + has = iBar.Init(symbol, forPeriod, lowIDX); + has = has && + swingLow.Init( + iBar.symbol, + iBar.period, + iBar.GetDown(), + low, + GetBarTime(iBar.symbol, iBar.period, lowIDX + swingsValidationLength - 1), + GetBarTime(iBar.symbol, iBar.period, barIndex), + X_DIRECTION_BULLISH, + ToXString(X_BAR_PATTERN_LOW), + lowAt // + ); + if (has && forceRefineZones) + { + RefineZone(swingLow, 500, 5, X_PRICE_CLOSE); + } + } + + // + // Recent High Swing ... + has = + IsXValid(highAt) && + NotEmptyZero(high) && + IsValidIndex(highIDX); + if (has) + { + // + has = iBar.Init(symbol, forPeriod, highIDX); + has = has && + swingHigh.Init( + iBar.symbol, + iBar.period, + high, + iBar.GetUp(), + GetBarTime(iBar.symbol, iBar.period, lowIDX + swingsValidationLength - 1), + GetBarTime(iBar.symbol, iBar.period, barIndex), + X_DIRECTION_BEARISH, + ToXString(X_BAR_PATTERN_HIGH), + highAt // + ); + if (has && forceRefineZones) + { + RefineZone(swingHigh, 500, 5, X_PRICE_CLOSE); + } + } + + // + bool result = swingLow.IsValid() && + swingHigh.IsValid(); + + // + return result; + } + + bool HasOrderFlow( + XBoxZone &flow[], + int barIndex = 0, + int flowValidationLength = 5, + ENUM_X_DIRECTION flowDir = X_DIRECTION_NONE, + int loopback = 50, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL, + ENUM_X_BOUNDARY_PRICE priceType = X_BOUNDARY_PRICE_HIGH_LOW // + ) + { + // + bool result = false; + + // + XClean(flow); + + // + // Validate ... + result = + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Normalizing Data ... + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + loopback = NormalizeInt(loopback, 5); + barIndex = kiParser.NormalizeBarIndex(barIndex); + flowValidationLength = NormalizeInt(flowValidationLength, 2); + + // + // Handle Works ... + + // + XOHCL iBar; + int iIndex = -1; + bool has = false; + XBoxZone tmpZone; + double iPrice = 0; + ENUM_X_PRICE iPriceType; + bool isBullish = !HasDirection(flowDir) || IsXBullish(flowDir); + bool isBearish = !HasDirection(flowDir) || IsXBearish(flowDir); + + // + // Looping Reversal ... + int start = barIndex + loopback; + int end = barIndex; + for (int i = start; i > end; i--) + { + // + has = iBar.Init(forSymbol, forPeriod, i); + if (!has) + { + continue; + } + + // + // Check iBar is Low Swing ... + if (isBullish) + { + // + iPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_DOWN; + iPrice = iBar.GetPrice(iPriceType); + has = iPrice == iBar.FindLowest(iIndex, flowValidationLength, iPriceType); + has = has && + IsValidSwing( + iPrice, + iBar.Index(), + barIndex, + iBar.symbol, + iBar.period, + X_SWING_LOW // + ); + if (has) + { + // + // Flow Detected ... + tmpZone.Clean(); + iPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_DOWN + : X_PRICE_UP; + has = tmpZone.Init( + iBar.symbol, + iBar.period, + iBar.GetPrice(iPriceType), + iPrice, + iBar.time, + GetBarTime(iBar.symbol, iBar.period, barIndex), + X_DIRECTION_BULLISH, + ToXString(X_BAR_PATTERN_LOW) // + ); + if (has) + { + // + AddIfNotExists( + tmpZone, + flow // + ); + + // + tmpZone.Clean(); + } + } + } + + // + // Check iBar is High Swing ... + if (isBearish) + { + // + iPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_UP; + iPrice = iBar.GetPrice(iPriceType); + has = iPrice == iBar.FindHighest(iIndex, flowValidationLength, iPriceType); + has = has && + IsValidSwing( + iPrice, + iBar.Index(), + barIndex, + iBar.symbol, + iBar.period, + X_SWING_HIGH // + ); + if (has) + { + // + // Flow Detected ... + tmpZone.Clean(); + iPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_UP + : X_PRICE_DOWN; + has = tmpZone.Init( + iBar.symbol, + iBar.period, + iPrice, + iBar.GetPrice(iPriceType), + iBar.time, + GetBarTime(iBar.symbol, iBar.period, barIndex), + X_DIRECTION_BEARISH, + ToXString(X_BAR_PATTERN_HIGH) // + ); + if (has) + { + // + AddIfNotExists( + tmpZone, + flow // + ); + + // + tmpZone.Clean(); + } + } + } + + // + iBar.Clean(); + tmpZone.Clean(); + } + + // + result = HasChild(flow); + + // + return result; + } + + bool IsValidSwing( + double price, + int swingIDX, + int barIndex = 0, + string forSymbol = NULL, + ENUM_TIMEFRAMES forPeriod = NULL, + ENUM_X_SWING_TYPE swingType = X_SWING_NONE // + ) + { + // + bool result = false; + + // + result = + NotEmptyZero(price) && + IsXValid(swingType) && + IsValidIndex(swingIDX) && + swingIDX >= barIndex; + if (!result) + { + return result; + } + + // + if (!IsXValid(forSymbol)) + { + forSymbol = symbol; + } + if (!IsXValid(forPeriod)) + { + forPeriod = period; + } + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + XOHCL iBar; + bool has = false; + for (int i = barIndex; i <= (swingIDX - barIndex); i++) + { + // + has = iBar.Init(forSymbol, forPeriod, i); + if (!has) + { + continue; + } + + // + // Check Price Break ... + has = + (swingType == X_SWING_LOW && + iBar.low < price) || + (swingType == X_SWING_HIGH && + iBar.high > price); + if (has) + { + break; + } + + // + iBar.Clean(); + } + + // + result = !has && !iBar.IsValid(); + + // + iBar.Clean(); + + // + return result; + } // #endregion // #region VolatilitySwitchedHigh ... @@ -2196,12 +2675,29 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector // #endregion // #region Bar Patterns ... + /* + * Check Recently Pattern Zone is Touched or not ... + * + * @param zone: XBoxZone, Touched Zone ... + * @param patterns: ENUM_X_BAR_PATTERN, Allowed to Check Patterns ... + * @param patternsDir: ENUM_X_DIRECTION, Allowed Directions ... + * @param price: double, a Price to Check Toch or Reject ... + * @param barIndex: int, Bar Index to Start Checking ... + * @param loopback: int, Loopback for Pattern Formations ... + * @param threshold: double, threshold for Pattern touch ... + * @param forPeriod: ENUM_TIMEFRAMES, Time Frame to Check Patterns ... + * @param forDir: ENUM_X_DIRECTION, Directions for Pattern's Formation Check ... + * + * @return ( bool ) + */ bool HasRecentPatternTouched( XBoxZone &zone, + ENUM_X_BAR_PATTERN &patterns[], + ENUM_X_DIRECTION &patternsDir[], double price, int barIndex = 0, int loopback = 5, - int threshold = 5, + double threshold = 5, ENUM_TIMEFRAMES forPeriod = NULL, ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // ) @@ -2214,7 +2710,11 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector // // Validate ... - result = NotEmptyZero(price); + result = + HasChild(patterns) && + NotEmptyZero(price) && + HasChild(patternsDir) && + ArraySize(patterns) == ArraySize(patternsDir); if (!result) { return result; @@ -2244,7 +2744,21 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector // // Preparing Pattern Analysis Config ... iConfig.Default(); - iConfig.FullPattern(); + + // + Copy( + patterns, + iConfig.allowedPatterns // + ); + Copy( + patternsDir, + iConfig.allowedDirs // + ); + + // + // XAUUSD ... + iConfig.AddPattern(X_BAR_PATTERN_FVG); + iConfig.AddPattern(X_BAR_PATTERN_PIERCING); // // Looping Back ...