From 2edb26cfc2b2f62919294c4ec4ff18a2b17a4f33 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Thu, 23 Oct 2025 13:05:34 +0330 Subject: [PATCH] last ... --- .../x-saherelm.x-backtester.expert.class.mq5 | 60 ++- Classes/x-saherelm.x-market.pattern.class.mq5 | 248 ++++++++++++ Documents/BKP/XFIMA Signals/signallers.mq5 | 272 +++++++++++++ Experts/x-saherelm.xfima.backtester.ea.mq5 | 35 ++ Helpers/x-saherelm.xfima.helper.mq5 | 370 ++++++++++++++++++ Libraries/x-saherelm.x-poi.lib.mq5 | 12 + .../x-saherelm.xfima.signaller.class.mq5 | 355 +++++++++++++---- 7 files changed, 1267 insertions(+), 85 deletions(-) diff --git a/Classes/x-saherelm.x-backtester.expert.class.mq5 b/Classes/x-saherelm.x-backtester.expert.class.mq5 index 2cd28622..1b80e005 100644 --- a/Classes/x-saherelm.x-backtester.expert.class.mq5 +++ b/Classes/x-saherelm.x-backtester.expert.class.mq5 @@ -94,6 +94,7 @@ class XCBackTesterEA : public XCBase // XCAlert *eaAlert; // EA Scope Alert Handler ... + XCGuard *eaGuard; // EA Scope Guard Handler ... XCTrade *eaTrader; // EA Scope Trade Handler ... XCTarget *eaTarget; // EA Scope Target Manager ... XCVolume *eaVolume; // EA Scope Volume Manager ... @@ -310,6 +311,13 @@ class XCBackTesterEA : public XCBase // Init Target Managers ... eaTarget = new XCTarget(eaTrader, eaAlert); + // + // Initialize Guard Handler ... + eaGuard = new XCGuard( + eaAlert, + eaTrader // + ); + // eaVolume = new XCVolume(); result = eaVolume.Init( @@ -369,6 +377,10 @@ class XCBackTesterEA : public XCBase delete eaTrader; ZeroMemory(eaTrader); + // + delete eaGuard; + ZeroMemory(eaGuard); + // SpecifiedClean(mOnModifyEventHandlers); SpecifiedClean(mStopLossEventHandlers); @@ -406,7 +418,10 @@ class XCBackTesterEA : public XCBase // // Manage Positions Drawings ... - eaPositionDrawer.Update(); + if (eaPositionDrawer != NULL) + { + eaPositionDrawer.Update(); + } } /** @@ -480,7 +495,10 @@ class XCBackTesterEA : public XCBase eaTarget.HandleOnStopLossTriggered(deal); // - eaPositionDrawer.HandleStopLossTriggered(deal); + if (eaPositionDrawer != NULL) + { + eaPositionDrawer.HandleStopLossTriggered(deal); + } } /** @@ -498,7 +516,10 @@ class XCBackTesterEA : public XCBase eaTarget.HandleOnTakeProfitTriggered(deal); // - eaPositionDrawer.HandleOnTakeProfitTriggered(deal); + if (eaPositionDrawer != NULL) + { + eaPositionDrawer.HandleOnTakeProfitTriggered(deal); + } } /** @@ -526,11 +547,15 @@ class XCBackTesterEA : public XCBase ); // - eaPositionDrawer.HandleOnPositionForceClosed( - ticket, - position, - comment // - ); + if (eaPositionDrawer != NULL) + { + // + eaPositionDrawer.HandleOnPositionForceClosed( + ticket, + position, + comment // + ); + } } /** @@ -598,11 +623,15 @@ class XCBackTesterEA : public XCBase ) { // - eaPositionDrawer.HandleOnPositionModified( - ticket, - profit, - comment // - ); + if (eaPositionDrawer != NULL) + { + // + eaPositionDrawer.HandleOnPositionModified( + ticket, + profit, + comment // + ); + } } /** @@ -665,7 +694,10 @@ class XCBackTesterEA : public XCBase eaTarget.AddExecutedSignal(signal); // - eaPositionDrawer.AddExecutedSignal(signal); + if (eaPositionDrawer != NULL) + { + eaPositionDrawer.AddExecutedSignal(signal); + } } // diff --git a/Classes/x-saherelm.x-market.pattern.class.mq5 b/Classes/x-saherelm.x-market.pattern.class.mq5 index 145cdb94..bd4c74cc 100644 --- a/Classes/x-saherelm.x-market.pattern.class.mq5 +++ b/Classes/x-saherelm.x-market.pattern.class.mq5 @@ -1650,6 +1650,254 @@ class XCMarketPatternDetector : public XCBase return result; } + bool IsConsolidationPattern( + XOHCL &bar, + XBoxZone &zone, + ENUM_X_DIRECTION &dir, + int validationLength = 5, + ENUM_X_PRICE breakPriceType = X_PRICE_CLOSE, + ENUM_X_PRICE upperPriceType = X_PRICE_HIGH, + ENUM_X_PRICE lowerPriceType = X_PRICE_LOW // + ) + { + // + // Descriptions: + // =============== + // Consolidation Zones Happens by Highest High and Lowest Low + // of Specified Range which Breakes From one Side ... + // + + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + CleanDirection(dir); + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 3); + + // + // Validate ... + result = bar.IsValid() && + IsXValid(lowerPriceType) && + IsXValid(upperPriceType) && + IsXValid(breakPriceType); + if (!result) + { + return result; + } + + // + // Define Requirements ... + XOHCL iBar; + bool has = false; + datetime to = NULL; + datetime from = NULL; + double iLow = EMPTY_VALUE; + bool hasLowShadow = false; + double lower = EMPTY_VALUE; + double upper = EMPTY_VALUE; + double iHigh = EMPTY_VALUE; + bool hasHighShadow = false; + double iPrice = EMPTY_VALUE; + bool isLowerBreaked = false; + bool isUpperBreaked = false; + + // + // Loop Through Bars ... + int barIndex = bar.Index(); + int idx = barIndex; + bool canLookup = IsValidIndex(idx); + while (canLookup) + { + // + // Initialize Indexed Bar ... + idx++; + iBar.Clean(); + result = bar.BarAt(idx, iBar); + if (!result) + { + break; + } + + // + // Update Time ... + if (idx == barIndex + 1) + { + to = iBar.time; + } + + // + // Extract Low and High Price ... + iLow = iBar.GetPrice(lowerPriceType); + iHigh = iBar.GetPrice(upperPriceType); + result = NotEmptyZero(iLow) && + NotEmptyZero(iHigh); + if (!result) + { + break; + } + + // + // Check Bar Has Low/High Shadow ... + hasLowShadow = iBar.GetLowShadow() > iBar.GetHighShadow(); + hasHighShadow = iBar.GetHighShadow() > iBar.GetLowShadow(); + + // + // Update Range Lower and Upper based on Shadows ... + + // + // Lower ... + if (hasLowShadow) + { + // + // Check Can Update ... + has = + !NotEmptyZero(lower) + ? true + : iLow < lower; + if (has) + { + lower = iLow; + } + } + + // + // Upper ... + if (hasHighShadow) + { + // + // Check Can Update ... + has = + !NotEmptyZero(upper) + ? true + : iHigh > upper; + if (has) + { + upper = iHigh; + } + } + + // + // Check Price Breakes ... + iPrice = iBar.GetPrice(breakPriceType); + result = NotEmptyZero(iPrice); + if (!result) + { + break; + } + + // + // Check Upper/Lower breakes ... + isLowerBreaked = iPrice < lower; + isUpperBreaked = iPrice > upper; + + // + canLookup = (!isLowerBreaked && !isUpperBreaked); + if (!canLookup) + { + break; + } + + // + from = iBar.time; + } + + // + // Validate Calculations ... + result = + // + IsXValid(to) && + IsXValid(from) && + from < to && + // + NotEmptyZero(lower) && + NotEmptyZero(upper) && + upper > lower + // + ; + + // + // Validate To Edge Breakes ... + if (result) + { + // + iPrice = bar.GetPrice(breakPriceType); + result = NotEmptyZero(iPrice); + + // + // Validate To Edge Breakes ... + if (result) + { + // + isUpperBreaked = iPrice > upper; + isLowerBreaked = iPrice < lower; + + // + // Validate To Break ... + result = isUpperBreaked || isLowerBreaked; + } + + // + // Prepare Direction ... + if (result) + { + // + dir = + isUpperBreaked + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Validate Direction ... + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.to = to; + zone.dir = dir; + zone.from = from; + zone.at = bar.time; + zone.upper = upper; + zone.lower = lower; + zone.symbol = bar.symbol; + zone.period = bar.period; + zone.type = ToXString(X_BAR_PATTERN_CONSOLIDATION); + + // + // Validate Zone ... + result = zone.IsValid(); + + // + // Validate Zone Length ... + if (result) + { + result = zone.FromIndex() - zone.ToIndex() >= validationLength; + } + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + CleanDirection(dir); + } + iBar.Clean(); + + // + return result; + } + // // FVG ... diff --git a/Documents/BKP/XFIMA Signals/signallers.mq5 b/Documents/BKP/XFIMA Signals/signallers.mq5 index 5578c043..d1cff402 100644 --- a/Documents/BKP/XFIMA Signals/signallers.mq5 +++ b/Documents/BKP/XFIMA Signals/signallers.mq5 @@ -790,3 +790,275 @@ bool Strategy2HasSignal( // return result; } + +// ======================================= +// Signaller 4: +// CONSOLIDATION Zones ... +// ======================================= + +/** + * 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; + } + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarAnalysis; + poiDetector.AnalyseBarPatterns( + pBar, + pBarAnalysis, + structureConfig.barsAnalysisConfig // + ); + + // + // Do ... + + // + bool isConsolidation = poiDetector.IsConsolidationPattern( + pBar, + zone, + dir // + ); + + // + // Validating Consolidation Zone ... + int lastPeakOverLast = -1; + int lastValeUnderLast = -1; + + // + // Bullish Consolidation ... + bool isConsolidationBullish = + 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()); + + // + // 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) + { + // + zone.to = bar.time; + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + iConfig.zonesWidth = 3; + iConfig.bullishColor = clrYellow; + iConfig.bearishColor = clrDarkOrange; + poiDrawer.DrawZone(zone, iConfig); + 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 // + ); + + // + // 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; +} diff --git a/Experts/x-saherelm.xfima.backtester.ea.mq5 b/Experts/x-saherelm.xfima.backtester.ea.mq5 index 43155ead..852fa40d 100644 --- a/Experts/x-saherelm.xfima.backtester.ea.mq5 +++ b/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -452,6 +452,12 @@ int OnInit() // detectorConfig.FullDetect(); // marketStructureDrawerConfig.FullDraw(); + // + // Ignoring Position Drawer ... + delete eaExpert.eaPositionDrawer; + ZeroMemory(eaExpert.eaPositionDrawer); + eaExpert.eaPositionDrawer = NULL; + // Print(ShortName, ": Initialized Successfully ..."); return INIT_SUCCEEDED; @@ -518,6 +524,35 @@ void OnTick() // // Signallers Calling OnTick ... fima1Signaller.OnTick(barIndex); + + // + // Checking For Guard only When has Position ... + XPosition positions[]; + int positionsCount = eaExpert.eaTrader.GetPositions( + positions, + fima1Signaller.symbol, + fima1Signaller.name, + fima1Signaller.period, + NULL, // All Types ... + true, // Filter By Magic ... + true // Force Clean ... + ); + if (IsValidSize(positionsCount)) + { + // + XGuard guards[]; + int guardsCount = fima1Signaller.CheckForGuard( + guards, + positions, + barIndex // + ); + if (IsValidSize(guardsCount)) + { + // + // Handling Guards ... + eaExpert.eaGuard.DoGuards(guards); + } + } } // diff --git a/Helpers/x-saherelm.xfima.helper.mq5 b/Helpers/x-saherelm.xfima.helper.mq5 index 26471f91..bb31cbe5 100644 --- a/Helpers/x-saherelm.xfima.helper.mq5 +++ b/Helpers/x-saherelm.xfima.helper.mq5 @@ -2656,9 +2656,115 @@ class XCXFIMAHelper : public XCBaseHelper return result; } + bool IsSarSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + int pBarIndex = barIndex + 1; + + // + bool isBullish = IsSarBullish(barIndex); + bool isPBullish = IsSarBullish(pBarIndex); + + // + result = isBullish && + !isPBullish; + + // + return result; + } + + bool IsSarSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + int pBarIndex = barIndex + 1; + + // + bool isBearish = IsSarBearish(barIndex); + bool isPBearish = IsSarBearish(pBarIndex); + + // + result = isBearish && + !isPBearish; + + // + return result; + } + // // PV ... + bool IsPeakSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double iC = GetPeak(barIndex); + double iP = GetPeak(barIndex + 1); + + // + result = iC == iP && + NotEmptyZero(iC); + + // + return result; + } + + bool IsValeSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double iC = GetVale(barIndex); + double iP = GetVale(barIndex + 1); + + // + result = iC == iP && + NotEmptyZero(iC); + + // + return result; + } + /** * Check Peak Happens over Last ... * @@ -3153,6 +3259,270 @@ class XCXFIMAHelper : public XCBaseHelper return result; } + bool HasPVConsolidationZone( + XBoxZone &zone, + int barIndex = 0, + bool forcePVBreak = false, + bool forceHasSarSwitch = false // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + bool isPeakSame = IsPeakSame(barIndex); + bool isValeSame = IsValeSame(barIndex); + result = !(isPeakSame && + isValeSame); + if (!result) + { + return result; + } + + // + double iPeak = EMPTY_VALUE; + double iVale = EMPTY_VALUE; + + // + int idx = barIndex; + bool canLookup = true; + while (canLookup) + { + // + idx++; + isPeakSame = IsPeakSame(idx); + isValeSame = IsValeSame(idx); + result = isPeakSame && + isValeSame; + if (!result) + { + // + zone.from = GetBarTime(mSymbol, mPeriod, idx); + break; + } + + // + if (idx == barIndex + 1) + { + // + zone.to = GetBarTime( + mSymbol, + mPeriod, + idx // + ); + } + + // + zone.from = GetBarTime( + mSymbol, + mPeriod, + idx // + ); + + // + iPeak = GetPeak(idx); + iVale = GetVale(idx); + + // + zone.lower = + !NotEmptyZero(zone.lower) + ? iVale + : MathMin(zone.lower, iVale); + + // + zone.upper = + !NotEmptyZero(zone.upper) + ? iPeak + : MathMax(zone.upper, iPeak); + } + + // + // Validating Zone Params ... + result = + // + IsXValid(zone.to) && + IsXValid(zone.from) && + zone.from < zone.to && + // + NotEmptyZero(zone.lower) && + NotEmptyZero(zone.upper) && + zone.upper > zone.lower + // + ; + + // + // Prepare Zone ... + if (result) + { + // + iPeak = GetPeak(barIndex); + iVale = GetVale(barIndex); + bool isPeakOverLast = IsPeakOverLast(barIndex); + bool isValeUnderLast = IsValeUnderLast(barIndex); + bool isValeBreak = iVale < zone.lower; + bool isPeakBreak = iPeak > zone.upper; + bool isPVBreak = isPeakBreak || + isValeBreak; + + // + zone.at = GetBarTime(mSymbol, mPeriod, barIndex); + zone.symbol = mSymbol; + zone.period = mPeriod; + zone.dir = (isPeakOverLast && !isValeUnderLast && isPVBreak) + ? X_DIRECTION_BULLISH + : (isValeUnderLast && !isPeakOverLast && isPVBreak) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + zone.type = ToXString(X_BAR_PATTERN_CONSOLIDATION); + + // + // Refine Zone Upper and Lower ... + if (zone.IsValid()) + { + // + XOHCL iBar; + int zoneLoopback = zone.FromIndex() - zone.ToIndex(); + result = zone.ToBar(iBar) && + IsValidSize(zoneLoopback); + if (result) + { + // + double zoneLL = iBar.FindLowest(zoneLoopback, MODE_LOW); + double zoneHH = iBar.FindHighest(zoneLoopback, MODE_HIGH); + result = NotEmptyZero(zoneLL) && + NotEmptyZero(zoneHH); + if (result) + { + // + zone.lower = zone.lower == zoneLL + ? zone.lower + : MathMax(zone.lower, zoneLL); + + // + zone.upper = zone.upper == zoneHH + ? zone.upper + : MathMin(zone.upper, zoneHH); + } + } + + // + iBar.Clean(); + } + + // + // Validate ... + result = zone.IsValid(); + } + + // + // Validate Zones From ... + if (result) + { + // + int idx = zone.FromIndex(); + + // + iPeak = GetPeak(idx); + iVale = GetVale(idx); + + // + bool isValeOverLast = IsValeOverLast(idx); + bool isPeakUnderLast = IsPeakUnderLast(idx); + + // + result = + result && + (zone.IsBullish() + ? !isPeakUnderLast + : zone.IsBearish() + ? !isValeOverLast + : false); + } + + // + // Apply Forces ... + + // + // PV Break ... + // Peak or Vale must Breaked at Bar ... + if (result && forcePVBreak) + { + // + bool isPVBreaked = + (zone.IsBullish() && IsPeakOverLast(barIndex)) || + (zone.IsBearish() && IsValeUnderLast(barIndex)); + + // + result = result && + isPVBreaked; + } + + // + // Other Loop based Forces ... + if (result && (forceHasSarSwitch)) + { + + // + bool hasSarSwitch = false; + + // + int start = zone.ToIndex(); + int end = zone.FromIndex(); + for (int i = start; i <= end; i++) + { + // + // Check Sar Switches ... + if (forceHasSarSwitch && !hasSarSwitch) + { + // + hasSarSwitch = + zone.IsBullish() + ? IsSarSwitchedToBullish(i) + : IsSarSwitchedToBearish(i); + } + } + + // + // Validate Forces ... + if (forceHasSarSwitch) + { + // + result = + result && + hasSarSwitch; + } + } + + // + // Cleanup ... + if (!result) + { + zone.Clean(); + } + + // + return result; + } + // // HK ... diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index ce243745..4cf71b61 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -50,6 +50,7 @@ enum ENUM_X_BAR_PATTERN X_BAR_PATTERN_SUPPORT = 14, X_BAR_PATTERN_RESISTANCE = 15, X_BAR_PATTERN_PULLBACK = 16, + X_BAR_PATTERN_CONSOLIDATION = 17, }; /** @@ -163,6 +164,11 @@ string ToXString(ENUM_X_BAR_PATTERN value) case X_BAR_PATTERN_PULLBACK: result = "XPULLBACK"; break; + + // + case X_BAR_PATTERN_CONSOLIDATION: + result = "XCONSOLIDATION"; + break; } // @@ -257,6 +263,10 @@ ENUM_X_BAR_PATTERN ToBarPattern(string value) { result = X_BAR_PATTERN_PULLBACK; } + else if (value == ToXString(X_BAR_PATTERN_CONSOLIDATION)) + { + result = X_BAR_PATTERN_CONSOLIDATION; + } // return result; @@ -290,6 +300,8 @@ int GetAllBarPatters(ENUM_X_BAR_PATTERN &dest[]) Add(X_BAR_PATTERN_FVG, dest); Add(X_BAR_PATTERN_SUPPORT, dest); Add(X_BAR_PATTERN_RESISTANCE, dest); + Add(X_BAR_PATTERN_PULLBACK, dest); + Add(X_BAR_PATTERN_CONSOLIDATION, dest); // return ArraySize(dest); diff --git a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 index bd9d7052..2b268969 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -402,20 +402,12 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // // Handle Partial Close Position if Reached TP 1.5 ... - // iTarget.Clean(); - // iTarget.doRF = true; - // iTarget.actingDistance = 10; - // iTarget.volumeMultiplier = 0.5; - // iTarget.target = isBullish ? entry + (1.8 * risk) : entry - (1.8 * risk); - // // iTarget.tpValue = isBullish ? entry + (2.5 * risk) : entry - (2.5 * risk); - // AddRef(iTarget, iTargets); - - // - // Reward 3 Target ... iTarget.Clean(); - iTarget.doRF = true; - iTarget.actingDistance = 0; - iTarget.target = isBullish ? entry + (3 * risk) : entry - (3 * risk); + 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); // @@ -432,58 +424,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // // Here we Can Do Target Preparing if Signaller Restricted and // then ignore restrictions if required ... - - // // - // // Risk Free On Entry: - // iTarget.Clean(); - // iTarget.doRF = true; - // iTarget.actingDistance = 10 * _point; // (5 * spread) / _point; - // iTarget.target = isBullish ? entry + risk : entry - risk; // isBullish ? entry + (2 * spread) : entry - (2 * spread); - // AddRef(iTarget, iTargets); - - // // - // // Partial Close Position Half on TP 1 ... - // // Increase Rewards to TP 3 ... - // iTarget.Clean(); - // iTarget.actingDistance = 1; - // iTarget.volumeMultiplier = 0.5; - // iTarget.target = isBullish ? entry + risk : entry - risk; - // iTarget.tpValue = isBullish ? entry + (2.5 * risk) : entry - (2.5 * risk); - // AddRef(iTarget, iTargets); - - // // - // // Reset Restrictions ... - // if (loosingTrades == 1) - // { - // ResetRestrictions(); - // } - - // - if (loosingTrades > 2) - { - // - if (IsXValid(restUntil) && iBar.time > restUntil) - { - // - WinTrade(); - restUntil = NULL; - } - else - { - // - XOHCL rBar; - bool has = rBar.Init(iZone.symbol, PERIOD_W1, 0); - if (has) - { - // - restUntil = rBar.NextAt(); // + PeriodSeconds(PERIOD_D1); - Print("Rest Until: ", restUntil); - } - - // - rBar.Clean(); - } - } + ResetRestrictions(); } // @@ -537,9 +478,73 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // SpecifiedClean(guards); + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Requirements ... + XGuard iGuard; + bool has = false; + + // + // Force Hedging ... + 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; + } + + // + // 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); + // + // Cleanup ... + iGuard.Clean(); + // return result; } @@ -581,11 +586,23 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // dir // // ); + // + // if (!result) + // { + // // + // result = Strategy3HasSignal( + // bar, + // zone, + // targets, + // dir // + // ); + // } + // if (!result) { // - result = Strategy3HasSignal( + result = Strategy4HasSignal( bar, zone, targets, @@ -593,11 +610,11 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller ); } - // - if (result) - { - // Print("Salam"); - } + // // + // if (result) + // { + // Print("Salam"); + // } // return result; @@ -1211,6 +1228,202 @@ 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 ... + // XFIMA Consolidation ... + + // + bool isConsolidation = fimaHelper.HasPVConsolidationZone( + zone, + pBar.Index(), + true, // Force PV Break ... + true // Force Has Sar Switch ... + ); + + // + isBullish = + isConsolidation && + zone.IsBullish(); + + // + isBearish = + isConsolidation && + zone.IsBearish(); + + // + // 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) + // + ); + + // + // 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; + + // + // Validate ... + result = isBullish || + isBearish; + if (result) + { + // + dir = zone.dir; + zone.to = bar.time; + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + iConfig.zonesWidth = 3; + iConfig.bullishColor = clrYellow; + iConfig.bearishColor = clrDarkOrange; + poiDrawer.DrawZone(zone, iConfig); + Print("Consolidation"); + } + + // + // 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; + } + // };