From 31f1abb8d3bba3cc92f5ac98c44651f8dcd82505 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Mon, 27 Oct 2025 05:02:51 +0330 Subject: [PATCH] last works ... --- Classes/x-saherelm.x-guard.class.mq5 | 52 +- Classes/x-saherelm.x-market.pattern.class.mq5 | 94 + Classes/x-saherelm.x-poi.drawer.class.mq5 | 67 +- Documents/BKP/XFIMA Signals/Test.mq5 | 949 +++++ .../x-saherelm.xfima.signaller.class copy.mq5 | 3121 +++++++++++++++++ Libraries/x-saherelm.x-poi.extensions.lib.mq5 | 31 + Libraries/x-saherelm.x-poi.lib.mq5 | 188 + Libraries/x-saherelm.x-trade.lib.mq5 | 65 +- .../Classes/x-saherelm.xfima.parser.class.mq5 | 4 +- .../x-saherelm.xfima.signaller.class.mq5 | 1189 +++++-- .../x-saherelm.xfima.x-poi.detector.class.mq5 | 267 ++ 11 files changed, 5766 insertions(+), 261 deletions(-) create mode 100644 Documents/BKP/XFIMA Signals/Test.mq5 create mode 100644 Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy.mq5 diff --git a/Classes/x-saherelm.x-guard.class.mq5 b/Classes/x-saherelm.x-guard.class.mq5 index d3861233..ca2a63fd 100644 --- a/Classes/x-saherelm.x-guard.class.mq5 +++ b/Classes/x-saherelm.x-guard.class.mq5 @@ -1556,14 +1556,24 @@ class XCGuard : public XCBase // // Validate Action and Requirements ... has = - guard.sl > 0 && + guard.sl >= 0 && NotEmpty(guard.ticket) && + (guard.sl <= 0 + ? guard.force + : true) && guard.action == X_GUARD_ACTION_TRAIL_STOP; if (!has) { return; } + // + // Normalize SL ... + if (guard.sl < 0) + { + guard.sl = 0; + } + // // Retrieve Position ... XPosition position; @@ -1582,6 +1592,16 @@ class XCGuard : public XCBase // bool isLong = IsLong(position.type); + bool isGuardPassed = + guard.sl > 0 + ? (isLong + ? position.price > guard.sl && + (position.sl == 0 || + position.sl < guard.sl) + : position.price < guard.sl && + (position.sl == 0 || + position.sl > guard.sl)) + : (guard.sl == 0 && guard.force); // // Check Can Trail Stop or not ... @@ -1594,13 +1614,7 @@ class XCGuard : public XCBase position.profit > 0 && // // Validate SL based on Position Type ... - (isLong - ? position.price > guard.sl && - (position.sl == 0 || - position.sl < guard.sl) - : position.price < guard.sl && - (position.sl == 0 || - position.sl > guard.sl)); + isGuardPassed; if (!has) { // @@ -1668,14 +1682,24 @@ class XCGuard : public XCBase // // Validate Action and Requirements ... has = - guard.tp > 0 && + guard.tp >= 0 && NotEmpty(guard.ticket) && + (guard.tp <= 0 + ? guard.force + : true) && guard.action == X_GUARD_ACTION_TRAIL_TARGET; if (!has) { return; } + // + // Normalize ... + if (guard.tp < 0) + { + guard.tp = 0; + } + // // Retrieve Position ... XPosition position; @@ -1694,6 +1718,12 @@ class XCGuard : public XCBase // bool isLong = IsLong(position.type); + bool isGuardPassed = + guard.tp > 0 + ? (isLong + ? guard.tp > position.price + : guard.tp < position.price) + : (guard.tp == 0 && guard.force); // // Check Can Trail Stop or not ... @@ -1706,9 +1736,7 @@ class XCGuard : public XCBase guard.tp != position.tp && // // Validate TP based on Current Price ... - (isLong - ? guard.tp > position.price - : guard.tp < position.price); + isGuardPassed; if (!has) { // diff --git a/Classes/x-saherelm.x-market.pattern.class.mq5 b/Classes/x-saherelm.x-market.pattern.class.mq5 index 60ace05c..054d3cc0 100644 --- a/Classes/x-saherelm.x-market.pattern.class.mq5 +++ b/Classes/x-saherelm.x-market.pattern.class.mq5 @@ -4264,6 +4264,100 @@ class XCMarketPatternDetector : public XCBase return result; } + // + // Trigger Bar ... + bool IsTriggerBar( + XOHCL &bar, + ENUM_X_DIRECTION forDir, + ENUM_TIMEFRAMES forPeriod = PERIOD_M1 // + ) + { + // + // Trigger Bars Detected in Specified Perido ... + + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + IsXValid(forPeriod) && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Initialized Specified Bar in Specified Time Frame ... + XOHCL periodBar; + int index = GetBarIndex( + bar.symbol, + forPeriod, + TimeCurrent() // + ); + result = periodBar.Init(bar.symbol, forPeriod, index); + if (!result) + { + return result; + } + + // + // Detect Pattern ... + XPatternAnalysisConfig iConfig; + iConfig.Default(); + iConfig.CleanPatterns(); + iConfig.AddPattern(X_BAR_PATTERN_LOW); + iConfig.AddPattern(X_BAR_PATTERN_HIGH); + iConfig.AddPattern(X_BAR_PATTERN_PINNED); + iConfig.AddPattern(X_BAR_PATTERN_ENGULFED); + iConfig.AddPattern(X_BAR_PATTERN_SIGNALKEY); + + // + XPatternAnalysis periodBarAnalysis; + result = AnalyseBarPatterns(periodBar, periodBarAnalysis, iConfig); + + // + bool isBullish = + result && + IsXBullish(forDir) && + ( + // + periodBarAnalysis.HasPattern(X_BAR_PATTERN_PINNED, X_DIRECTION_BULLISH) || + periodBarAnalysis.HasPattern(X_BAR_PATTERN_ENGULFED, X_DIRECTION_BULLISH) || + periodBarAnalysis.HasPattern(X_BAR_PATTERN_SIGNALKEY, X_DIRECTION_BULLISH) + // + ); + + // + bool isBearish = + result && + IsXBearish(forDir) && + ( + // + periodBarAnalysis.HasPattern(X_BAR_PATTERN_PINNED, X_DIRECTION_BEARISH) || + periodBarAnalysis.HasPattern(X_BAR_PATTERN_ENGULFED, X_DIRECTION_BEARISH) || + periodBarAnalysis.HasPattern(X_BAR_PATTERN_SIGNALKEY, X_DIRECTION_BEARISH) + // + ); + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Cleanup ... + iConfig.Clean(); + periodBar.Clean(); + periodBarAnalysis.Clean(); + + // + return result; + } + // // Protected ... protected: diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index 3a57c251..5455bdfa 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -1557,7 +1557,61 @@ class XCPOIDrawer : public XCBase { // // Apply Style ... - object.Color(clr); + object.Color(clrTrend); + object.Width(config.trendWidth); + object.Style(config.trendStyle); + + // + // Save Object ... + drawnObjects.Add(object); + } + + // + ZeroMemory(object); + } + + void DrawTrendLine( + XTrend &trend, + XPOIDrawConfig &config, + color clr = CLR_NONE // + ) + { + // + // Validate ... + bool has = trend.IsValid(); + if (!has) + { + return; + } + + // + color trendColor = + (clr != CLR_NONE) + ? clr + : trend.IsBullish() + ? config.bullishColor + : trend.IsBearish() + ? config.bearishColor + : config.neuturalColor; + string name = trend.GetObjectID(); + + // + CChartObjectTrend *object; + has = DrawTrendLine( + trend.fromValue, + trend.fromTime, + trend.toValue, + trend.toTime, + object, + name, + config.trendRayRight, + config.trendRayLeft // + ); + if (has) + { + // + // Apply Style ... + object.Color(trendColor); object.Width(config.trendWidth); object.Style(config.trendStyle); @@ -2528,23 +2582,26 @@ class XCPOIDrawer : public XCBase /** * Draw a Collection of Pattern Analysis ... - * + * * @param analysises: XPatternAnalysis, collection reference to Data Source ... * @param config: XPatternAnalysisDrawConfig, reference to Specified Drawing Config ... */ void DrawPatternAnalysises( XPatternAnalysis &analysises[], XPatternAnalysisDrawConfig &config // - ) { + ) + { // bool has = HasChild(analysises); - if (!has) { + if (!has) + { return; } // int count = ArraySize(analysises); - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { DrawPatternAnalysis(analysises[i], config); } } diff --git a/Documents/BKP/XFIMA Signals/Test.mq5 b/Documents/BKP/XFIMA Signals/Test.mq5 new file mode 100644 index 00000000..e3433d9f --- /dev/null +++ b/Documents/BKP/XFIMA Signals/Test.mq5 @@ -0,0 +1,949 @@ + +/** + * Check Bar Has Signal Based on Strategy 4 ... + * + * @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 Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + bool validateByBarPatterns = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XPatternAnalysis pBarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + + // + bool isConsolidation = poiDetector.DetectXPVZone(zone, p2Bar.Index()); + + // + isBullish = + isConsolidation && + zone.IsBullish(); + + // + isBearish = + isConsolidation && + zone.IsBearish(); + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Force PBar Has Pattern ... + if (result && validateByBarPatterns) + { + // + // Analyse Bar Patterns ... + result = pBarPatterns.IsValid(); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + result && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + result && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + isBullish = + isBullish && + isPBarHasBullishPatterns && + !isPBarHasBearishPatterns; + + // + isBearish = + isBearish && + isPBarHasBearishPatterns && + !isPBarHasBullishPatterns; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + if (result) + { + // + poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + DebugBreak(); + + // + result = false; + isBullish = false; + isBearish = false; + } + + // // + // // Validate based on Bars Patterns ... + // bool validateByBarPatterns = true; + // if (validateByBarPatterns) + // { + // // + // // Reading pBar Patterns ... + // XPatternAnalysis pBarAnalysis; + // poiDetector.AnalyseBarPatterns( + // pBar, + // pBarAnalysis, + // structureConfig.barsAnalysisConfig // + // ); + + // // + // // Bullish ... + // bool isPBarHasBullishPatterns = + // (bar.close > pBar.low || + // bar.open > pBar.low) && + // ( + // // + // pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || + // pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || + // pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || + // pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || + // pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) + // // + // ); + + // // + // // Bearish ... + // bool isPBarHasBearishPatterns = + // (bar.close < pBar.high || + // bar.open < pBar.high) && + // ( + // // + // pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || + // pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || + // pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || + // pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || + // pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) + // // + // ); + + // // + // isBullish = + // isBullish && + // isPBarHasBullishPatterns && + // !isPBarHasBearishPatterns; + + // // + // isBearish = + // isBearish && + // isPBarHasBearishPatterns && + // !isPBarHasBullishPatterns; + + // // + // // Summarize Result ... + // result = isBullish || + // isBearish; + // } + + // // + // // Checking PullBack ... + // bool validateByPullback = false; + // if (validateByPullback) + // { + // // + // XBoxZone pullback; + // ENUM_X_DIRECTION pullbackDir; + // bool isPullBack = result && + // poiDetector.IsPullbackPattern( + // pBar, + // pullback, + // pullbackDir, + // 2, + // false // Force Break ... + // ); + // bool isPullbackBullish = isPullBack && + // IsXBullish(pullbackDir); + // bool isPullbackBearish = isPullBack && + // IsXBearish(pullbackDir); + + // // + // isBullish = + // isBullish && + // isPullbackBullish; + + // // + // isBearish = + // isBearish && + // isPullbackBearish; + + // // + // // Summarize Result ... + // result = isBullish || + // isBearish; + // } + + // + // Validate ... + result = isBullish || + isBearish; + + // + // Prepare Zone ... + if (result) + { + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + + // + return result; +} + +// // +// bool isConsolidation = poiDetector.DetectXPVZone(zone, p2Bar.Index()); + +// // +// isBullish = +// isConsolidation && +// zone.IsBullish(); + +// // +// isBearish = +// isConsolidation && +// zone.IsBearish(); + +// // +// // Summarize Result ... +// result = isBullish || isBearish; + +// // +// // Force PBar Has Pattern ... +// if (result && validateByBarPatterns) +// { +// // +// // Analyse Bar Patterns ... +// result = pBarPatterns.IsValid(); + +// // +// // Bullish ... +// bool isPBarHasBullishPatterns = +// result && +// ( +// // +// pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || +// pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || +// pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || +// pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || +// pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) +// // +// ); + +// // +// // Bearish ... +// bool isPBarHasBearishPatterns = +// result && +// ( +// // +// pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || +// pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || +// pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || +// pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || +// pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) +// // +// ); + +// // +// isBullish = +// isBullish && +// isPBarHasBullishPatterns && +// !isPBarHasBearishPatterns; + +// // +// isBearish = +// isBearish && +// isPBarHasBearishPatterns && +// !isPBarHasBullishPatterns; + +// // +// // Summarize Result ... +// result = isBullish || isBearish; + +// // +// // Reset Flags ... +// if (!result) +// { +// // +// isBullish = false; +// isBearish = false; +// } +// } + +// // +// if (result) +// { +// // +// poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); +// poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); +// DebugBreak(); + +// // +// result = false; +// isBullish = false; +// isBearish = false; +// } + +// // +// // Validate based on Bars Patterns ... +// bool validateByBarPatterns = true; +// if (validateByBarPatterns) +// { +// // +// // Reading pBar Patterns ... +// XPatternAnalysis pBarAnalysis; +// poiDetector.AnalyseBarPatterns( +// pBar, +// pBarAnalysis, +// structureConfig.barsAnalysisConfig // +// ); + +// // +// // Bullish ... +// bool isPBarHasBullishPatterns = +// (bar.close > pBar.low || +// bar.open > pBar.low) && +// ( +// // +// pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || +// pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || +// pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || +// pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || +// pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) +// // +// ); + +// // +// // Bearish ... +// bool isPBarHasBearishPatterns = +// (bar.close < pBar.high || +// bar.open < pBar.high) && +// ( +// // +// pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || +// pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || +// pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || +// pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || +// pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) +// // +// ); + +// // +// isBullish = +// isBullish && +// isPBarHasBullishPatterns && +// !isPBarHasBearishPatterns; + +// // +// isBearish = +// isBearish && +// isPBarHasBearishPatterns && +// !isPBarHasBullishPatterns; + +// // +// // Summarize Result ... +// result = isBullish || +// isBearish; +// } + +// // +// // Checking PullBack ... +// bool validateByPullback = false; +// if (validateByPullback) +// { +// // +// XBoxZone pullback; +// ENUM_X_DIRECTION pullbackDir; +// bool isPullBack = result && +// poiDetector.IsPullbackPattern( +// pBar, +// pullback, +// pullbackDir, +// 2, +// false // Force Break ... +// ); +// bool isPullbackBullish = isPullBack && +// IsXBullish(pullbackDir); +// bool isPullbackBearish = isPullBack && +// IsXBearish(pullbackDir); + +// // +// isBullish = +// isBullish && +// isPullbackBullish; + +// // +// isBearish = +// isBearish && +// isPullbackBearish; + +// // +// // Summarize Result ... +// result = isBullish || +// isBearish; +// } + +/** + * Check Bar Has Signal Based on Strategy 4 ... + * + * @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 Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + bool validateByBarPatterns = false; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XPatternAnalysis pBarPatterns; + XPatternAnalysis p2BarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + poiDetector.AnalyseBarPatterns( + p2Bar, + p2BarPatterns, + patternConfig // + ); + + // + bool hasSupport = p2BarPatterns.IsValid() && + p2BarPatterns.IsSupport(); + bool hasResistance = p2BarPatterns.IsValid() && + p2BarPatterns.IsResistance(); + + // + isBullish = + hasSupport && + p2BarPatterns.Count(X_DIRECTION_BULLISH) >= 4; + + // + isBearish = + hasResistance && + p2BarPatterns.Count(X_DIRECTION_BEARISH) >= 4; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Extract Affected Zone ... + if (result) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone tmpZone; + + // + if (hasSupport) + { + // + hasSupport = p2BarPatterns.GetSupport(tmpBar, tmpPivot, tmpZone); + isBullish = + isBullish && + hasSupport && + (IsActed(pBar, tmpZone) || + IsTested(pBar, tmpZone)); + } + + // + if (hasResistance) + { + // + hasResistance = p2BarPatterns.GetResistance(tmpBar, tmpPivot, tmpZone); + isBearish = + isBearish && + hasResistance && + (IsActed(pBar, tmpZone) || + IsTested(pBar, tmpZone)); + } + + // + // Cleanup ... + tmpBar.Clean(); + tmpZone.Clean(); + tmpPivot.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate based on Bars Patterns ... + if (result && validateByBarPatterns) + { + // + // Bullish... + bool isPBarHasBullishPatterns = + pBarPatterns.IsValid() && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + pBarPatterns.IsValid() && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + isBullish = + isBullish && + isPBarHasBullishPatterns && + !isPBarHasBearishPatterns; + + // + isBearish = + isBearish && + isPBarHasBearishPatterns && + !isPBarHasBullishPatterns; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + if (result) + { + // + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + poiDrawer.DrawPatternAnalysis(p2BarPatterns, structureDrawConfig.barAnalysisDrawConfig); + DebugBreak(); + + // + result = false; + isBullish = false; + isBearish = false; + } + + // // + // bool isConsolidation = poiDetector.DetectXPVZone(zone, p2Bar.Index()); + + // // + // isBullish = + // isConsolidation && + // zone.IsBullish(); + + // // + // isBearish = + // isConsolidation && + // zone.IsBearish(); + + // // + // // Summarize Result ... + // result = isBullish || isBearish; + + // // + // // Force PBar Has Pattern ... + // if (result && validateByBarPatterns) + // { + // // + // // Analyse Bar Patterns ... + // result = pBarPatterns.IsValid(); + + // // + // // Bullish ... + // bool isPBarHasBullishPatterns = + // result && + // ( + // // + // pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + // pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + // pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + // pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + // pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // // + // ); + + // // + // // Bearish ... + // bool isPBarHasBearishPatterns = + // result && + // ( + // // + // pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + // pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + // pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + // pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + // pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // // + // ); + + // // + // isBullish = + // isBullish && + // isPBarHasBullishPatterns && + // !isPBarHasBearishPatterns; + + // // + // isBearish = + // isBearish && + // isPBarHasBearishPatterns && + // !isPBarHasBullishPatterns; + + // // + // // Summarize Result ... + // result = isBullish || isBearish; + + // // + // // Reset Flags ... + // if (!result) + // { + // // + // isBullish = false; + // isBearish = false; + // } + // } + + // // + // if (result) + // { + // // + // poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + // poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + // DebugBreak(); + + // // + // result = false; + // isBullish = false; + // isBearish = false; + // } + + // // + // // Checking PullBack ... + // bool validateByPullback = false; + // if (validateByPullback) + // { + // // + // XBoxZone pullback; + // ENUM_X_DIRECTION pullbackDir; + // bool isPullBack = result && + // poiDetector.IsPullbackPattern( + // pBar, + // pullback, + // pullbackDir, + // 2, + // false // Force Break ... + // ); + // bool isPullbackBullish = isPullBack && + // IsXBullish(pullbackDir); + // bool isPullbackBearish = isPullBack && + // IsXBearish(pullbackDir); + + // // + // isBullish = + // isBullish && + // isPullbackBullish; + + // // + // isBearish = + // isBearish && + // isPullbackBearish; + + // // + // // Summarize Result ... + // result = isBullish || + // isBearish; + // } + + // + // Validate ... + result = isBullish || + isBearish; + + // + // Prepare Zone ... + if (result) + { + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + patternConfig.Clean(); + p2BarPatterns.Clean(); + + // + return result; +} + +bool validateByPVChange = false; +bool validateByPVInside = false; + +// +// Validate By PV Inside ... +if (result && validateByPVInside) +{ + // + double pVale = fimaHelper.GetVale(pBar.Index()); + double pPeak = fimaHelper.GetPeak(pBar.Index()); + + // + bool isValePassed = pVale <= support.upper && + pVale >= support.upper && + fimaParser.IsValeSame(pBar.Index()); + + // + bool isPeakPassed = pPeak <= resistance.upper && + pPeak >= resistance.upper && + fimaParser.IsPeakSame(pBar.Index()); + + // + isBullish = + isBullish && + isValePassed; + + // + isBearish = + isBearish && + isPeakPassed; + + // + // Summarize Result ... + result = isBullish || isBearish; +} + +// +// Validate by PV Change ... +if (result && validateByPVChange) +{ + // + // bullish => p3, p2 vale under last ... + // bearish => p3, p2 peak over last ... + + // + bool isValePassed = + fimaParser.IsValeUnderLast(p2Bar.Index()) || + fimaParser.IsValeUnderLast(p3Bar.Index()); + + // + bool isPeakPassed = + fimaParser.IsPeakOverLast(p2Bar.Index()) || + fimaParser.IsPeakOverLast(p3Bar.Index()); + + // + isBullish = + isBullish && + isValePassed; + + // + isBearish = + isBearish && + isPeakPassed; + + // + // Summarize Result ... + result = isBullish || isBearish; +} diff --git a/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy.mq5 b/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy.mq5 new file mode 100644 index 00000000..749cb7ee --- /dev/null +++ b/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy.mq5 @@ -0,0 +1,3121 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMASignaller ... +// Description: XFIMA Signaller Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XFIMA Signaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.parser.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" + +// +// Implementation ... + +// +// Base XFIMA base Signaller ... +class XCXFIMABaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + CArrayObj drawnObjects; // Drawing Objects Holder ... + XFIMAInputs fimaInputs; // XFIMA Inputs ... + XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... + XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... + XCXFIMAHelperParser *fimaParser; // XFIMA Helper Parser ... + XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... + XFIMAMarketStructureConfig structureConfig; // XFIMA Market Structure Detector Config ... + XFIMAMarketStructureDrawerConfig structureDrawConfig; // XFIMA Market Structure Draw Config ... + + // + // Constructor ... + XCXFIMABaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCBaseSignaller(_name, + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Instantiating XFIMA Indicator Helper Class ... + if (_fimaInputs.IsValid()) + { + // + fimaHelper = new XCXFIMAHelper(); + bool isInited = fimaHelper.Init( + _symbol, + _period, + _fimaInputs // + ); + if (isInited) + { + fimaInputs = _fimaInputs; + } + else + { + // + delete fimaHelper; + ZeroMemory(fimaHelper); + } + } + + // + // Instantiate XFIMA Helper Parser ... + fimaParser = new XCXFIMAHelperParser(fimaHelper); + + // + poiDrawer = new XCXFIMAPOIDrawer(); + poiDetector = new XCXFIMAPOIDetector(fimaHelper, fimaParser); + + // + // Configure ... + structureConfig.Default(); + structureDrawConfig.Default(); + } + + // + // Deconstructor ... + ~XCXFIMABaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + fimaInputs.Clean(); + + // + delete fimaHelper; + ZeroMemory(fimaHelper); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + + // + structureConfig.Clean(); + structureDrawConfig.Clean(); + } + + // + // Virtuals ... + + /** + * Before Destroy ... + */ + void virtual BeforeDestroy() + { + } + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + // + bool result = false; + + // + // Validate Fima Helper Requirements ... + result = fimaInputs.IsValid() && + fimaHelper != NULL && + poiDetector != NULL; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + // + // Protected ... + protected: + // + + // + // Protected Actions ... + + // + // Private ... + private: + // +}; + +// +// XFIMA Strategy 2 Signaller Class ... +class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCXFIMAStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA1", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Configure ... + drawLeg = true; + drawZones = true; + drawSupport = true; + drawOrderFlow = true; + drawResistance = true; + + // + structureConfig.Default(); + structureDrawConfig.Default(); + } + + // + // Deconstructor ... + ~XCXFIMAStrategy1Signaller() + { + // + Destroy(); + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + XOHCL iBar; + XBoxZone iZone; + XSignal iSignal; + bool has = false; + XTarget iTargets[]; + bool isBullish = false; + bool isBearish = false; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = iBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + return; + } + + // + // Manage ... + Manage(iBar); + + // + // Strategy X ... + has = HasSignal( + iBar, + iZone, + iTargets, + iDir // + ); + + // + // Handle Resting Signals ... + has = HasDirection(iDir) && + iZone.IsValid(); + + // + // Prepare Signal ... + if (has) + { + // + isBullish = IsXBullish(iDir); + isBearish = IsXBearish(iDir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, iDir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Signal ... + has = PrepareSignal( + iSignal, + iDir, + iTargets, + 0, // Use Default R2R ... + sl, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + } + + // + // Notify On Signal Event ... + if (has) + { + NotifySignalEventListeners(iSignal); + } + + // + // Cleanup ... + iBar.Clean(); + iZone.Clean(); + iSignal.Clean(); + XClean(iTargets); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard, reference collection to holds result ... + * @param positions: XPosition, reference collection to provides positions ... + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + XClean(guards); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Requirements ... + XGuard iGuard; + bool has = false; + int samePeaks = 0; + int sameVales = 0; + double iValue = 0; + double points10 = 0; + double points50 = 0; + double points100 = 0; + int samePVValidation = 5; + bool isPeakOverLast = false; + bool isValeUnderLast = false; + + // + for (int i = 0; i < positionsCount; i++) + { + // + points10 = 10 * positions[i].GetPointsValue(); + points50 = 50 * positions[i].GetPointsValue(); + points100 = 100 * positions[i].GetPointsValue(); + + // + // Near to TP Guard ... + has = positions[i].profit > 0; + if (has) + { + // + // Has Same Peaks or Vales ... + samePeaks = fimaParser.CountSamePeaks(barIndex); + sameVales = fimaParser.CountSameVales(barIndex); + isPeakOverLast = (fimaParser.IsPeakOverLast(barIndex) || + fimaParser.IsPeakOverLast(barIndex + 1)); + isValeUnderLast = (fimaParser.IsValeUnderLast(barIndex) || + fimaParser.IsValeUnderLast(barIndex + 1)); + has = (positions[i].IsBullish() + ? ( + isPeakOverLast && + sameVales >= samePVValidation && + fimaHelper.GetVale(barIndex) > positions[i].sl) + : positions[i].IsBearish() + ? ( + isValeUnderLast && + samePeaks >= samePVValidation && + fimaHelper.GetPeak(barIndex) < positions[i].sl) + : false); + if (has) + { + // + iGuard.Clean(); + iGuard.time = TimeCurrent(); + iGuard.symbol = positions[i].symbol; + iGuard.period = positions[i].period; + iGuard.ticket = positions[i].ticket; + iGuard.provider = positions[i].provider; + iGuard.sl = positions[i].IsBullish() + ? fimaHelper.GetVale(barIndex) - points10 + : fimaHelper.GetPeak(barIndex) + points10; + iGuard.action = X_GUARD_ACTION_TRAIL_STOP; + + // + has = iGuard.IsValid(); + if (has) + { + AddRef(iGuard, guards); + + // + // Remove TP if in Profit SL ... + iValue = (positions[i].IsBullish() ? positions[i].entry + points10 : positions[i].entry - points10); + has = + (positions[i].IsBullish() && HasResistance()) + ? (iGuard.sl >= iValue && + positions[i].tp < resistance.lower) + : (positions[i].IsBearish() && HasSupport()) + ? (iGuard.sl <= iValue && + positions[i].tp > support.upper) + : false; + if (has) + { + // + iGuard.Clean(); + iGuard.force = false; + iGuard.tp = positions[i].IsBullish() + ? resistance.lower + : support.upper; + iGuard.time = TimeCurrent(); + iGuard.symbol = positions[i].symbol; + iGuard.period = positions[i].period; + iGuard.ticket = positions[i].ticket; + iGuard.provider = positions[i].provider; + iGuard.action = X_GUARD_ACTION_TRAIL_TARGET; + + // + has = iGuard.IsValid(); + if (has) + { + AddRef(iGuard, guards); + } + } + } + } + } + } + + // + result = ArraySize(guards); + + // + // Cleanup ... + iGuard.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + void Manage(XOHCL &bar) + { + // + bool has = bar.IsValid(); + if (!has) + { + return; + } + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + has = bar.GetPreviousBar(pBar); + has = has && + pBar.GetPreviousBar(p2Bar); + has = has && + p2Bar.GetPreviousBar(p3Bar); + if (!has) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + } + + // + ManageLeg(bar); + ManageZones(p2Bar); + ManageOrderFlow(p3Bar); + + // + // Cleanup ... + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + } + + // + // Private ... + private: + // + // Props ... + + // + // Leg ... + + XLeg leg; // Exists Leg ... + bool drawLeg; // Draw Leg ... + + // + bool HasLeg() + { + return leg.IsValid(); + } + + // + bool ValidateLeg(XOHCL &bar) + { + // + bool result = false; + + // + result = HasLeg() && + bar.IsValid(); + if (!result) + { + return result; + } + + // + result = + leg.IsBullish() + ? bar.low > leg.lower + : leg.IsBearish() + ? bar.high < leg.upper + : false; + + // + return result; + } + + // + void DrawLeg() + { + // + if (!drawLeg) + { + return; + } + + // + if (!HasLeg()) + { + return; + } + + // + // Update to Times ... + leg.UpdateTimes(); + + // + // Draw Leg Box ... + XBoxZone legZone; + leg.ToBox(legZone); + if (legZone.IsValid()) + { + // + legZone.to = TimeCurrent(); + poiDrawer.DrawZone(legZone, structureDrawConfig.drawConfig); + } + + // + // Draw Legs Other Stufs ... + return; + + // + // FVGs ... + poiDrawer.DrawZones(leg.bullishFVGs, structureDrawConfig.drawConfig); + poiDrawer.DrawZones(leg.bearishFVGs, structureDrawConfig.drawConfig); + + // + // Support and Resistances ... + poiDrawer.DrawZones(leg.supports, structureDrawConfig.drawConfig); + poiDrawer.DrawZones(leg.resistances, structureDrawConfig.drawConfig); + + // + // Patterns ... + poiDrawer.DrawPatternAnalysises(leg.patterns, structureDrawConfig.barAnalysisDrawConfig); + } + + // + void ManageLeg(XOHCL &bar) + { + // + // Validate Exists ... + if (HasLeg()) + { + // + if (!ValidateLeg(bar)) + { + // + // Invalidate XLeg ... + leg.Clean(); + } + } + + // + // Detect New ... + if (!HasLeg()) + { + poiDetector.IsLegPattern(bar, leg); + } + + // + // Update Exists ... + if (HasLeg()) + { + // + // Update to Times ... + leg.UpdateTimes(); + + // + DrawLeg(); + } + } + + // + // Order Flow ... + + // + bool drawOrderFlow; + XBoxZone orderFlow[]; + ENUM_X_DIRECTION orderFlowDir; + + // + bool HasOrderFlow() + { + // + return HasChild(orderFlow) && + HasDirection(orderFlowDir); + } + + // + bool HasBullishOrderFlow() + { + return HasOrderFlow() && + IsXBullish(orderFlowDir); + } + + // + bool HasBearishOrderFlow() + { + return HasOrderFlow() && + IsXBearish(orderFlowDir); + } + + // + bool GetOrderFlowBoundary( + double &upper, + double &lower // + ) + { + // + bool result = false; + + // + // Prepare ... + upper = EMPTY_VALUE; + lower = EMPTY_VALUE; + + // + // Validate ... + result = HasOrderFlow(); + if (!result) + { + return result; + } + + // + int idx = -1; + + // + // Upper ... + idx = GetHighest(orderFlow); + if (IsValidIndex(idx)) + { + upper = orderFlow[idx].upper; + } + + // + // Lower ... + idx = GetLowest(orderFlow); + if (IsValidIndex(idx)) + { + lower = orderFlow[idx].lower; + } + + // + result = NotEmptyZero(upper) && + NotEmptyZero(lower) && + upper > lower; + + // + // Cleanup ... + if (!result) + { + // + upper = EMPTY_VALUE; + lower = EMPTY_VALUE; + } + + // + return result; + } + + // + bool ValidateOrderFlow(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasOrderFlow(); + if (!result) + { + return result; + } + + // + double upper = EMPTY_VALUE; + double lower = EMPTY_VALUE; + result = GetOrderFlowBoundary(upper, lower); + result = result && + HasBullishOrderFlow() + ? bar.low > lower + : bar.high < upper; + + // + return result; + } + + // + void DrawOrderFlow() + { + // + if (!drawOrderFlow || !HasOrderFlow()) + { + return; + } + + // + poiDrawer.DrawZones(orderFlow, structureDrawConfig.drawConfig); + } + + // + void ManageOrderFlow(XOHCL &bar) + { + // + // Validate Exists ... + if (HasOrderFlow()) + { + // + if (!ValidateOrderFlow(bar)) + { + // + // Invalidate OrderFlow ... + XClean(orderFlow); + orderFlowDir = X_DIRECTION_NONE; + } + } + + // + // Detect New ... + if (!HasOrderFlow()) + { + // + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + // patternConfig.Default(); + // patternConfig.supportAndResistanceLoopbackLength = 21; + // patternConfig.supportAndResistanceValidationLength = 7; + + // + poiDetector.HasOrderFlow( + bar, + orderFlowDir, + orderFlow, + structureConfig.orderFlowValidation, + structureConfig.orderFlowUseOB, + structureConfig.orderFlowUseFVG, + structureConfig.orderFlowUseSupportAndResistance, + patternConfig.supportAndResistanceLoopbackLength, + patternConfig.supportAndResistanceValidationLength, + structureConfig.loopback // + ); + } + + // + // Update Exists ... + if (HasOrderFlow()) + { + // + // Update to Times ... + UpdateToTime(orderFlow, TimeCurrent()); + + // + DrawOrderFlow(); + } + } + + // + // Zone ... + + // + XBoxZone support; + XBoxZone resistance; + bool drawZones; + bool drawSupport; + bool drawResistance; + + // + bool HasZones() + { + return HasSupport() || + HasResistance(); + } + + // + bool HasSupport() + { + return support.IsValid(); + } + + // + bool HasResistance() + { + return resistance.IsValid(); + } + + // + bool ValidateZones(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasZones(); + if (!result) + { + return result; + } + + // + // Support ... + bool hasSupport = HasSupport(); + if (hasSupport) + { + // + result = bar.close > support.lower && + !IsBreaked(support, X_PRICE_CLOSE); + if (!result) + { + // + support.breakAt = bar.time; + support.Clean(); + } + } + + // + // Resistance ... + bool hasResistance = HasResistance(); + if (hasResistance) + { + // + result = bar.close < resistance.upper && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!result) + { + // + resistance.breakAt = bar.time; + resistance.Clean(); + } + } + + // + result = + (hasSupport && !HasSupport()) || + (hasResistance && !HasResistance()); + + // + return result; + } + + // + void DrawZones() + { + // + if (!drawZones || !HasZones()) + { + return; + } + + // + if (drawSupport && HasSupport()) + { + poiDrawer.DrawZone(support, structureDrawConfig.drawConfig); + } + + // + if (drawResistance && HasResistance()) + { + poiDrawer.DrawZone(resistance, structureDrawConfig.drawConfig); + } + } + + // + void ManageZones(XOHCL &bar) + { + // + // Validate Exists ... + if (HasZones()) + { + // + if (!ValidateZones(bar)) + { + // + // Invalidate Zones ... + + // + // Support ... + if (IsXValid(support.breakAt)) + { + support.Clean(); + } + + // + // Resistance ... + if (IsXValid(resistance.breakAt)) + { + resistance.Clean(); + } + } + } + + // + // Detect New ... + XOHCL tmpBar; + bool has = false; + + // + // Detect Support ... + if (!HasSupport()) + { + // + has = poiDetector.HasSupport( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToSupportBox(tmpBar, support, bar.time); + has = + has && + !IsBreaked(support, X_PRICE_CLOSE); + if (!has) + { + support.Clean(); + } + } + } + + // + // Detect Resistance ... + if (!HasResistance()) + { + // + has = poiDetector.HasResistance( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToResistanceBox(tmpBar, resistance, bar.time); + has = + has && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!has) + { + resistance.Clean(); + } + } + } + + // + // Update Exists ... + if (HasZones()) + { + // + if (HasSupport()) + { + // + support.to = bar.time; + support.type = "XFIMASUP"; + } + + // + if (HasResistance()) + { + // + resistance.to = bar.time; + resistance.type = "XFIMARes"; + } + + // + DrawZones(); + } + + // + // Cleanup ... + tmpBar.Clean(); + } + + // + // Implementing Strategies ... + + /** + * Check Bar Has Signal Based on Strategy X ... + * + * @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 HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Configuration Flags ... + + // + // Signaller Flags ... + bool useSignaller1 = false; + bool useSignaller2 = false; + bool useSignaller3 = false; + bool useSignaller4 = true; + + // + // Validator Flags ... + string provider = NULL; + bool validateByOrderFlow = false; + + // + // Target Flags ... + bool hasPartialCloseOnTp1 = false; + + // + bool doRFOnEntryOnTP1 = false; + + // + // Draw Flags ... + bool draw = true; + bool drawZone = true; + bool drawMarketStructurePivots = true; + bool drawMarketStructureAnalysis = true; + bool drawMarketStructureOrderFlow = true; + XPOIDrawConfig iDrawConfig; + + // + drawLeg = false; + drawZones = true; + drawSupport = true; + drawOrderFlow = false; + drawResistance = true; + + // + // Signal Checking ... + + // + // Analyse Market Strucutre ... + XFIMAMarketStructure marketStructure; + + // + // Check Market ... + // result = HasLeg() && + // HasOrderFlow() && + // orderFlowDir == leg.dir; + // result = HasBearishOrderFlow(); + // if (result) + // { + // // + // result = false; + // DebugBreak(); + // } + + // + // Signaller 1 ... + if (!result && useSignaller1) + { + // + result = Strategy1HasSignal( + bar, + zone, + targets, + dir // + ); + + // + if (result) + { + provider = "1"; + } + } + + // + // Signaller 2 ... + if (!result && useSignaller2) + { + // + result = Strategy2HasSignal( + bar, + zone, + targets, + dir // + ); + + // + if (result) + { + provider = "2"; + } + } + + // + // Signaller 3 ... + if (!result && useSignaller3) + { + // + result = Strategy3HasSignal( + bar, + zone, + targets, + dir // + ); + + // + if (result) + { + provider = "3"; + } + } + + // + // Signaller 4 ... + if (!result && useSignaller4) + { + // + result = Strategy4HasSignal( + bar, + zone, + targets, + dir // + ); + + // + if (result) + { + provider = "4"; + } + } + + // + // Signal Validating ... + + // + // Validate Signals by Order Flow ... + if (result && validateByOrderFlow) + { + // + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) + { + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } + + // + bool isBullish = IsXBullish(dir) && + marketStructure.HasBullishOrderFlow(); + + // + bool isBearish = IsXBearish(dir) && + marketStructure.HasBearishOrderFlow(); + + // + // Summarizing result ... + result = isBullish || + isBearish; + } + + // + // Targets, Restrictions and Risk Management ... + if (result) + { + // + // Requirements ... + XTarget iTarget; + + // + // Checking Direction of Signal ... + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + // Provided SL ... + double points = GetPoints(symbol); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, dir); + + // + // Calculate SL Addition ... + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * points; + + // + // Calculate SL Price ... + double sl = + isBullish + ? zone.lower - slAddition + : zone.upper + slAddition; + + // + // Calculate Risk ... + double risk = MathAbs(entry - sl); + + // + // Calculate Reward ... + double reward = defaultSignalR2R * risk; + + // + // Calculate TP1 ... + double tp1 = isBullish + ? entry + risk + : entry - risk; + double tp2 = isBullish + ? entry + (2 * risk) + : entry - (2 * risk); + + // + // Calculate TP ... + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Check Max Allowed Risk ... + bool hasTooMuchRisk = maxAllowedRiskDistance <= 0 + ? false + : risk >= (maxAllowedRiskDistance * points); + if (hasTooMuchRisk) + { + // + // Clean Signal if Too much Risk ... + zone.Clean(); + dir = X_DIRECTION_NONE; + } + + // + // Common Targets ... + + // + // Partial Close on TP 1 ... + if (hasPartialCloseOnTp1) + { + // + iTarget.Clean(); + iTarget.target = tp1; + iTarget.actingDistance = 5; + iTarget.volumeMultiplier = 0.8; + iTarget.doRFOnEntry = doRFOnEntryOnTP1; + + // + AddRef(iTarget, targets); + } + + // + // Custom Signaller Targets ... + + // + // Restrictions Handling ... + if (risk > 0 && HasRestrictions()) + { + // + // Reset Restricitons if necessary ... + ResetRestrictions(); + + // + // Handle Custom Restrictions Senario ... + } + + // + // Ignore Targets ... + if (ignoreTargets) + { + XClean(targets); + } + + // + // Summarize Result ... + result = zone.IsValid() && + HasDirection(dir); + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Draws ... + if (result && draw) + { + // + // Prepare Draw Config ... + iDrawConfig = structureDrawConfig.drawConfig; + iDrawConfig.zonesWidth = 3; + iDrawConfig.zonesStyle = STYLE_DASH; + iDrawConfig.bullishColor = clrYellow; + iDrawConfig.bearishColor = clrDarkOrange; + + // + // Draw Zone ... + if (drawZone) + { + poiDrawer.DrawZone(zone, iDrawConfig); + } + + // + // Draw Market Structure ... + // + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) + { + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } + if (marketStructure.IsValid()) + { + // + // Order Flow ... + if (drawMarketStructureOrderFlow && marketStructure.HasOrderFlow()) + { + poiDrawer.DrawZones(marketStructure.orderFlow, iDrawConfig); + } + + // + // Pivots ... + if (drawMarketStructurePivots) + { + // + XPivot pivots[]; + int pivotsCount = marketStructure.CollectPivots( + pivots, + true // Contains Patterns ... + ); + if (IsValidSize(pivotsCount)) + { + poiDrawer.DrawPivots(pivots, iDrawConfig); + } + + // + XClean(pivots); + } + + // + // Analysis ... + if (drawMarketStructureAnalysis) + { + // + } + } + + // + // Other Drawing Materials ... + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + + // + // Debug Breake ... + if (result) + { + DebugBreak(); + } + + // + // Cleanup ... + iDrawConfig.Clean(); + marketStructure.Clean(); + + // + return result; + } + + // + // Custom Signal Strategies ... + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @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; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Reading Conditions ... + int pullBackStartBar = -1; + bool isPullBack = result && + poiDetector.IsPullbackPattern( + pBar, + zone, + dir, + 2, + false // Force Break ... + ); + bool isPullbackBullish = isPullBack && + IsXBullish(dir); + bool isPullbackBearish = isPullBack && + IsXBearish(dir); + if (isPullBack) + { + pullBackStartBar = zone.FromIndex(); + } + + // + // Reading HK Band ... + + // + double pHKBandUpper = fimaHelper.GetHKBandUpper(pBar.Index()); + double pHKBandLower = fimaHelper.GetHKBandLower(pBar.Index()); + int overHKBandUpperCount = fimaParser.CountOverHKBandUpper(pullBackStartBar, X_PRICE_LOW); + int underHKBandLowerCount = fimaParser.CountUnderHKBandLower(pullBackStartBar, X_PRICE_HIGH); + + // + // Reading PV Requirements ... + + // + int lastPeakOverLastIDX = -1; + int lastValeUnderLastIDX = -1; + double pPeak = fimaHelper.GetPeak(pBar.Index()); + double pVale = fimaHelper.GetVale(pBar.Index()); + int samePeaks = fimaParser.CountSamePeaks(pBar.Index()); + int sameVales = fimaParser.CountSameVales(pBar.Index()); + fimaParser.FindLastPeakOverLast(lastPeakOverLastIDX, pBar.Index()); + fimaParser.FindLastValeUnderLast(lastValeUnderLastIDX, pBar.Index()); + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // + ); + + // + // Check Bar Patterns ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + // Check PBar Close Over Under Fast Ma ... + bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); + bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); + + // + // Try To Find Affected Zone ... + + // + // Collecting Zones ... + XBoxZone zones[]; + XBoxZone affectedZones[]; + XBoxZone affectedZonesBullish[]; + XBoxZone affectedZonesBearish[]; + int zonesCount = poiDetector.CollectZones( + pBar, + zones, // + 5, // Zones Loopback ... + 3 // Zones Validation Length ... + // Required Zones ... + // Loopback ... + ); + int affectedZonesCount = ExtractAffectedZones( + pBar, + zones, + affectedZones // + ); + int affectedZonesBullishCount = ExtractByDirection( + affectedZonesBullish, + affectedZones, + X_DIRECTION_BULLISH // + ); + int affectedZonesBearishCount = ExtractByDirection( + affectedZonesBearish, + affectedZones, + X_DIRECTION_BEARISH // + ); + + // + int insideBullishIDX = -1; + int insideBearishIDX = -1; + bool hasBullishInside = + pBar.IsBullish() && + HasInside( + insideBullishIDX, + pBar, + affectedZonesBullish // + ); + bool hasBearishInside = + pBar.IsBearish() && + HasInside( + insideBearishIDX, + pBar, + affectedZonesBearish // + ); + + // + // Do ... + + // + isBullish = + // + hasBullishInside && + isPullbackBullish && + isPBarHasBullishPatterns && + fimaParser.IsSARBullish(pBar.Index()) && + (pVale >= affectedZonesBullish[insideBullishIDX].lower && + pVale <= affectedZonesBullish[insideBullishIDX].upper) + // + ; + + // + isBearish = + // + hasBearishInside && + isPullbackBearish && + isPBarHasBearishPatterns && + fimaParser.IsSARBearish(pBar.Index()) && + (pPeak >= affectedZonesBearish[insideBearishIDX].lower && + pPeak <= affectedZonesBearish[insideBearishIDX].upper) + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + if (isBullish) + { + zone = affectedZonesBullish[insideBullishIDX]; + } + else + { + zone = affectedZonesBearish[insideBearishIDX]; + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + XClean(zones); + pBarAnalysis.Clean(); + XClean(affectedZones); + XClean(affectedZonesBullish); + XClean(affectedZonesBearish); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * @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 Strategy2HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // + ); + + // + // Check Bar Patterns ... + bool isPBarHasBullishPatterns = + (bar.close > pBar.low || + bar.open > pBar.low) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + bool isPBarHasBearishPatterns = + (bar.close < pBar.high || + bar.open < pBar.high) && + ( + // + pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || + pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || + pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || + pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || + pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + double peak = fimaHelper.GetPeak(bar.Index()); + double vale = fimaHelper.GetVale(bar.Index()); + double pPeak = fimaHelper.GetPeak(pBar.Index()); + double pVale = fimaHelper.GetVale(pBar.Index()); + double p2Peak = fimaHelper.GetPeak(p2Bar.Index()); + double p2Vale = fimaHelper.GetVale(p2Bar.Index()); + bool isPPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index()); + bool isPValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index()); + bool isP2PeakOverLast = fimaParser.IsPeakOverLast(p2Bar.Index()); + bool isP2ValeUnderLast = fimaParser.IsValeUnderLast(p2Bar.Index()); + bool isPeakOverLast = isPPeakOverLast || + isP2PeakOverLast; + bool isValeUnderLast = isPValeUnderLast || + isP2ValeUnderLast; + bool isP2ValeOverLast = pVale > p2Vale; + bool isP2PeakUnderLast = pPeak < p2Peak; + + // + // Check PBar Close Over Under Fast Ma ... + bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); + bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); + bool isFastOverLast = fimaHelper.GetMAFast(pBar.Index()) > fimaHelper.GetMAFast(p2Bar.Index()); + bool isFastUnderLast = fimaHelper.GetMAFast(pBar.Index()) < fimaHelper.GetMAFast(p2Bar.Index()); + + // + // Force P2Bar is Pin Bar ... + ENUM_X_DIRECTION p2Dir; + bool isP2BarPinned = poiDetector.IsPinnedBar( + p2Bar, + p2Dir // + ); + bool isP2BarBullishPinned = + isP2BarPinned && + IsXBullish(p2Dir); + bool isP2BarBearishPinned = + isP2BarPinned && + IsXBearish(p2Dir); + + // + // Do ... + + // + isBullish = + // + isFastOverLast && + isValeUnderLast && + !isP2PeakUnderLast && + isPBarCloseOverFast && + isP2BarBullishPinned && + isPBarHasBullishPatterns + // + ; + + // + isBearish = + // + isPeakOverLast && + isFastUnderLast && + !isP2ValeOverLast && + isPBarCloseUnderFast && + isP2BarBearishPinned && + isPBarHasBearishPatterns + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Manage Stops ... + if (result) + { + // + double entry = GetEntry(zone.symbol, zone.dir); + double riskSide = zone.IsBullish() ? zone.lower : zone.upper; + double risk = MathAbs(entry - riskSide); + + // + // Collecting Affected Zones ... + XBoxZone tmps[]; + XBoxZone zones[]; + XBoxZone actedZones[]; + XBoxZone insideZones[]; + XBoxZone breakedZones[]; + XBoxZone affectedZones[]; + + // + // Support and Resistances ... + poiDetector.CollectZones(bar, tmps); + Copy(tmps, zones, false); + + // + // OBS ... + poiDetector.CollectOBs(bar, tmps); + Copy(tmps, zones, false); + + // + // FVGs ... + poiDetector.CollectFVGs(bar, tmps); + Copy(tmps, zones, false); + + // + ExtractAffectedZones(bar, zones, affectedZones); + + // + // Acteds Zones ... + ExtractActeds(bar, actedZones, affectedZones); + + // + // Inside Zones ... + ExtractInsides(bar, insideZones, affectedZones); + + // + // Breaked Zones ... + ExtractBreakeds(bar, breakedZones, affectedZones); + + // + // Cleanup ... + XClean(tmps); + XClean(zones); + XClean(actedZones); + XClean(insideZones); + XClean(breakedZones); + XClean(affectedZones); + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 4 ... + * + * @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 Strategy3HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Configurations ... + int patternsFillValidation = 3; + + // + // Validation Flags ... + bool validateByBarPatterns = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XPatternAnalysis pBarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + + // + int pBarBullishPatternsCount = + !pBarPatterns.IsValid() + ? 0 + : pBarPatterns.Count(X_DIRECTION_BULLISH); + bool isPBarFillBullishPatterns = + IsValidSize(pBarBullishPatternsCount) && + pBarBullishPatternsCount >= patternsFillValidation; + bool isPBarHasBullishPatterns = + pBarPatterns.IsValid() && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + int pBarBearishPatternsCount = + !pBarPatterns.IsValid() + ? 0 + : pBarPatterns.Count(X_DIRECTION_BEARISH); + bool isPBarFillBearishPatterns = + IsValidSize(pBarBearishPatternsCount) && + pBarBearishPatternsCount >= patternsFillValidation; + bool isPBarHasBearishPatterns = + pBarPatterns.IsValid() && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + bool hasSupport = HasSupport(); + bool hasResistance = HasResistance(); + + // + bool isP2BarInSupport = hasSupport && + pBar.low > support.lower && + p2Bar.low < support.upper && + p2Bar.low > support.lower; + + // + bool isP2BarInResistance = hasResistance && + pBar.high < resistance.upper && + p2Bar.high > resistance.lower && + p2Bar.high < resistance.upper; + + // + isBullish = + hasSupport && + isP2BarInSupport; + + // + isBearish = + hasResistance && + isP2BarInResistance; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Validate Bar Patterns ... + if (result && validateByBarPatterns) + { + // + isBullish = + isBullish && + isPBarHasBullishPatterns && + isPBarFillBullishPatterns; + + // + isBearish = + isBearish && + isPBarHasBearishPatterns && + isPBarFillBearishPatterns; + + // + // Summarize result ... + result = isBullish || isBearish; + } + + // + if (result) + { + // + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + // poiDrawer.DrawPatternAnalysis(p2BarPatterns, structureDrawConfig.barAnalysisDrawConfig); + DebugBreak(); + + // + result = false; + isBullish = false; + isBearish = false; + } + + // + // Validate ... + result = isBullish || + isBearish; + + // + // Prepare Zone ... + if (result) + { + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + // pBarPatterns.Clean(); + // patternConfig.Clean(); + // p2BarPatterns.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 4 ... + * + * Strategy 4: + * =========== + * - Works Based on Order Flow ... + * - Looking for new and Fresh Order Flow ... + * - Validate Bar is Inside Order Flow ... + * - Validate Bar has Proper Pattern ... + * - Validate Bar Based on ATR Band in two Step: + * - Step 1: Bars is Inside ATR Band (Middle) ... + * - Step 2: Trigger Bars Close Price based on ATR Band ... + * - Validate Order Flow based on Market Structure Zone ... + * - Validate Trigger Bar based on InDirectional Market Structure Zones ... + * + * Manipulations: + * ================ + * there are Some Flags properties to Change Validations in Strategy ... + * we can use them for Testing Purposes ... + * + * @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 Strategy4HasSignal( + XOHCL &bar, + XBoxZone &zone, + XTarget &targets[], + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Validation Flags ... + bool validateBarInsideZone = true; + bool validateByBarPatterns = true; + bool validateByXFIMABoundary = true; + bool validateByBarInsideATRBand = true; + bool validateByBarBasedOnATRBand = true; + bool validateByXFIMABoundaryTrend = true; + bool validateMarketStructureHasDirectionalZone = true; + bool validateMarketStructureDirectionalZoneInsideOrderFlow = true; + bool validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP = true; + + // + // Define Requirements ... + + // + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + bool isBullish = false; + bool isBearish = false; + + // + // Read PBar ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Do ... + + // + // Retrieve pBar Patterns ... + XPatternAnalysis pBarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + + // + // Detecting OrderFlow ... + XBoxZone oFlow[]; + bool hasOrderFlow = poiDetector.HasOrderFlow( + p3Bar, + dir, + oFlow, + structureConfig.orderFlowValidation, + structureConfig.orderFlowUseOB, + structureConfig.orderFlowUseFVG, + structureConfig.orderFlowUseSupportAndResistance, + patternConfig.supportAndResistanceLoopbackLength, + patternConfig.supportAndResistanceValidationLength, + structureConfig.loopback // + ); + + // + XTrend boundaryTrend; + double boundaryMax = EMPTY_VALUE; + double boundaryMin = EMPTY_VALUE; + double atrBandUpper = EMPTY_VALUE; + double atrBandLower = EMPTY_VALUE; + double atrBandMiddle = EMPTY_VALUE; + + // + isBullish = hasOrderFlow && + IsXBullish(dir); + + // + isBearish = hasOrderFlow && + IsXBearish(dir); + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Force Price of p2Bar is Inside Order Flow ... + if (result && validateBarInsideZone) + { + // + double orderFlowUpper = 0; + double orderFlowLower = 0; + + // + int idx = -1; + idx = GetHighest(oFlow); + if (IsValidIndex(idx)) + { + orderFlowUpper = oFlow[idx].upper; + } + idx = GetLowest(oFlow); + if (IsValidIndex(idx)) + { + orderFlowLower = oFlow[idx].lower; + } + + // + result = NotEmptyZero(orderFlowUpper) && + NotEmptyZero(orderFlowLower) && + orderFlowUpper > orderFlowLower && + (isBullish + ? p2Bar.low < orderFlowUpper + : p2Bar.high > orderFlowLower); + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force PBar Has Pattern ... + if (result && validateByBarPatterns) + { + // + // Analyse Bar Patterns ... + result = pBarPatterns.IsValid(); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + result && + // (bar.close > pBar.low || + // bar.open > pBar.low) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // + ); + + // + // Bearish ... + bool isPBarHasBearishPatterns = + result && + // (bar.close < pBar.high || + // bar.open < pBar.high) && + ( + // + pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // + ); + + // + isBullish = + isBullish && + isPBarHasBullishPatterns && + !isPBarHasBearishPatterns; + + // + isBearish = + isBearish && + isPBarHasBearishPatterns && + !isPBarHasBullishPatterns; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force P2Bar Place Checking based on ATR Band ... + if (result && validateByBarInsideATRBand) + { + // + atrBandUpper = fimaHelper.GetATRBandUpper(p2Bar.Index()); + atrBandLower = fimaHelper.GetATRBandLower(p2Bar.Index()); + + // + atrBandMiddle = atrBandLower + ((atrBandUpper - atrBandLower) / 2); + + // + isBullish = + isBullish && + NotEmptyZero(atrBandMiddle) && + p2Bar.low < atrBandMiddle; + + // + isBearish = + isBearish && + NotEmptyZero(atrBandMiddle) && + p2Bar.high > atrBandMiddle; + + // + // Summarize Result ... + result = isBullish || isBearish; + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Force PBar Place Checking based on ATR Band ... + if (result && validateByBarBasedOnATRBand) + { + // + atrBandUpper = fimaHelper.GetATRBandUpper(pBar.Index()); + atrBandLower = fimaHelper.GetATRBandLower(pBar.Index()); + + // + result = + NotEmptyZero(atrBandUpper) && + NotEmptyZero(atrBandLower) && + (isBullish + ? pBar.close > atrBandLower + : pBar.close < atrBandUpper); + + // + // Reset Flags ... + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // for Bullish has Support ... + // for Bearish has Resistance ... + if (result && validateMarketStructureHasDirectionalZone) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone _support; + XBoxZone _resistance; + + // + // Check Market Strucutre Has Support / Resistance ... + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Retrieve Support / Resistance Zone ... + if (hasSupport) + { + pBarPatterns.GetSupport(tmpBar, tmpPivot, _support); + } + if (hasResistance) + { + pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + } + + // + // Validate Support and Resistance by Order Flow ... + + // + // Converts Order Flow to Zone ... + XBoxZone ofZone; + bool hasOFBox = ToBox(ofZone, oFlow); + + // + // Check Market Strucutre Support and Resistance Validation ... + if (validateMarketStructureDirectionalZoneInsideOrderFlow) + { + // + hasSupport = + hasOFBox && + hasSupport && + ofZone.lower < _support.lower && + ofZone.upper > _support.upper; + + // + hasResistance = + hasOFBox && + hasResistance && + ofZone.lower < _resistance.lower && + ofZone.upper > _resistance.upper; + } + + // + // Validate Directional Support or Resistance Exists ... + + // + isBullish = + isBullish && + hasSupport; + + // + isBearish = + isBearish && + hasResistance; + + // + // Cleanup ... + ofZone.Clean(); + tmpBar.Clean(); + _support.Clean(); + tmpPivot.Clean(); + _resistance.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate Makret Structure Has Not Indirectional Zone ... + if (result && validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + XBoxZone _support; + XBoxZone _resistance; + + // + // Check Market Strucutre Has Support / Resistance ... + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Retrieve Support / Resistance Zone ... + if (hasSupport) + { + pBarPatterns.GetSupport(tmpBar, tmpPivot, _support); + } + if (hasResistance) + { + pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + } + + // + // Converts Order Flow to Zone ... + XBoxZone ofZone; + bool hasOFBox = ToBox(ofZone, oFlow); + + // + bool hasIndirectionalZone = + (isBullish && hasResistance) || + (isBearish && hasSupport); + if (hasIndirectionalZone) + { + // + // Here we Have to Validate Zone Place ... + + // + double point = GetPoints(bar.symbol); + double entry = GetEntry(bar.symbol, dir); + double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; + double risk = MathAbs(entry - (isBullish ? oFlow[0].lower : oFlow[0].upper)) + (slAddition * point); + double reward = (defaultSignalR2R * risk); + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // Bullish ... + if (isBullish && hasResistance) + { + hasResistance = _resistance.lower <= tp; + } + + // + // Bearish ... + if (isBearish && hasSupport) + { + hasSupport = _support.upper >= tp; + } + } + + // + isBullish = + isBullish && + !hasResistance; + + // + isBearish = + isBearish && + !hasSupport; + + // + // Cleanup ... + ofZone.Clean(); + tmpBar.Clean(); + _support.Clean(); + tmpPivot.Clean(); + _resistance.Clean(); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + } + + // + // Prepare Zone and do Zone Based Validations ... + if (result) + { + // + zone.Clean(); + result = ToBox( + p2Bar, + zone, + dir, + X_BAR_PATTERN_PINNED // + ); + + // + // Refine Zone ... + zone.to = bar.time; + zone.upper = MathMax(zone.upper, atrBandMiddle); + zone.lower = MathMin(zone.lower, atrBandMiddle); + + // + // Validate by XFIMA Boundary ... + if (result && validateByXFIMABoundary) + { + // + // Reading Zones Boundary ... + XPivot uppers[]; + XPivot lowers[]; + int boundariesCount = poiDetector.CollectZonesBoundary(uppers, lowers, zone); + int lowestIDX = GetLowest(lowers); + int highestIDX = GetHighest(uppers); + if (IsValidIndex(lowestIDX)) + { + boundaryMin = lowers[lowestIDX].value; + } + if (IsValidIndex(highestIDX)) + { + boundaryMax = uppers[highestIDX].value; + } + + // + isBullish = + isBullish && + IsValidIndex(lowestIDX) && + IsValidSize(boundariesCount) && + zone.lower > lowers[lowestIDX].value; + + // + isBearish = + isBearish && + IsValidIndex(highestIDX) && + IsValidSize(boundariesCount) && + zone.upper < uppers[highestIDX].value; + + // + // Detect Directions of Boundary ... + + // + bool isUppersBullish = uppers[0].value > uppers[1].value; + bool isUppersBearish = uppers[0].value < uppers[1].value; + + // + bool isLowersBullish = lowers[0].value > lowers[1].value; + bool isLowersBearish = lowers[0].value < lowers[1].value; + + // + bool isBoundaryBullish = isUppersBullish || isLowersBullish; + bool isBoundaryBearish = isUppersBearish || isLowersBearish; + + // + bool isBoundaryTrend = isBoundaryBullish || isBoundaryBearish; + if (isBoundaryTrend) + { + // + double fromPrice = + isBoundaryBullish + ? isLowersBullish + ? lowers[1].value + : isUppersBullish + ? uppers[1].value + : EMPTY_VALUE + : isBoundaryBearish + ? isUppersBearish + ? uppers[1].value + : isLowersBearish + ? lowers[1].value + : EMPTY_VALUE + : EMPTY_VALUE; + + // + double toPrice = + isBoundaryBullish + ? isLowersBullish + ? lowers[0].value + : isUppersBullish + ? uppers[0].value + : EMPTY_VALUE + : isBoundaryBearish + ? isUppersBearish + ? uppers[0].value + : isLowersBearish + ? lowers[0].value + : EMPTY_VALUE + : EMPTY_VALUE; + + // + if (NotEmptyZero(fromPrice) && NotEmptyZero(toPrice)) + { + // + boundaryTrend.Init( + zone.symbol, + zone.period, + bar.time, + fromPrice, + zone.from, + toPrice, + zone.to // + ); + + // + // Validate By Boundary Trend ... + if (validateByXFIMABoundaryTrend) + { + // + isBullish = + isBullish && + boundaryTrend.IsValid() && + boundaryTrend.IsBullish(); + + // + isBearish = + isBearish && + boundaryTrend.IsValid() && + boundaryTrend.IsBearish(); + + // + // Summarizing Result ... + result = isBullish || isBearish; + if (!result) + { + zone.Clean(); + } + } + } + } + + // + // Cleanup ... + XClean(uppers); + XClean(lowers); + + // + // Summarize Result ... + result = isBullish || isBearish; + if (!result) + { + zone.Clean(); + } + } + + // + // Draws ... + if (result) + { + // + if (NotEmptyZero(boundaryMin)) + { + // + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + iConfig.trendRayLeft = false; + iConfig.trendRayRight = false; + poiDrawer.DrawTrendLine( + "LOWEST_" + ToXString(TimeToSeconds(zone.from)), + boundaryMin, + zone.from, + boundaryMin, + zone.to, + iConfig, + clrYellow // + ); + iConfig.Clean(); + } + + // + if (NotEmptyZero(boundaryMax)) + { + // + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + iConfig.trendRayLeft = false; + iConfig.trendRayRight = false; + poiDrawer.DrawTrendLine( + "HIGHEST_" + ToXString(TimeToSeconds(zone.from)), + boundaryMax, + zone.from, + boundaryMax, + zone.to, + iConfig, + clrYellow // + ); + iConfig.Clean(); + } + + // + if (boundaryTrend.IsValid()) + { + // + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + iConfig.trendRayLeft = false; + iConfig.trendRayRight = false; + poiDrawer.DrawTrendLine( + boundaryTrend, + iConfig // + ); + iConfig.Clean(); + } + + // + poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + + // + DebugBreak(); + } + + // + // Manage Stops ... + if (result) + { + // + // Since Stop Management Changes Zones Edge(s) ... + // we do it here for Refining Zone ... + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + // + XTarget iTarget; + + // + // Calculate Requirements ... + double point = GetPoints(bar.symbol); + double entry = GetEntry(bar.symbol, dir); + double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; + double risk = MathAbs(entry - (isBullish ? zone.lower : zone.upper)) + (slAddition * point); + double reward = (defaultSignalR2R * risk); + double tp = isBullish + ? entry + reward + : entry - reward; + + // + // High Risk Target is Used to Protect In Profit Positiions + // from Reversal Patterns ... + double highRiskR2r = (defaultSignalR2R / 5) * 4; + double highRiskReward = highRiskR2r * risk; + double highRiskTP = isBullish + ? entry + highRiskReward + : entry - highRiskReward; + iTarget.Clean(); + iTarget.actingDistance = 5; + iTarget.doRFOnEntry = true; + iTarget.target = highRiskTP; + iTarget.volumeMultiplier = 0.8; + AddRef(iTarget, targets); + + // + // Cleanup ... + iTarget.Clean(); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + XClean(oFlow); + pBarPatterns.Clean(); + boundaryTrend.Clean(); + patternConfig.Clean(); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 index c321ee15..ff74fb2f 100644 --- a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -5497,6 +5497,37 @@ bool HasInside( return result; } +bool IsZoneAffected( + XOHCL &bar, + XBoxZone &zone // +) +{ + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + zone.IsValid(); + if (!result) + { + return result; + } + + // + bool isActed = IsActed(bar, zone); + bool isTested = IsTested(bar, zone); + bool isFakeBreaked = IsFakeBreaked(bar, zone); + + // + result = isActed || + isTested || + isFakeBreaked; + + // + return result; +} + /** * Extract Affected Zones for Specified Bar ... * diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index 7c691eab..a5cb0614 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -321,6 +321,194 @@ int GetAllBarPatters(ENUM_X_BAR_PATTERN &dest[]) // // Structures ... +/** + * Model a Trend Line ... + **/ +struct XTrend +{ + // + string symbol; + datetime time; + ENUM_TIMEFRAMES period; + + // + double fromValue; + datetime fromTime; + + // + double toValue; + datetime toTime; + + // + ENUM_X_DIRECTION dir; + + // + // Constructor ... + XTrend() + { + Clean(); + } + + // + // Tools ... + + /** + * Initialize ... + * + * @param _symbol: string, Specified Symbol ... + * @param _period: ENUM_TIMEFRAMES, Specified Period ... + * @param _time: datetime, Detection Time ... + * @param _fromValue: double, From Value ... + * @param _fromTime: datetime, From Time ... + * @param _toValue: double, To Value ... + * @param _toTime: datetime, To Time ... + * + * @return ( bool ) + */ + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + datetime _time, + double _fromValue, + datetime _fromTime, + double _toValue, + datetime _toTime // + ) + { + // + bool result = false; + + // + time = _time; + symbol = _symbol; + period = _period; + toTime = _toTime; + toValue = _toValue; + fromTime = _fromTime; + fromValue = _fromValue; + + // + result = IsValid(); + if (!result) + { + Clean(); + } + + // + // Setting Direction ... + if (result) + { + // + dir = + fromValue < toValue + ? X_DIRECTION_BULLISH + : fromValue > toValue + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + return result; + } + + /** + * Cleanup ... + */ + void Clean() + { + // + time = NULL; + toValue = 0; + fromValue = 0; + symbol = NULL; + period = NULL; + toTime = NULL; + fromTime = NULL; + dir = X_DIRECTION_NONE; + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + IsXValid(time) && + IsXValid(symbol) && + IsXValid(period) && + IsXValid(toTime) && + IsXValid(fromTime) && + NotEmptyZero(toValue) && + NotEmptyZero(fromValue) && + fromTime < toTime; + + // + return result; + } + + /** + * Check Trend Has Specific Direction ... + * + * @return ( bool ) + */ + bool HasTrend() + { + return IsValid() && + HasDirection(dir); + } + + /** + * Check Trend is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + return HasTrend() && + IsXBullish(dir); + } + + /** + * Check Trend is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + return HasTrend() && + IsXBearish(dir); + } + + /** + * Get Unique Identifier ... + * + * @return ( string ) + */ + string GetObjectID() + { + // + string result = NULL; + + // + if (IsValid()) + { + result = "XTRND_" + ToXString(dir) + "_" + ToXString(TimeToSeconds(time)); + } + + // + return result; + } +}; + /** * Represent a Pivot ... **/ diff --git a/Libraries/x-saherelm.x-trade.lib.mq5 b/Libraries/x-saherelm.x-trade.lib.mq5 index 354aaf97..db5da321 100644 --- a/Libraries/x-saherelm.x-trade.lib.mq5 +++ b/Libraries/x-saherelm.x-trade.lib.mq5 @@ -1098,6 +1098,43 @@ struct XPosition return result; } + // + bool IsLong() + { + return IsValid() && + IsXBullish(type); + } + + // + bool IsBullish() + { + return IsLong(); + } + + // + bool IsShort() + { + return IsValid() && + IsXBearish(type); + } + + // + bool IsBearish() + { + return IsShort(); + } + + // + ENUM_X_DIRECTION GetDirection() + { + // + return IsBullish() + ? X_DIRECTION_BULLISH + : IsBearish() + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + // // Retrieve Entry Price ... double GetEntry() @@ -1317,7 +1354,7 @@ struct XPosition // double risk = GetRisk(); int r2r = (int)GetRiskRewardRatio(); - bool isLong = IsLong(type); + bool isLong = IsLong(); for (int i = 0; i < r2r; i++) { // @@ -1350,7 +1387,7 @@ struct XPosition reachedLevel = -1; reachedPrice = 0; double tps[]; - bool isLong = IsLong(type); + bool isLong = IsLong(); double exitPrice = GetExit(); int tpLevels = CalculateTPLevels(tps); if (!IsValidSize(tpLevels) || exitPrice <= 0) @@ -3868,6 +3905,30 @@ bool IsValid(ENUM_X_ORDER_MODES value) return value != X_ORDER_MODE_NOTHING; } +// +bool IsXBullish(ENUM_POSITION_TYPE type) +{ + return type == POSITION_TYPE_BUY; +} + +// +bool IsXBullish(ENUM_X_POSITION_TYPES type) +{ + return type == X_POSITION_TYPE_LONG; +} + +// +bool IsXBearish(ENUM_POSITION_TYPE type) +{ + return type == POSITION_TYPE_SELL; +} + +// +bool IsXBearish(ENUM_X_POSITION_TYPES type) +{ + return type == X_POSITION_TYPE_SHORT; +} + // // Ages ... diff --git a/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 index 329ae440..19dccbc8 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 @@ -2887,7 +2887,7 @@ class XCXFIMAHelperParser : XCBase // double values[]; GetBoundaryValuesArray(values, barIndex); - result = GetMax(values); + result = GetMin(values); // return result; @@ -2920,7 +2920,7 @@ class XCXFIMAHelperParser : XCBase // double values[]; GetBoundaryValuesArray(values, barIndex); - result = GetMin(values); + result = GetMax(values); // return result; diff --git a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 index 5d1c13bb..88e5c304 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -285,7 +285,15 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // // Configure ... drawLeg = true; + drawZones = true; + drawIZones = true; + drawSupport = true; + drawISupport = true; drawOrderFlow = true; + drawResistance = true; + drawIResistance = true; + + // structureConfig.Default(); structureDrawConfig.Default(); } @@ -450,60 +458,105 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // Requirements ... XGuard iGuard; bool has = false; + int samePeaks = 0; + int sameVales = 0; + double iValue = 0; + double points10 = 0; + double points50 = 0; + double points100 = 0; + int samePVValidation = 5; + bool isPeakOverLast = false; + bool isValeUnderLast = false; // - // Force Hedging ... - // bool forceHedging = (positionsCount >= 2); - // if (forceHedging) - // { - // // - // // Minimum Required Reward ... - // double minRequiredReward = 1.5; + for (int i = 0; i < positionsCount; i++) + { + // + points10 = 10 * positions[i].GetPointsValue(); + points50 = 50 * positions[i].GetPointsValue(); + points100 = 100 * positions[i].GetPointsValue(); - // // - // // Summarizing Risk and Reward of Collections ... - // // double risk = 0; - // // double volume = 0; - // // double reward = 0; - // // for (int i = 0; i < positionsCount; i++) - // // { - // // // - // // risk += positions[i].GetRisk() + positions[i].commission + (-1 * positions[i].swap); - // // reward += positions[i].profit; - // // volume += positions[i].volume; - // // } + // + // Near to TP Guard ... + has = positions[i].profit > 0; + if (has) + { + // + // Has Same Peaks or Vales ... + samePeaks = fimaParser.CountSamePeaks(barIndex); + sameVales = fimaParser.CountSameVales(barIndex); + isPeakOverLast = (fimaParser.IsPeakOverLast(barIndex) || + fimaParser.IsPeakOverLast(barIndex + 1)); + isValeUnderLast = (fimaParser.IsValeUnderLast(barIndex) || + fimaParser.IsValeUnderLast(barIndex + 1)); + has = (positions[i].IsBullish() + ? ( + isPeakOverLast && + sameVales >= samePVValidation && + fimaHelper.GetVale(barIndex) > positions[i].sl) + : positions[i].IsBearish() + ? ( + isValeUnderLast && + samePeaks >= samePVValidation && + fimaHelper.GetPeak(barIndex) < positions[i].sl) + : false); + if (has) + { + // + iGuard.Clean(); + iGuard.time = TimeCurrent(); + iGuard.symbol = positions[i].symbol; + iGuard.period = positions[i].period; + iGuard.ticket = positions[i].ticket; + iGuard.provider = positions[i].provider; + iGuard.sl = positions[i].IsBullish() + ? fimaHelper.GetVale(barIndex) - points10 + : fimaHelper.GetPeak(barIndex) + points10; + iGuard.action = X_GUARD_ACTION_TRAIL_STOP; - // // // - // // risk *= volume; - // // reward *= volume; + // + has = iGuard.IsValid(); + if (has) + { + AddRef(iGuard, guards); - // // // - // // // Calculating Can Hedge rops ... - // // has = reward >= (risk * minRequiredReward); - // // if (has) - // // { - // // // - // // iGuard.Clean(); - // // iGuard.force = true; - // // iGuard.symbol = symbol; - // // iGuard.period = period; - // // iGuard.provider = name; - // // iGuard.time = TimeCurrent(); - // // iGuard.action = X_GUARD_ACTION_HEDGE; + // + // Remove TP if in Profit SL ... + iValue = (positions[i].IsBullish() ? positions[i].entry + points10 : positions[i].entry - points10); + has = + (positions[i].IsBullish() && HasResistance()) + ? (iGuard.sl >= iValue && + positions[i].tp < resistance.lower) + : (positions[i].IsBearish() && HasSupport()) + ? (iGuard.sl <= iValue && + positions[i].tp > support.upper) + : false; + if (has) + { + // + iGuard.Clean(); + iGuard.force = false; + iGuard.tp = positions[i].IsBullish() + ? resistance.lower + : support.upper; + iGuard.time = TimeCurrent(); + iGuard.symbol = positions[i].symbol; + iGuard.period = positions[i].period; + iGuard.ticket = positions[i].ticket; + iGuard.provider = positions[i].provider; + iGuard.action = X_GUARD_ACTION_TRAIL_TARGET; - // // // - // // // Validate Guard ... - // // has = iGuard.IsValid(); - // // if (has) - // // { - // // // - // // AddRef( - // // iGuard, - // // guards // - // // ); - // // } - // // } - // } + // + has = iGuard.IsValid(); + if (has) + { + AddRef(iGuard, guards); + } + } + } + } + } + } // result = ArraySize(guards); @@ -550,6 +603,8 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // ManageLeg(bar); + ManageZones(p2Bar); + ManageIZones(p2Bar); ManageOrderFlow(p3Bar); // @@ -704,18 +759,21 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller HasDirection(orderFlowDir); } + // bool HasBullishOrderFlow() { return HasOrderFlow() && IsXBullish(orderFlowDir); } + // bool HasBearishOrderFlow() { return HasOrderFlow() && IsXBearish(orderFlowDir); } + // bool GetOrderFlowBoundary( double &upper, double &lower // @@ -774,6 +832,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller return result; } + // bool ValidateOrderFlow(XOHCL &bar) { // @@ -801,6 +860,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller return result; } + // void DrawOrderFlow() { // @@ -813,6 +873,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller poiDrawer.DrawZones(orderFlow, structureDrawConfig.drawConfig); } + // void ManageOrderFlow(XOHCL &bar) { // @@ -867,6 +928,441 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller } } + // + // Zone ... + + // + XBoxZone support; + XBoxZone resistance; + bool drawZones; + bool drawSupport; + bool drawResistance; + + // + bool HasZones() + { + return HasSupport() || + HasResistance(); + } + + // + bool HasSupport() + { + return support.IsValid(); + } + + // + bool HasResistance() + { + return resistance.IsValid(); + } + + // + bool ValidateZones(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasZones(); + if (!result) + { + return result; + } + + // + // Support ... + bool hasSupport = HasSupport(); + if (hasSupport) + { + // + result = bar.close > support.lower && + !IsBreaked(support, X_PRICE_CLOSE); + if (!result) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + + // + support.breakAt = bar.time; + support.Clean(); + } + } + + // + // Resistance ... + bool hasResistance = HasResistance(); + if (hasResistance) + { + // + result = bar.close < resistance.upper && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!result) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + + // + resistance.breakAt = bar.time; + resistance.Clean(); + } + } + + // + result = + (hasSupport && !HasSupport()) || + (hasResistance && !HasResistance()); + + // + return result; + } + + // + void DrawZones() + { + // + if (!drawZones || !HasZones()) + { + return; + } + + // + if (drawSupport && HasSupport()) + { + poiDrawer.DrawZone(support, structureDrawConfig.drawConfig); + } + + // + if (drawResistance && HasResistance()) + { + poiDrawer.DrawZone(resistance, structureDrawConfig.drawConfig); + } + } + + // + void ManageZones(XOHCL &bar) + { + // + // Validate Exists ... + if (HasZones()) + { + // + if (!ValidateZones(bar)) + { + // + // Invalidate Zones ... + + // + // Support ... + if (IsXValid(support.breakAt)) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + + // + support.Clean(); + } + + // + // Resistance ... + if (IsXValid(resistance.breakAt)) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + + // + resistance.Clean(); + } + } + } + + // + // Detect New ... + XOHCL tmpBar; + bool has = false; + + // + // Detect Support ... + if (!HasSupport()) + { + // + has = poiDetector.HasSupport( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToSupportBox(tmpBar, support, bar.time); + has = + has && + !IsBreaked(support, X_PRICE_CLOSE); + if (!has) + { + // + if (support.IsValid()) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + } + + // + support.Clean(); + } + } + } + + // + // Detect Resistance ... + if (!HasResistance()) + { + // + has = poiDetector.HasResistance( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToResistanceBox(tmpBar, resistance, bar.time); + has = + has && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!has) + { + // + if (resistance.IsValid()) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + } + + // + resistance.Clean(); + } + } + } + + // + // Update Exists ... + if (HasZones()) + { + // + if (HasSupport()) + { + // + support.to = bar.time; + support.type = "XFIMASup"; + } + + // + if (HasResistance()) + { + // + resistance.to = bar.time; + resistance.type = "XFIMARes"; + } + + // + DrawZones(); + } + + // + // Cleanup ... + tmpBar.Clean(); + } + + // + XBoxZone iSupport; + XBoxZone iResistance; + bool drawIZones; + bool drawISupport; + bool drawIResistance; + + // + bool HasIZones() + { + // + return HasISupport() || + HasIResistance(); + } + + // + bool HasISupport() + { + return iSupport.IsValid(); + } + + // + bool HasIResistance() + { + return iResistance.IsValid(); + } + + // + void DrawIZones() + { + // + if (!drawIZones || !HasIZones()) + { + return; + } + + // + if (drawISupport && HasISupport()) + { + poiDrawer.DrawZone(iSupport, structureDrawConfig.drawConfig); + } + + // + if (drawIResistance && HasIResistance()) + { + poiDrawer.DrawZone(iResistance, structureDrawConfig.drawConfig); + } + } + + // + bool ValidateIZones(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasIZones(); + if (!result) + { + return result; + } + + // + + // + // Support ... + bool hasSupport = HasISupport(); + if (hasSupport) + { + // + result = bar.close > iSupport.lower && + !IsBreaked(iSupport, X_PRICE_CLOSE); + if (!result) + { + // + iSupport.breakAt = bar.time; + iSupport.Clean(); + } + } + + // + // Resistance ... + bool hasResistance = HasIResistance(); + if (hasResistance) + { + // + result = bar.close < iResistance.upper && + !IsBreaked(iResistance, X_PRICE_CLOSE); + if (!result) + { + // + iResistance.breakAt = bar.time; + iResistance.Clean(); + } + } + + // + result = + (hasSupport && !HasISupport()) || + (hasResistance && !HasIResistance()); + + // + return result; + } + + // + void ManageIZones(XOHCL &bar) + { + // + // Validate Exists ... + if (HasIZones()) + { + // + if (!ValidateIZones(bar)) + { + // + // Invalidate Zones ... + + // + // Support ... + if (IsXValid(iSupport.breakAt)) + { + iSupport.Clean(); + } + + // + // Resistance ... + if (IsXValid(iResistance.breakAt)) + { + iResistance.Clean(); + } + } + } + + // + // Update Exists ... + if (HasIZones()) + { + // + if (HasISupport()) + { + // + iSupport.to = bar.time; + iSupport.type = "XFIMAISup"; + } + + // + if (HasIResistance()) + { + // + iResistance.to = bar.time; + iResistance.type = "XFIMAIRes"; + } + + // + DrawIZones(); + } + } + // // Implementing Strategies ... @@ -923,7 +1419,13 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // drawLeg = false; + drawZones = true; + drawIZones = true; + drawSupport = true; + drawISupport = true; drawOrderFlow = false; + drawResistance = true; + drawIResistance = true; // // Signal Checking ... @@ -932,19 +1434,6 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // Analyse Market Strucutre ... XFIMAMarketStructure marketStructure; - // - // Check Market ... - // result = HasLeg() && - // HasOrderFlow() && - // orderFlowDir == leg.dir; - // result = HasBearishOrderFlow(); - // if (result) - // { - // // - // result = false; - // DebugBreak(); - // } - // // Signaller 1 ... if (!result && useSignaller1) @@ -1259,7 +1748,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // Debug Breake ... if (result) { - DebugBreak(); + // DebugBreak(); } // @@ -1271,6 +1760,9 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller return result; } + // + // Custom Signal Strategies ... + /** * Check Bar Has Signal Based on Strategy 3 ... * @@ -1853,178 +2345,191 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller } // - // Define Requirements ... + // Configurations ... + // int patternsFillValidation = 3; - // - XOHCL pBar; - XOHCL p2Bar; - bool isBullish = false; - bool isBearish = false; + // // + // // Validation Flags ... + // bool validateByBarPatterns = true; - // - // Read PBar ... - result = bar.GetPreviousBar(pBar); - result = result && - pBar.GetPreviousBar(p2Bar); - if (!result) - { - // - pBar.Clean(); - p2Bar.Clean(); + // // + // // Define Requirements ... - // - return result; - } + // // + // XOHCL pBar; + // XOHCL p2Bar; + // XOHCL p3Bar; + // bool isBullish = false; + // bool isBearish = false; - // - // Do ... - // XFIMA Consolidation ... + // // + // // Read PBar ... + // result = bar.GetPreviousBar(pBar); + // result = result && + // pBar.GetPreviousBar(p2Bar); + // result = result && + // p2Bar.GetPreviousBar(p3Bar); + // if (!result) + // { + // // + // pBar.Clean(); + // p2Bar.Clean(); + // p3Bar.Clean(); - // - bool isConsolidation = poiDetector.DetectPVConsolidationZone( - zone, - pBar.Index(), - true, // Force PV Break ... - true // Force Has Sar Switch ... - ); + // // + // return result; + // } - // - isBullish = - isConsolidation && - zone.IsBullish(); + // // + // // Do ... - // - isBearish = - isConsolidation && - zone.IsBearish(); + // // + // // Retrieve pBar Patterns ... + // XPatternAnalysis pBarPatterns; + // XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + // poiDetector.AnalyseBarPatterns( + // pBar, + // pBarPatterns, + // patternConfig // + // ); - // - // Validate based on Bars Patterns ... - bool validateByBarPatterns = true; - if (validateByBarPatterns) - { - // - // Reading pBar Patterns ... - XPatternAnalysis pBarAnalysis; - poiDetector.AnalyseBarPatterns( - pBar, - pBarAnalysis, - structureConfig.barsAnalysisConfig // - ); + // // + // int pBarBullishPatternsCount = + // !pBarPatterns.IsValid() + // ? 0 + // : pBarPatterns.Count(X_DIRECTION_BULLISH); + // bool isPBarFillBullishPatterns = + // IsValidSize(pBarBullishPatternsCount) && + // pBarBullishPatternsCount >= patternsFillValidation; + // bool isPBarHasBullishPatterns = + // pBarPatterns.IsValid() && + // ( + // // + // pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || + // pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || + // pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || + // pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || + // pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) + // // + // ); - // - // Bullish ... - bool isPBarHasBullishPatterns = - (bar.close > pBar.low || - bar.open > pBar.low) && - ( - // - pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || - pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || - pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || - pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || - pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) - // - ); + // // + // int pBarBearishPatternsCount = + // !pBarPatterns.IsValid() + // ? 0 + // : pBarPatterns.Count(X_DIRECTION_BEARISH); + // bool isPBarFillBearishPatterns = + // IsValidSize(pBarBearishPatternsCount) && + // pBarBearishPatternsCount >= patternsFillValidation; + // bool isPBarHasBearishPatterns = + // pBarPatterns.IsValid() && + // ( + // // + // pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || + // pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || + // pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || + // pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || + // pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) + // // + // ); - // - // Bearish ... - bool isPBarHasBearishPatterns = - (bar.close < pBar.high || - bar.open < pBar.high) && - ( - // - pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || - pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || - pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || - pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || - pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) - // - ); + // // + // bool hasSupport = HasSupport(); + // bool hasResistance = HasResistance(); - // - isBullish = - isBullish && - isPBarHasBullishPatterns && - !isPBarHasBearishPatterns; + // // + // bool isP2BarInSupport = hasSupport && + // pBar.low > support.lower && + // p2Bar.low < support.upper && + // p2Bar.low > support.lower; - // - isBearish = - isBearish && - isPBarHasBearishPatterns && - !isPBarHasBullishPatterns; + // // + // bool isP2BarInResistance = hasResistance && + // pBar.high < resistance.upper && + // p2Bar.high > resistance.lower && + // p2Bar.high < resistance.upper; - // - // Summarize Result ... - result = isBullish || - isBearish; - } + // // + // isBullish = + // hasSupport && + // isP2BarInSupport; - // - // Checking PullBack ... - bool validateByPullback = false; - if (validateByPullback) - { - // - XBoxZone pullback; - ENUM_X_DIRECTION pullbackDir; - bool isPullBack = result && - poiDetector.IsPullbackPattern( - pBar, - pullback, - pullbackDir, - 2, - false // Force Break ... - ); - bool isPullbackBullish = isPullBack && - IsXBullish(pullbackDir); - bool isPullbackBearish = isPullBack && - IsXBearish(pullbackDir); + // // + // isBearish = + // hasResistance && + // isP2BarInResistance; - // - isBullish = - isBullish && - isPullbackBullish; + // // + // // Summarize Result ... + // result = isBullish || isBearish; - // - isBearish = - isBearish && - isPullbackBearish; + // // + // // Validate Bar Patterns ... + // if (result && validateByBarPatterns) + // { + // // + // isBullish = + // isBullish && + // isPBarHasBullishPatterns && + // isPBarFillBullishPatterns; - // - // Summarize Result ... - result = isBullish || - isBearish; - } + // // + // isBearish = + // isBearish && + // isPBarHasBearishPatterns && + // isPBarFillBearishPatterns; - // - // Validate ... - result = isBullish || - isBearish; + // // + // // Summarize result ... + // result = isBullish || isBearish; + // } - // - // Prepare Zone ... - if (result) - { - } + // // + // if (result) + // { + // // + // poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + // // poiDrawer.DrawPatternAnalysis(p2BarPatterns, structureDrawConfig.barAnalysisDrawConfig); + // DebugBreak(); - // - // Prepare Targets ... - if (result) - { - } + // // + // result = false; + // isBullish = false; + // isBearish = false; + // } - // - // Cleanup ... - if (!result) - { - // - zone.Clean(); - XClean(targets); - dir = X_DIRECTION_NONE; - } - pBar.Clean(); - p2Bar.Clean(); + // // + // // Validate ... + // result = isBullish || + // isBearish; + + // // + // // Prepare Zone ... + // if (result) + // { + // } + + // // + // // Prepare Targets ... + // if (result) + // { + // } + + // // + // // Cleanup ... + // if (!result) + // { + // // + // zone.Clean(); + // XClean(targets); + // dir = X_DIRECTION_NONE; + // } + // pBar.Clean(); + // p2Bar.Clean(); + // p3Bar.Clean(); + // // pBarPatterns.Clean(); + // // patternConfig.Clean(); + // // p2BarPatterns.Clean(); // return result; @@ -2085,8 +2590,10 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // Validation Flags ... bool validateBarInsideZone = true; bool validateByBarPatterns = true; + bool validateByXFIMABoundary = true; bool validateByBarInsideATRBand = true; bool validateByBarBasedOnATRBand = true; + bool validateByXFIMABoundaryTrend = true; bool validateMarketStructureHasDirectionalZone = true; bool validateMarketStructureDirectionalZoneInsideOrderFlow = true; bool validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP = true; @@ -2151,6 +2658,9 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller ); // + XTrend boundaryTrend; + double boundaryMax = EMPTY_VALUE; + double boundaryMin = EMPTY_VALUE; double atrBandUpper = EMPTY_VALUE; double atrBandLower = EMPTY_VALUE; double atrBandMiddle = EMPTY_VALUE; @@ -2343,8 +2853,8 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // XOHCL tmpBar; XPivot tmpPivot; - XBoxZone support; - XBoxZone resistance; + XBoxZone _support; + XBoxZone _resistance; // // Check Market Strucutre Has Support / Resistance ... @@ -2355,11 +2865,11 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // Retrieve Support / Resistance Zone ... if (hasSupport) { - pBarPatterns.GetSupport(tmpBar, tmpPivot, support); + pBarPatterns.GetSupport(tmpBar, tmpPivot, _support); } if (hasResistance) { - pBarPatterns.GetResistance(tmpBar, tmpPivot, resistance); + pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); } // @@ -2378,15 +2888,15 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller hasSupport = hasOFBox && hasSupport && - ofZone.lower < support.lower && - ofZone.upper > support.upper; + ofZone.lower < _support.lower && + ofZone.upper > _support.upper; // hasResistance = hasOFBox && hasResistance && - ofZone.lower < resistance.lower && - ofZone.upper > resistance.upper; + ofZone.lower < _resistance.lower && + ofZone.upper > _resistance.upper; } // @@ -2406,9 +2916,9 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // Cleanup ... ofZone.Clean(); tmpBar.Clean(); - support.Clean(); + _support.Clean(); tmpPivot.Clean(); - resistance.Clean(); + _resistance.Clean(); // // Summarize Result ... @@ -2422,8 +2932,8 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // XOHCL tmpBar; XPivot tmpPivot; - XBoxZone support; - XBoxZone resistance; + XBoxZone _support; + XBoxZone _resistance; // // Check Market Strucutre Has Support / Resistance ... @@ -2434,11 +2944,11 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // Retrieve Support / Resistance Zone ... if (hasSupport) { - pBarPatterns.GetSupport(tmpBar, tmpPivot, support); + pBarPatterns.GetSupport(tmpBar, tmpPivot, _support); } if (hasResistance) { - pBarPatterns.GetResistance(tmpBar, tmpPivot, resistance); + pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); } // @@ -2469,14 +2979,14 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // Bullish ... if (isBullish && hasResistance) { - hasResistance = resistance.lower <= tp; + hasResistance = _resistance.lower <= tp; } // // Bearish ... if (isBearish && hasSupport) { - hasSupport = support.upper >= tp; + hasSupport = _support.upper >= tp; } } @@ -2494,9 +3004,9 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // Cleanup ... ofZone.Clean(); tmpBar.Clean(); - support.Clean(); + _support.Clean(); tmpPivot.Clean(); - resistance.Clean(); + _resistance.Clean(); // // Summarize Result ... @@ -2520,7 +3030,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller } // - // Prepare Zone ... + // Prepare Zone and do Zone Based Validations ... if (result) { // @@ -2538,6 +3048,210 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller zone.upper = MathMax(zone.upper, atrBandMiddle); zone.lower = MathMin(zone.lower, atrBandMiddle); + // + // Validate by XFIMA Boundary ... + if (result && validateByXFIMABoundary) + { + // + // Reading Zones Boundary ... + XPivot uppers[]; + XPivot lowers[]; + int boundariesCount = poiDetector.CollectZonesBoundary(uppers, lowers, zone); + int lowestIDX = GetLowest(lowers); + int highestIDX = GetHighest(uppers); + if (IsValidIndex(lowestIDX)) + { + boundaryMin = lowers[lowestIDX].value; + } + if (IsValidIndex(highestIDX)) + { + boundaryMax = uppers[highestIDX].value; + } + + // + isBullish = + isBullish && + IsValidIndex(lowestIDX) && + IsValidSize(boundariesCount) && + zone.lower > lowers[lowestIDX].value; + + // + isBearish = + isBearish && + IsValidIndex(highestIDX) && + IsValidSize(boundariesCount) && + zone.upper < uppers[highestIDX].value; + + // + // Detect Directions of Boundary ... + + // + bool isUppersBullish = uppers[0].value > uppers[1].value; + bool isUppersBearish = uppers[0].value < uppers[1].value; + + // + bool isLowersBullish = lowers[0].value > lowers[1].value; + bool isLowersBearish = lowers[0].value < lowers[1].value; + + // + bool isBoundaryBullish = isUppersBullish || isLowersBullish; + bool isBoundaryBearish = isUppersBearish || isLowersBearish; + + // + bool isBoundaryTrend = isBoundaryBullish || isBoundaryBearish; + if (isBoundaryTrend) + { + // + double fromPrice = + isBoundaryBullish + ? isLowersBullish + ? lowers[1].value + : isUppersBullish + ? uppers[1].value + : EMPTY_VALUE + : isBoundaryBearish + ? isUppersBearish + ? uppers[1].value + : isLowersBearish + ? lowers[1].value + : EMPTY_VALUE + : EMPTY_VALUE; + + // + double toPrice = + isBoundaryBullish + ? isLowersBullish + ? lowers[0].value + : isUppersBullish + ? uppers[0].value + : EMPTY_VALUE + : isBoundaryBearish + ? isUppersBearish + ? uppers[0].value + : isLowersBearish + ? lowers[0].value + : EMPTY_VALUE + : EMPTY_VALUE; + + // + if (NotEmptyZero(fromPrice) && NotEmptyZero(toPrice)) + { + // + boundaryTrend.Init( + zone.symbol, + zone.period, + bar.time, + fromPrice, + zone.from, + toPrice, + zone.to // + ); + + // + // Validate By Boundary Trend ... + if (validateByXFIMABoundaryTrend) + { + // + isBullish = + isBullish && + boundaryTrend.IsValid() && + boundaryTrend.IsBullish(); + + // + isBearish = + isBearish && + boundaryTrend.IsValid() && + boundaryTrend.IsBearish(); + + // + // Summarizing Result ... + result = isBullish || isBearish; + if (!result) + { + zone.Clean(); + } + } + } + } + + // + // Cleanup ... + XClean(uppers); + XClean(lowers); + + // + // Summarize Result ... + result = isBullish || isBearish; + if (!result) + { + zone.Clean(); + } + } + + // + // Draws ... + if (result) + { + // // + // if (NotEmptyZero(boundaryMin)) + // { + // // + // XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + // iConfig.trendRayLeft = false; + // iConfig.trendRayRight = false; + // poiDrawer.DrawTrendLine( + // "LOWEST_" + ToXString(TimeToSeconds(zone.from)), + // boundaryMin, + // zone.from, + // boundaryMin, + // zone.to, + // iConfig, + // clrYellow // + // ); + // iConfig.Clean(); + // } + + // // + // if (NotEmptyZero(boundaryMax)) + // { + // // + // XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + // iConfig.trendRayLeft = false; + // iConfig.trendRayRight = false; + // poiDrawer.DrawTrendLine( + // "HIGHEST_" + ToXString(TimeToSeconds(zone.from)), + // boundaryMax, + // zone.from, + // boundaryMax, + // zone.to, + // iConfig, + // clrYellow // + // ); + // iConfig.Clean(); + // } + + // // + // if (boundaryTrend.IsValid()) + // { + // // + // XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + // iConfig.trendRayLeft = false; + // iConfig.trendRayRight = false; + // poiDrawer.DrawTrendLine( + // boundaryTrend, + // iConfig // + // ); + // iConfig.Clean(); + // } + + // // + // poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + // poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + + // // + // DebugBreak(); + } + // // Manage Stops ... if (result) @@ -2545,13 +3259,6 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // // Since Stop Management Changes Zones Edge(s) ... // we do it here for Refining Zone ... - - // - poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); - poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); - - // - DebugBreak(); } // @@ -2608,8 +3315,10 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller pBar.Clean(); p2Bar.Clean(); p3Bar.Clean(); - XClean(orderFlow); + XClean(oFlow); pBarPatterns.Clean(); + boundaryTrend.Clean(); + patternConfig.Clean(); // return result; diff --git a/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 index 46b05e54..0f1de116 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 @@ -478,6 +478,174 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector return result; } + bool DetectXPVZone( + XBoxZone &zone, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + + // + // Normalize ... + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + result = fimaParser.IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(fimaParser.symbol, fimaParser.period, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + // Vale ... + bool isValeOverLast = fimaParser.IsValeOverLast(barIndex); + bool isValeUnderLast = fimaParser.IsValeUnderLast(barIndex); + bool isNewVale = isValeOverLast || isValeUnderLast; + + // + // Peak ... + bool isPeakOverLast = fimaParser.IsPeakOverLast(barIndex); + bool isPeakUnderLast = fimaParser.IsPeakUnderLast(barIndex); + bool isNewPeak = isPeakOverLast || isPeakUnderLast; + + // + // Detect new Peak or Vale ... + result = isNewVale || isNewPeak; + + // + // Count Same Peaks and Same Vales from Index of Prev ... + int pIDX = barIndex + 1; + int samePeaks = fimaParser.CountSamePeaks(pIDX); + int sameVales = fimaParser.CountSameVales(pIDX); + result = + result && + IsValidSize(samePeaks) && + IsValidSize(sameVales); + + // + // Try to Evaluate Zone ... + int peaksStartIndex = pIDX + samePeaks; + int valesStartIndex = pIDX + sameVales; + int fromIDX = MathMin(peaksStartIndex, valesStartIndex); + if (result) + { + // + // Assign Zone Symbol / Period ... + zone.symbol = fimaParser.symbol; + zone.period = fimaParser.period; + + // + // Calculate Zone Times ... + zone.to = GetBarTime( + zone.symbol, + zone.period, + barIndex // + ); + zone.from = GetBarTime( + zone.symbol, + zone.period, + fromIDX // + ); + zone.at = zone.to; + + // + // Calculate Upper and Lower ... + zone.upper = fimaHelper.GetPeak(fromIDX); + zone.lower = fimaHelper.GetVale(fromIDX); + + // + // Validate Zone Upper and Lower ... + for (int i = pIDX; i <= fromIDX; i++) + { + // + if (isValeUnderLast) + { + zone.lower = MathMin(zone.lower, fimaHelper.GetVale(i)); + } + + // + if (isPeakOverLast) + { + zone.upper = MathMax(zone.upper, fimaHelper.GetPeak(i)); + } + } + + // + // Calculate Zone Direction ... + zone.dir = + isValeOverLast + ? X_DIRECTION_BULLISH + : isValeUnderLast + ? X_DIRECTION_BEARISH + : isPeakOverLast + ? X_DIRECTION_BULLISH + : isPeakUnderLast + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + // Refine Zone Upper / Lower based on Direction and Bars ... + + // + // Detect Highest High / Lowest Low ... + double ll = bar.FindLowest(fromIDX - barIndex, MODE_LOW); + double hh = bar.FindHighest(fromIDX - barIndex, MODE_HIGH); + + // + if (isNewVale) + { + zone.upper = MathMin(zone.upper, hh); + } + + // + if (isNewPeak) + { + zone.lower = MathMax(zone.lower, ll); + } + + // + // Set Zone Type ... + zone.type = ToXString(XFIMA_PIVOT_PV); + + // + // Summarize result ... + result = zone.IsValid(); + } + + // + result = zone.IsValid(); + + // + // Cleanup ... + if (!result) + { + zone.Clean(); + } + bar.Clean(); + + // + return result; + } + // // Analysors ... @@ -1422,6 +1590,105 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector return result; } + int CollectZonesBoundary( + XPivot &uppers[], + XPivot &lowers[], + XBoxZone &zone // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(uppers); + XClean(lowers); + + // + // Validate ... + bool has = zone.IsValid() && + fimaParser.IsValid(); + if (!has) + { + return result; + } + + // + double iUpper; + double iLower; + datetime iTime; + XPivot upperPivot; + XPivot lowerPivot; + int start = zone.ToIndex(); + int end = zone.FromIndex(); + for (int i = start; i <= end; i++) + { + // + iUpper = fimaParser.GetBoundaryMax(i); + iLower = fimaParser.GetBoundaryMin(i); + iTime = GetBarTime(zone.symbol, zone.period, i); + + // + has = + IsXValid(iTime) && + NotEmptyZero(iUpper) && + NotEmptyZero(iLower); + if (has) + { + // + // Upper Pivot ... + upperPivot.Clean(); + has = upperPivot.Init( + iUpper, + iTime, + zone.symbol, + zone.dir, + zone.period, + X_PIVOT_TYPE_PEAK // + ); + if (has) { + upperPivot.prefix = "XBNDUP"; + } + + // + // Lower Pivot ... + lowerPivot.Clean(); + has = lowerPivot.Init( + iLower, + iTime, + zone.symbol, + zone.dir, + zone.period, + X_PIVOT_TYPE_VALE // + ); + if (has) { + lowerPivot.prefix = "XBNDLO"; + } + + // + has = upperPivot.IsValid() && + lowerPivot.IsValid(); + if (has) + { + // + AddRef(upperPivot, uppers); + AddRef(lowerPivot, lowers); + } + } + } + + // + result = MathMin(ArraySize(uppers), ArraySize(lowers)); + + // + // Cleanup ... + upperPivot.Clean(); + lowerPivot.Clean(); + + // + return result; + } + // // Others ...