diff --git a/Classes/x-saherelm.x-backtester.expert.class.mq5 b/Classes/x-saherelm.x-backtester.expert.class.mq5 index 1b80e005..f02d0bf5 100644 --- a/Classes/x-saherelm.x-backtester.expert.class.mq5 +++ b/Classes/x-saherelm.x-backtester.expert.class.mq5 @@ -365,9 +365,13 @@ class XCBackTesterEA : public XCBase ZeroMemory(eaTarget); // - eaPositionDrawer.Destroy(); - delete eaPositionDrawer; - ZeroMemory(eaPositionDrawer); + if (eaPositionDrawer != NULL) + { + // + eaPositionDrawer.Destroy(); + delete eaPositionDrawer; + ZeroMemory(eaPositionDrawer); + } // delete eaVolume; diff --git a/Classes/x-saherelm.x-market.pattern.class.mq5 b/Classes/x-saherelm.x-market.pattern.class.mq5 index bd4c74cc..b4fd8185 100644 --- a/Classes/x-saherelm.x-market.pattern.class.mq5 +++ b/Classes/x-saherelm.x-market.pattern.class.mq5 @@ -1898,6 +1898,334 @@ class XCMarketPatternDetector : public XCBase return result; } + bool HasOrderFlow( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &orderFlow[], + int orderFlowValidation = 2, + bool containsOBs = false, + bool containsFVGs = true, + bool containsSupportResistances = false, + int zonesLoopback = 5, + int zonesValidationLength = 21, + int maxRequiredZone = 0, + int loopback = 100 // + ) + { + // + bool result = false; + + // + // Prepare ... + XClean(orderFlow); + CleanDirection(dir); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 10); + zonesLoopback = NormalizeInt(zonesLoopback, 3); + maxRequiredZone = NormalizeInt(maxRequiredZone, 0); + orderFlowValidation = NormalizeInt(orderFlowValidation, 1); + zonesValidationLength = NormalizeInt(zonesValidationLength, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Collectiong Zones ... + XBoxZone tmp; + XBoxZone tmps[]; + XBoxZone _zones[]; + XBoxZone bullishZones[]; + XBoxZone bearishZones[]; + int bullishZonesCount = 0; + int bearishZonesCount = 0; + + // + // Order Blocks ... + if (containsOBs) + { + // + XClean(tmps); + CollectOBs(bar, tmps, zonesLoopback, maxRequiredZone, loopback); + FillNotExists(_zones, tmps); + } + + // + // Fair Value Gaps ... + if (containsFVGs) + { + // + XClean(tmps); + CollectFVGs(bar, tmps, zonesLoopback, maxRequiredZone, loopback); + FillNotExists(_zones, tmps); + } + + // + // Support and Resistances ... + if (containsSupportResistances) + { + // + XClean(tmps); + CollectZones(bar, tmps, zonesLoopback, maxRequiredZone, loopback); + FillNotExists(_zones, tmps); + } + + // + // Validate Zones ... + result = HasChild(_zones); + + // + // Extract Only Validated Zones ... + if (result) + { + // + ValidateBoxes( + _zones, + bar.Index() // + ); + + // + result = HasChild(_zones); + } + + // + // Separate Zones Direction ... + if (result) + { + // + bullishZonesCount = ExtractByDirection(bullishZones, _zones, X_DIRECTION_BULLISH); + bearishZonesCount = ExtractByDirection(bearishZones, _zones, X_DIRECTION_BEARISH); + + // + result = IsValidSize(bullishZonesCount) || + IsValidSize(bearishZonesCount); + } + + // + // Looking for Sequences of Zones ... + if (result) + { + // + int idx = -1; + bool has = false; + XBoxZone bullOrderFlow[]; + XBoxZone bearOrderFlow[]; + + // + // Bullish OrderFlow ... + + // + // Sorting ... + Copy(bullishZones, bullOrderFlow); + Sort( + bullOrderFlow, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH, + orderFlowValidation + 1 // + ); + bool hasBullishOrderFlow = ArraySize(bullOrderFlow) >= orderFlowValidation; + if (hasBullishOrderFlow) + { + // + // Validate Order Flow ... + Copy(bullOrderFlow, tmps); + XClean(bullOrderFlow); + while (HasChild(tmps)) + { + // + tmp.Clean(); + tmp = tmps[0]; + ArrayRemove(tmps, 0, 1); + + // + idx = GetHighest(tmps); + has = !IsValidIndex(idx) + ? true + : tmps[idx].lower < tmp.lower; + if (has) + { + AddIfNotExists(tmp, bullOrderFlow); + } + } + + // + hasBullishOrderFlow = ArraySize(bullOrderFlow) >= orderFlowValidation; + } + + // + // Bearish OrderFlow ... + + // + // Sorting ... + Copy(bearishZones, bearOrderFlow); + Sort( + bearOrderFlow, + X_SORT_BY_DATE, + X_DIRECTION_BULLISH, + orderFlowValidation + 1 // + ); + bool hasBearishOrderFlow = ArraySize(bearOrderFlow) >= orderFlowValidation; + if (hasBearishOrderFlow) + { + // + // Validate Order Flow ... + Copy(bearOrderFlow, tmps); + XClean(bearOrderFlow); + while (HasChild(tmps)) + { + // + tmp.Clean(); + tmp = tmps[0]; + ArrayRemove(tmps, 0, 1); + + // + idx = GetLowest(tmps); + has = !IsValidIndex(idx) + ? true + : tmps[idx].upper > tmp.upper; + if (has) + { + AddIfNotExists(tmp, bearOrderFlow); + } + } + + // + hasBearishOrderFlow = ArraySize(bearOrderFlow) >= orderFlowValidation; + } + + // + result = hasBullishOrderFlow || + hasBearishOrderFlow; + + // + // Validate Order Flows ... + if (result) + { + // + has = (hasBullishOrderFlow && !hasBearishOrderFlow) || + (hasBearishOrderFlow && !hasBullishOrderFlow); + + // + // When only Have One Direction ... + if (has) + { + // + if (hasBullishOrderFlow) + { + // + dir = X_DIRECTION_BULLISH; + Copy(bullOrderFlow, orderFlow); + } + else if (hasBearishOrderFlow) + { + // + dir = X_DIRECTION_BEARISH; + Copy(bearOrderFlow, orderFlow); + } + } + // + // When Two Direction Exists ... + else + { + // + // Retrieve Oldest Of Bullish / Bearish ... + int oldestBullIDX = GetOldest(bullOrderFlow); + int oldestBearIDX = GetOldest(bearOrderFlow); + result = IsValidIndex(oldestBullIDX) && + IsValidIndex(oldestBearIDX); + if (result) + { + // + dir = + bullOrderFlow[oldestBullIDX].from > bearOrderFlow[oldestBearIDX].from + ? X_DIRECTION_BULLISH + : bearOrderFlow[oldestBearIDX].from > bullOrderFlow[oldestBullIDX].from + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + result = HasDirection(dir); + if (result) + { + // + if (IsXBullish(dir)) + { + Copy(bullOrderFlow, orderFlow); + } + else if (IsXBearish(dir)) + { + Copy(bearOrderFlow, orderFlow); + } + } + } + } + + // + XClean(bullOrderFlow); + XClean(bearOrderFlow); + + // + result = HasChild(orderFlow) && + HasDirection(dir); + } + + // + // Validate Price ... + if (result) + { + // + int idx = -1; + if (IsXBullish(dir)) + { + // + idx = GetHighest(orderFlow); + result = IsValidIndex(idx) && + bar.low > orderFlow[idx].upper; + } + else + { + // + idx = GetLowest(orderFlow); + result = IsValidIndex(idx) && + bar.high < orderFlow[idx].lower; + } + } + + // + // Update To Time of Order Flow ... + if (result) + { + UpdateToTime(orderFlow, bar.time); + } + + // + // Cleanup ... + if (!result) + { + // + XClean(orderFlow); + CleanDirection(dir); + } + tmp.Clean(); + XClean(tmps); + XClean(_zones); + XClean(bullishZones); + XClean(bearishZones); + + // + return result; + } + // // FVG ... diff --git a/Documents/BKP/XFIMA Signals/signallers.mq5 b/Documents/BKP/XFIMA Signals/signallers.mq5 index d1cff402..c2e811c8 100644 --- a/Documents/BKP/XFIMA Signals/signallers.mq5 +++ b/Documents/BKP/XFIMA Signals/signallers.mq5 @@ -176,11 +176,11 @@ bool StrategyXHasSignal( } // ======================================= -// Signaller 1: +// Signallers: // ======================================= /** - * Check Bar Has Signal Based on Strategy 1 ... + * Check Bar Has Signal Based on Strategy 3 ... * * @param bar: XOHCL, reference to Bar ... * @param zone: XBoxZone, reference to holds affected zone ... @@ -216,6 +216,298 @@ bool Strategy1HasSignal( // // 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 Bond ... + + // + double pHKBondUpper = fimaHelper.GetHKBondUpper(pBar.Index()); + double pHKBondLower = fimaHelper.GetHKBondLower(pBar.Index()); + int overHKBondUpperCount = fimaHelper.CountOverHKBondUpper(pullBackStartBar, X_PRICE_LOW); + int underHKBondLowerCount = fimaHelper.CountUnderHKBondLower(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 = fimaHelper.CountSamePeaks(pBar.Index()); + int sameVales = fimaHelper.CountSameVales(pBar.Index()); + fimaHelper.FindLastPeakOverLast(lastPeakOverLastIDX, pBar.Index()); + fimaHelper.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 && + fimaHelper.IsSarBullish(pBar.Index()) && + (pVale >= affectedZonesBullish[insideBullishIDX].lower && + pVale <= affectedZonesBullish[insideBullishIDX].upper) + // + ; + + // + isBearish = + // + hasBearishInside && + isPullbackBearish && + isPBarHasBearishPatterns && + fimaHelper.IsSarBearish(pBar.Index()) && + (pPeak >= affectedZonesBearish[insideBearishIDX].lower && + pPeak <= affectedZonesBearish[insideBearishIDX].upper) + // + ; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + if (isBullish) + { + // + poiDrawer.DrawZone( + affectedZonesBullish[insideBullishIDX], + structureDrawConfig.drawConfig // + ); + } + else + { + // + poiDrawer.DrawZone( + affectedZonesBearish[insideBearishIDX], + structureDrawConfig.drawConfig // + ); + } + + // + 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; @@ -495,307 +787,6 @@ bool Strategy1HasSignal( return result; } -// ======================================= -// Signaller 2: -// ======================================= - -/** - * Check Bar Has Signal Based on Strategy 1 ... - * - * @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; - 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 Bond ... - - // - double pHKBondUpper = fimaHelper.GetHKBondUpper(pBar.Index()); - double pHKBondLower = fimaHelper.GetHKBondLower(pBar.Index()); - int overHKBondUpperCount = fimaHelper.CountOverHKBondUpper(pullBackStartBar, X_PRICE_LOW); - int underHKBondLowerCount = fimaHelper.CountUnderHKBondLower(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 = fimaHelper.CountSamePeaks(pBar.Index()); - int sameVales = fimaHelper.CountSameVales(pBar.Index()); - fimaHelper.FindLastPeakOverLast(lastPeakOverLastIDX, pBar.Index()); - fimaHelper.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 && - fimaHelper.IsSarBullish(pBar.Index()) && - (pVale >= affectedZonesBullish[insideBullishIDX].lower && - pVale <= affectedZonesBullish[insideBullishIDX].upper) - // - ; - - // - isBearish = - // - hasBearishInside && - isPullbackBearish && - isPBarHasBearishPatterns && - fimaHelper.IsSarBearish(pBar.Index()) && - (pPeak >= affectedZonesBearish[insideBearishIDX].lower && - pPeak <= affectedZonesBearish[insideBearishIDX].upper) - // - ; - - // - // Validate ... - result = isBullish || - isBearish; - if (result) - { - // - if (isBullish) - { - // - poiDrawer.DrawZone( - affectedZonesBullish[insideBullishIDX], - structureDrawConfig.drawConfig // - ); - } - else - { - // - poiDrawer.DrawZone( - affectedZonesBearish[insideBearishIDX], - structureDrawConfig.drawConfig // - ); - } - - // - 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; -} - -// ======================================= -// Signaller 4: -// CONSOLIDATION Zones ... -// ======================================= - /** * Check Bar Has Signal Based on Strategy 4 ... * @@ -806,7 +797,7 @@ bool Strategy2HasSignal( * * @return ( bool ) */ -bool Strategy4HasSignal( +bool Strategy3HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], @@ -854,131 +845,135 @@ bool Strategy4HasSignal( return result; } - // - // Reading pBar Patterns ... - XPatternAnalysis pBarAnalysis; - poiDetector.AnalyseBarPatterns( - pBar, - pBarAnalysis, - structureConfig.barsAnalysisConfig // - ); - // // Do ... + // XFIMA Consolidation ... // - bool isConsolidation = poiDetector.IsConsolidationPattern( - pBar, + bool isConsolidation = fimaHelper.HasPVConsolidationZone( zone, - dir // + pBar.Index(), + true, // Force PV Break ... + true // Force Has Sar Switch ... ); // - // Validating Consolidation Zone ... - int lastPeakOverLast = -1; - int lastValeUnderLast = -1; + isBullish = + isConsolidation && + zone.IsBullish(); // - // Bullish Consolidation ... - bool isConsolidationBullish = + isBearish = isConsolidation && - IsXBullish(dir) && - fimaHelper.FindLastPeakOverLast( - lastPeakOverLast, - zone.ToIndex(), - zone.FromIndex() - zone.ToIndex() // - ) && - fimaHelper.IsSarBullish(pBar.Index()); - - // - // Bearish Consolidation ... - bool isConsolidationBearish = - isConsolidation && - IsXBearish(dir) && - fimaHelper.FindLastValeUnderLast( - lastValeUnderLast, - zone.ToIndex(), - zone.FromIndex() - zone.ToIndex() // - ) && - fimaHelper.IsSarBearish(pBar.Index()); + zone.IsBearish(); // // Validate based on Bars Patterns ... - - // - // 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) - // - ); - - // - isConsolidationBullish = - isConsolidationBullish && - isPBarHasBullishPatterns; - - // - isConsolidationBearish = - isConsolidationBearish && - isPBarHasBearishPatterns; - - // - // Validate Based on Same Peaks and Vales ... - - // - int samePVValidationLength = 3; - int samePeaks = fimaHelper.CountSamePeaks(pBar.Index(), (zone.FromIndex() - zone.ToIndex())); - int sameVales = fimaHelper.CountSameVales(pBar.Index(), (zone.FromIndex() - zone.ToIndex())); - - // - bool isPeakValid = samePeaks >= samePVValidationLength; - bool isValeValid = sameVales >= samePVValidationLength; - bool isPVValid = isPeakValid || - isValeValid; - - // - isConsolidationBullish = - isConsolidationBullish && - isPVValid; - - // - isConsolidationBearish = - isConsolidationBearish && - isPVValid; - - // - // Validation Consolidation ... - isConsolidation = - isConsolidationBullish || - isConsolidationBearish; - - // - if (isConsolidation) + 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; + if (result) + { + // + dir = zone.dir; zone.to = bar.time; XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; iConfig.zonesWidth = 3; @@ -988,48 +983,18 @@ bool Strategy4HasSignal( Print("Consolidation"); } - // - isBullish = - // - false - // - ; - - // - isBearish = - // - false - // - ; - - // - // 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 // - ); + // zone.Clean(); + // result = ToBox( + // p2Bar, + // zone, + // dir, + // X_BAR_PATTERN_PINNED // + // ); // // Manage Stops ... diff --git a/Experts/x-saherelm.xfima.backtester.ea.mq5 b/Experts/x-saherelm.xfima.backtester.ea.mq5 index 852fa40d..2ff8e182 100644 --- a/Experts/x-saherelm.xfima.backtester.ea.mq5 +++ b/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -362,7 +362,7 @@ int OnInit() eaSignallerRiskInPoint, // Default Risk In Points ... eaSignallerVolume // Defaul Volume ... ); - fima1Signaller.slAdditionDistance = 15; + fima1Signaller.slAdditionDistance = 30; fima1Signaller.AddOnSignalEventHandler(OnSignalTriggered); // diff --git a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 index 938fa5bb..36f7b047 100644 --- a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -3268,6 +3268,70 @@ bool AddIfNotExists( // return result; } + +template +int FillNotExists( + T &dest[], + T &source[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + int maxAllowed = 0 // +) +{ + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + maxAllowed = NormalizeInt(maxAllowed, 0); + + // + // Validate ... + bool has = HasChild(source); + if (!has) + { + return result; + } + + // + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + has = + source[i].IsValid() && + (!HasDirection(forDir) || forDir == source[i].dir); + if (!has) + { + continue; + } + + // + has = AddIfNotExists(source[i], dest); + if (has) + { + result++; + } + } + + // + // Handle Cleanup Collection + // if Max Reached ... + if (maxAllowed > 0) + { + // + CleanupArray( + dest, + maxAllowed // + ); + } + + // + return result; +} //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ @@ -4774,9 +4838,9 @@ bool ToResistanceBox( /** * Remove Breaked Zones from a Collection ... - * + * * @param source: XBoxZone, reference to Specified Collection ... - * + * * @return ( int ) */ int RemoveBreakedZones(XBoxZone &source[]) @@ -5465,7 +5529,6 @@ int ExtractBreakeds( return result; } - /** * Collect all Bars which Breakes Specified Zone ... * diff --git a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 index 2b268969..94e9dac7 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -396,19 +396,29 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // // Preparing Signal Targets ... XTarget iTarget; - double spread = GetSpread(iZone.symbol); - double entry = GetEntry(iZone.symbol, iZone.dir); - double risk = MathAbs(entry - (isBullish ? iZone.lower : iZone.upper)); + double spread = GetSpread(symbol); + double entry = GetEntry(symbol, iZone.dir); + double risk = MathAbs(entry - slPrice); + + // + // Ignore Signal if Risk is too Much ... + bool hasToomuchRisk = risk > (iZone.upper - iZone.lower) + slAddition + (100 * _point); + if (hasToomuchRisk) + { + // + iZone.Clean(); + Print("Too Much Risk ..."); + } // // Handle Partial Close Position if Reached TP 1.5 ... - iTarget.Clean(); - iTarget.doRF = false; - iTarget.actingDistance = 5; - iTarget.doRFOnEntry = false; - iTarget.volumeMultiplier = 0.5; - iTarget.target = isBullish ? entry + (4 * risk) : entry - (4 * risk); - AddRef(iTarget, iTargets); + // iTarget.Clean(); + // iTarget.doRF = false; + // iTarget.actingDistance = 5; + // iTarget.doRFOnEntry = false; + // iTarget.volumeMultiplier = 0.5; + // iTarget.target = isBullish ? entry + (4 * risk) : entry - (4 * risk); + // AddRef(iTarget, iTargets); // // Handle Ignore Signal Targets if Forced ... @@ -429,14 +439,15 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // // Prepare Founded Signal ... - has = PrepareSignal( - iSignal, - iDir, - iTargets, - 0, // Use Default R2R ... - slPrice, // Provided Price for SL ... - 0 // Specified Risk in Point .... - ); + has = iZone.IsValid() && + PrepareSignal( + iSignal, + iDir, + iTargets, + 0, // Use Default R2R ... + slPrice, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); if (has) { // @@ -492,51 +503,57 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // // Force Hedging ... - bool forceHedging = (positionsCount >= 2); - if (forceHedging) - { - // - // Minimum Required Reward ... - double minRequiredReward = 1.5; + // bool forceHedging = (positionsCount >= 2); + // if (forceHedging) + // { + // // + // // Minimum Required Reward ... + // double minRequiredReward = 1.5; - // - // Summarizing Risk and Reward of Collections ... - double risk = 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; - } + // // + // // 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; + // // } - // - // 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; + // // // + // // risk *= volume; + // // reward *= volume; - // - // Validate Guard ... - 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; + + // // // + // // // Validate Guard ... + // // has = iGuard.IsValid(); + // // if (has) + // // { + // // // + // // AddRef( + // // iGuard, + // // guards // + // // ); + // // } + // // } + // } // result = ArraySize(guards); @@ -579,27 +596,58 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller bool result = false; // - // result = Strategy2HasSignal( - // bar, - // zone, - // targets, - // dir // - // ); + // Signaller Flags ... + bool useSignaller1 = true; + bool useSignaller2 = true; + bool useSignaller3 = true; + bool useSignaller4 = false; // - // if (!result) - // { - // // - // result = Strategy3HasSignal( - // bar, - // zone, - // targets, - // dir // - // ); - // } + // Validator Flags ... + bool validateByOrderFlow = true; // - if (!result) + // Signaller 1 ... + if (!result && useSignaller1) + { + // + result = Strategy1HasSignal( + bar, + zone, + targets, + dir // + ); + } + + // + // Signaller 2 ... + if (!result && useSignaller2) + { + // + result = Strategy2HasSignal( + bar, + zone, + targets, + dir // + ); + } + + // + // Signaller 3 ... + if (!result && useSignaller3) + { + // + result = Strategy3HasSignal( + bar, + zone, + targets, + dir // + ); + } + + // + // Signaller 4 ... + if (!result && useSignaller4) { // result = Strategy4HasSignal( @@ -610,6 +658,40 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller ); } + // + // Validate Signals by Order Flow ... + if (validateByOrderFlow) + { + // + // Detecting OrderFlow ... + XBoxZone orderFlow[]; + ENUM_X_DIRECTION orderFlowDir; + bool hasOrderFlow = poiDetector.HasOrderFlow( + bar, + orderFlowDir, + orderFlow, + 2, + false, // Contains OB ... + true, // Contains FVG ... + false // Contains Support and Resistances ... + ); + + // + bool isBullish = hasOrderFlow && + IsXBullish(dir) && + IsXBullish(orderFlowDir); + + // + bool isBearish = hasOrderFlow && + IsXBearish(dir) && + IsXBearish(orderFlowDir); + + // + // Summarizing result ... + result = isBullish || + isBearish; + } + // // // if (result) // { @@ -630,7 +712,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller * * @return ( bool ) */ - bool Strategy2HasSignal( + bool Strategy1HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], @@ -922,7 +1004,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller * * @return ( bool ) */ - bool Strategy3HasSignal( + bool Strategy2HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], @@ -1238,7 +1320,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller * * @return ( bool ) */ - bool Strategy4HasSignal( + bool Strategy3HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], @@ -1310,57 +1392,102 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // // Validate based on Bars Patterns ... - - // - // 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) - // + bool validateByBarPatterns = true; + if (validateByBarPatterns) + { + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // ); - // - // 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) - // - ); + // + // 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; + } // - isBullish = - isBullish && - isPBarHasBullishPatterns && - !isPBarHasBearishPatterns; + // 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 = - isBearish && - isPBarHasBearishPatterns && - !isPBarHasBullishPatterns; + // + isBullish = + isBullish && + isPullbackBullish; + + // + isBearish = + isBearish && + isPullbackBearish; + + // + // Summarize Result ... + result = isBullish || + isBearish; + } // // Validate ... @@ -1424,6 +1551,173 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller 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 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; + } + + // + // 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; + } + + // + // Do ... + + // + // Detecting OrderFlow ... + XBoxZone orderFlow[]; + bool hasOrderFlow = poiDetector.HasOrderFlow( + pBar, + dir, + orderFlow, + 2, + false, // Contains OB ... + true, // Contains FVG ... + false // Contains Support and Resistances ... + ); + + // + isBullish = hasOrderFlow && + IsXBullish(dir); + + // + isBearish = hasOrderFlow && + IsXBearish(dir); + + // + result = isBullish || + isBearish; + if (result) + { + // + poiDrawer.DrawZones(orderFlow, structureDrawConfig.drawConfig); + Print("OrderFlow Detected ..."); + } + + // + isBullish = + // + false + // + ; + + // + isBearish = + // + false + // + ; + + // + // 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) + { + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + // };