From 4ed75abc2becdb97428d95c03acbc1ad3941ccd0 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Wed, 14 May 2025 04:15:20 +0330 Subject: [PATCH] complete signaller trigger cond 1 and 2 and apply sorting for Tagets and etc ... --- Classes/x-saherelm.x-bar.analyser.class.mq5 | 76 ++++ Experts/x-saherelm.xcaea.ea.mq5 | 5 +- Libraries/x-saherelm.x-trade.lib.mq5 | 171 +++++++++ XCAEA/Classes/xcaea.x-poi.detector.class.mq5 | 3 + XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 | 14 + XCAEA/Helpers/xcaea.helper.mq5 | 103 +++++- XCAEA/Libraries/xcaea.signaller.lib.mq5 | 347 ++++++++++++++----- XCAEA/Signals/xcaea.signaller.class.mq5 | 37 +- 8 files changed, 670 insertions(+), 86 deletions(-) diff --git a/Classes/x-saherelm.x-bar.analyser.class.mq5 b/Classes/x-saherelm.x-bar.analyser.class.mq5 index 9a7be539..d23284ab 100644 --- a/Classes/x-saherelm.x-bar.analyser.class.mq5 +++ b/Classes/x-saherelm.x-bar.analyser.class.mq5 @@ -2223,6 +2223,82 @@ class XCBarAnalyser : public XCBase return result; } + /** + * Check Specified Bar's Prev Bar is Simple Swing or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to it's Prev Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * + * @return ( bool ) + */ + bool IsSwimpleSwing( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + // Valdate Args ... + result = bar.IsValid(); + + // + // Reading Requirements ... + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + result = + bar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Now we Have to Check pBar is Swing Low or High ... + + // + bool isPBarSwingLow = + pBar.low < cBar.low && + pBar.low < p2Bar.low; + + // + bool isPBarSwingHigh = + pBar.high > cBar.high && + pBar.high > p2Bar.high; + + // + result = isPBarSwingLow || + isPBarSwingHigh; + + // + // Cleanup Resourses ... + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + /** * Check Specified Bar is Hammer Pattern or not ... * diff --git a/Experts/x-saherelm.xcaea.ea.mq5 b/Experts/x-saherelm.xcaea.ea.mq5 index d6ff5003..6118f672 100644 --- a/Experts/x-saherelm.xcaea.ea.mq5 +++ b/Experts/x-saherelm.xcaea.ea.mq5 @@ -397,9 +397,10 @@ void OnTick() // // Handling Targets ... - Copy( + ApplyTargetsOnSignal( + eaConditions.dir, eaConditions.targets, - eaSignal.targets // + eaSignal // ); // diff --git a/Libraries/x-saherelm.x-trade.lib.mq5 b/Libraries/x-saherelm.x-trade.lib.mq5 index baced782..2256bd08 100644 --- a/Libraries/x-saherelm.x-trade.lib.mq5 +++ b/Libraries/x-saherelm.x-trade.lib.mq5 @@ -531,6 +531,145 @@ struct XTarget } }; +// +// Get Lowest Target index ... +int GetLowest(XTarget &targets[]) +{ + // + int result = -1; + + // + if (!HasChild(targets)) + { + return result; + } + + // + XTarget iTarget; + int count = ArraySize(targets); + for (int i = 0; i < count; i++) + { + // + bool canSet = + !iTarget.IsValid() + ? true + : iTarget.target > targets[i].target; + if (canSet) + { + // + result = i; + iTarget = targets[i]; + } + } + + // + iTarget.Clean(); + + // + return result; +} + +// +// Get Highest Target index ... +int GetHighest(XTarget &targets[]) +{ + // + int result = -1; + + // + if (!HasChild(targets)) + { + return result; + } + + // + XTarget iTarget; + int count = ArraySize(targets); + for (int i = 0; i < count; i++) + { + // + bool canSet = + !iTarget.IsValid() + ? true + : iTarget.target < targets[i].target; + if (canSet) + { + // + result = i; + iTarget = targets[i]; + } + } + + // + iTarget.Clean(); + + // + return result; +} + +// +// Apply Sorting on Targets ... +void ApplySortOnTargets( + ENUM_X_DIRECTION forDir, // Target Sorting Direction ... + XTarget &targets[] // Targets to Apply Sorting ... +) +{ + // + bool has = HasChild(targets) && + HasDirection(forDir); + if (!has) + { + return; + } + + // + bool isBullish = IsBullish(forDir); + bool isBearish = IsBearish(forDir); + + // + XTarget tmp[]; + Copy( + targets, + tmp // + ); + Clean(targets); + while (HasChild(tmp)) + { + // + int idx = -1; + if (isBullish) + { + idx = GetLowest(tmp); + } + else if (isBearish) + { + idx = GetHighest(tmp); + } + + // + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XTarget iTarget = tmp[idx]; + ArrayRemove( + tmp, + idx, + 1 // + ); + AddRef( + iTarget, + targets // + ); + } + + // + Clean(tmp); +} + // // Model an Open Position ... struct XPosition @@ -5740,4 +5879,36 @@ int ExtractSymbolPositions( return result; } +// +// Apply a Collection of Targets +// on Specified Signal ... +void ApplyTargetsOnSignal( + ENUM_X_DIRECTION sortingDir, // Target Sorting Direction ... + XTarget &targets[], // Required Targets ... + XSignal &signal // Destination Signal ... +) +{ + // + bool has = + HasChild(targets) && + HasDirection(sortingDir); + if (!has) + { + return; + } + + // + // Sort Targets ... + ApplySortOnTargets( + sortingDir, + targets // + ); + + // + Copy( + targets, + signal.targets // + ); +} + // \ No newline at end of file diff --git a/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 b/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 index 1390559b..9ea1cb5f 100644 --- a/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 +++ b/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 @@ -1526,6 +1526,9 @@ class XCXCAEAPOIDetector : public XCBase // Clean(tmp); + // + result = ArraySize(pivots); + // return result; } diff --git a/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 b/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 index 380186f1..6058e36d 100644 --- a/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 +++ b/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 @@ -243,6 +243,20 @@ class XCXCAEAPOIDrawer : public XCBase DrawTrendBearishPivots(to); } + // + void DrawPivot( + XBoxZone &pivot, + datetime to = NULL // + ) { + // + DrawBox( + pivot, + to, + false, + false // + ); + } + // void DrawBox( XBoxZone &box, diff --git a/XCAEA/Helpers/xcaea.helper.mq5 b/XCAEA/Helpers/xcaea.helper.mq5 index b5e53b30..b5e155c9 100644 --- a/XCAEA/Helpers/xcaea.helper.mq5 +++ b/XCAEA/Helpers/xcaea.helper.mq5 @@ -185,6 +185,10 @@ struct XCAEAConditions double volumeBullish; double volumeBearish; double priceChangeRate; + bool bullishEngulfedBars[]; + bool bearishEngulfedBars[]; + bool bullishRejectedBars[]; + bool bearishRejectedBars[]; // // X3MA ... @@ -835,10 +839,18 @@ struct XCAEAConditions volumeBearish = 0; Clean(velocities); priceChangeRate = 0; + Clean(bullishEngulfedBars); + Clean(bearishEngulfedBars); + Clean(bullishRejectedBars); + Clean(bearishRejectedBars); ArraySetAsSeries(bars, true); ArraySetAsSeries(bodies, true); ArraySetAsSeries(ranges, true); ArraySetAsSeries(velocities, true); + ArraySetAsSeries(bullishEngulfedBars, true); + ArraySetAsSeries(bearishEngulfedBars, true); + ArraySetAsSeries(bullishRejectedBars, true); + ArraySetAsSeries(bearishRejectedBars, true); // // X3MA ... @@ -3357,6 +3369,95 @@ class XCXCAEAHelper : XCBase return result; } + // + // Reading Bars Conditions ... + XOHCL iBar; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + for (int i = 0; i < ArraySize(conditions.bars); i++) + { + // + iBar = conditions.bars[i]; + + // + // Reading Bars Patterns ... + + // + // Rejection ... + bool isRejected = + barAnalyser + .IsRejected( + iBar, + iDir, + false, + true // + ); + bool isBullishRejected = + isRejected && + IsBullish(iDir); + bool isBearishRejected = + isRejected && + IsBearish(iDir); + + // + Add( + isBullishRejected, + conditions.bullishRejectedBars // + ); + + // + Add( + isBearishRejected, + conditions.bearishRejectedBars // + ); + + // + // Engulfing ... + bool isEngulfed = + barAnalyser + .IsEngulfed( + iBar, + iDir // + ); + bool isBullishEngulfed = + isEngulfed && + IsBullish(iDir); + bool isBearishEngulfed = + isEngulfed && + IsBearish(iDir); + + // + Add( + isBullishEngulfed, + conditions.bullishEngulfedBars // + ); + + // + Add( + isBearishEngulfed, + conditions.bearishEngulfedBars // + ); + + // + // Momentum ... + bool isMomentum = + barAnalyser + .IsMomentum( + iBar, + iDir, + 1 // + ); + bool isBullishMomentum = + isMomentum && + IsBullish(iDir); + bool isBearishMomentum = + isMomentum && + IsBearish(iDir); + + // + iBar.Clean(); + } + iBar.Clean(); + // int zIndex = barIndex; int cIndex = zIndex + 1; @@ -3391,7 +3492,7 @@ class XCXCAEAHelper : XCBase fromBar.Init( zBar.symbol, zBar.period, - zIndex + loopback); + zIndex + loopback - 1); // // Conditions Retriever ... diff --git a/XCAEA/Libraries/xcaea.signaller.lib.mq5 b/XCAEA/Libraries/xcaea.signaller.lib.mq5 index 0508ca7d..58480f6b 100644 --- a/XCAEA/Libraries/xcaea.signaller.lib.mq5 +++ b/XCAEA/Libraries/xcaea.signaller.lib.mq5 @@ -1609,11 +1609,227 @@ bool CanTriggerCond1( // Define Requirements ... // + bool has = false; string symbol = helper.GetSymbol(); bool isBullish = decisionZone.IsBullish(); bool isBearish = decisionZone.IsBearish(); ENUM_TIMEFRAMES period = helper.GetPeriod(); + // + int toIDX = decisionZone.ToIndex(); + int fromIDX = decisionZone.FromIndex(); + + // + // Reading Bars ... + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + result = zBar.Init( + symbol, + period, + barIndex // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Reading Bar's Conditions ... + XCAEAConditions iConditions; + result = helper.GetConditions( + iConditions, + barIndex, + loopback // + ); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + iConditions.Clean(); + + // + return result; + } + + // + // Reading Conditions Values ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + + // + // PEAK ... + double zPeak = iConditions.peakBuffer[zIDX]; + double cPeak = iConditions.peakBuffer[cIDX]; + double pPeak = iConditions.peakBuffer[pIDX]; + double p2Peak = iConditions.peakBuffer[p2IDX]; + double p3Peak = iConditions.peakBuffer[p3IDX]; + + // + // VALE ... + double zVale = iConditions.valeBuffer[zIDX]; + double cVale = iConditions.valeBuffer[cIDX]; + double pVale = iConditions.valeBuffer[pIDX]; + double p2Vale = iConditions.valeBuffer[p2IDX]; + double p3Vale = iConditions.valeBuffer[p3IDX]; + + // + // SWH ... + double zSWH = iConditions.swingHighBuffer[zIDX]; + double cSWH = iConditions.swingHighBuffer[cIDX]; + double pSWH = iConditions.swingHighBuffer[pIDX]; + double p2SWH = iConditions.swingHighBuffer[p2IDX]; + double p3SWH = iConditions.swingHighBuffer[p3IDX]; + + // + // SWL ... + double zSWL = iConditions.swingLowBuffer[zIDX]; + double cSWL = iConditions.swingLowBuffer[cIDX]; + double pSWL = iConditions.swingLowBuffer[pIDX]; + double p2SWL = iConditions.swingLowBuffer[p2IDX]; + double p3SWL = iConditions.swingLowBuffer[p3IDX]; + + // + // Required Conditions ... + + // + bool isPeakBraked = + zPeak == cPeak && + cPeak == pPeak && + (pPeak > p2Peak || + pPeak > p3Peak); + + // + bool isValeBraked = + zVale == cVale && + cVale == pVale && + (pVale < p2Vale || + pVale < p3Vale); + + // + bool isSWHBraked = + zSWH == cSWH && + cSWH == pSWH && + (pSWH > p2SWH || + pSWH > p3SWH); + + // + bool isSWLBraked = + zSWL == cSWL && + cSWL == pSWL && + (pSWL < p2SWL || + pSWL < p3SWL); + + // + // Select Activated Pivot ... + XBoxZone selectedPivot; + bool hasPivots = HasChild(decisionPivots); + int pivotsCount = ArraySize(decisionPivots); + if (hasPivots) + { + // + for (int i = 0; i < pivotsCount; i++) + { + // + // Detect Type of Pivot ... + ENUM_XCA_PIVOTS iType = GetPivotType(decisionPivots[i]); + + // + // Check Rejection of Block ... + + // + bool isBullishBraked = + isBullish && + (isSWLBraked && + isValeBraked) && + iType == XCA_OB_BULL && + decisionPivots[i].IsBullish() && + zVale < decisionPivots[i].upper && + zVale > decisionPivots[i].lower; + + // + bool isBearishBraked = + isBearish && + (isSWHBraked && + isPeakBraked) && + iType == XCA_OB_BEAR && + decisionPivots[i].IsBearish() && + zPeak < decisionPivots[i].upper && + zPeak > decisionPivots[i].lower; + + // + has = isBullishBraked || + isBearishBraked; + if (has) + { + // + selectedPivot = decisionPivots[i]; + break; + } + } + } + bool hasSelectedPivot = selectedPivot.IsValid(); + + // + // Draw Selected Pivot ... + if (allowDraws && + hasSelectedPivot) + { + // + // Draw Pivot ... + XCBoxObject *iObj; + + // + has = helper.poiDrawer.DrawBox( + selectedPivot, + iObj // + ); + if (has) + { + // + color iColor = + isBullish + ? clrAqua + : clrMagenta; + + // + iObj.BoxWidth(2); + iObj.BoxColor(iColor); + iObj.BoxStyle(STYLE_SOLID); + + // + drawns.Add(iObj); + } + + // + ZeroMemory(iObj); + } + // // Parse Conditions ... @@ -1622,11 +1838,15 @@ bool CanTriggerCond1( // bool canTriggerLong = - false; + isBullish && + hasSelectedPivot && + selectedPivot.IsBullish(); // bool canTriggerShort = - false; + isBearish && + hasSelectedPivot && + selectedPivot.IsBearish(); // result = canTriggerLong || @@ -1641,15 +1861,51 @@ bool CanTriggerCond1( // // Trigger Stop Loss ... - sl = 0; + sl = isBullish + ? selectedPivot.lower + : selectedPivot.upper; // // Trigger Targets ... + XTarget iTarget; + if (canTriggerLong && + zBar.close < decisionZone.upper) + { + // + iTarget.doRF = true; + iTarget.target = decisionZone.upper; + } + if (canTriggerShort && + zBar.close > decisionZone.lower) + { + // + iTarget.doRF = true; + iTarget.target = decisionZone.lower; + } + + // + if (iTarget.IsValid()) + { + // + AddRef( + iTarget, + targets // + ); + } + iTarget.Clean(); } // // Cleanup Resources ... + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + iConditions.Clean(); + selectedPivot.Clean(); + // return result; } @@ -1692,6 +1948,7 @@ bool CanTriggerCond2( // Define Requirements ... // + bool has = false; string symbol = helper.GetSymbol(); bool isBullish = decisionZone.IsBullish(); bool isBearish = decisionZone.IsBearish(); @@ -1726,28 +1983,31 @@ bool CanTriggerCond2( } // - bool has = false; + // Select Activated Pivot ... XBoxZone selectedPivot; bool hasPivots = HasChild(decisionPivots); int pivotsCount = ArraySize(decisionPivots); - - // - // Select Activated Pivot ... if (hasPivots) { // for (int i = 0; i < pivotsCount; i++) { + // + // Detect Type of Pivot ... + ENUM_XCA_PIVOTS iType = GetPivotType(decisionPivots[i]); + // // Check Rejection of Block ... has = isBullish ? cBar.IsBullish() && + iType == XCA_OB_BULL && decisionPivots[i].IsBullish() && cBar.low < decisionPivots[i].upper && cBar.low > decisionPivots[i].lower && cBar.close > decisionPivots[i].upper : cBar.IsBearish() && + iType == XCA_OB_BEAR && decisionPivots[i].IsBearish() && cBar.high > decisionPivots[i].lower && cBar.high < decisionPivots[i].upper && @@ -1756,82 +2016,10 @@ bool CanTriggerCond2( { selectedPivot = decisionPivots[i]; } - - // // - // // Draw Pivot ... - // XCBoxObject *iObj; - - // // - // has = helper.poiDrawer.DrawBox( - // decisionPivots[i], - // iObj // - // ); - // if (has) - // { - // drawns.Add(iObj); - // } - - // // - // ZeroMemory(iObj); } } - - // - // Check Selected Pivot is Exists or not ... bool hasSelectedPivot = selectedPivot.IsValid(); - // - // Detect Liquidity For Selected Pivot ... - double ssl = 0; - double bsl = 0; - bool hasSSL = false; - bool hasBSL = false; - if (hasSelectedPivot) - { - // - // Required Info ... - // int toIDX = selectedPivot.ToIndex(); - // int fromIDX = selectedPivot.FromIndex(); - - // // - // // SSL ... - // datetime sslTo = NULL; - // datetime sslFrom = NULL; - - // // - // // BSL ... - // datetime bslTo = NULL; - // datetime bslFrom = NULL; - - // // - // // Loop ... - // XOHCL iBar; - // for (int i = fromIDX; i > toIDX; i--) - // { - // // - // hasSSL = - // ssl > 0 && - // IsValid(sslTo) && - // IsValid(sslFrom); - - // // - // hasBSL = - // bsl > 0 && - // IsValid(bslTo) && - // IsValid(bslFrom); - - // // - // iBar.Clean(); - - // // - // if (hasSSL && hasBSL) - // { - // break; - // } - // } - // iBar.Clean(); - } - // // Draw Selected Pivot ... if (allowDraws && @@ -1909,6 +2097,7 @@ bool CanTriggerCond2( // zBar.Clean(); cBar.Clean(); + selectedPivot.Clean(); // return result; diff --git a/XCAEA/Signals/xcaea.signaller.class.mq5 b/XCAEA/Signals/xcaea.signaller.class.mq5 index 919ae2ee..58db14ec 100644 --- a/XCAEA/Signals/xcaea.signaller.class.mq5 +++ b/XCAEA/Signals/xcaea.signaller.class.mq5 @@ -381,7 +381,7 @@ class XCXCAEASignaller : XCBase // // Reading Requirements ... - + // int loopback = 10; double ask = GetAsk(symbol); @@ -472,6 +472,14 @@ class XCXCAEASignaller : XCBase allowedTypes // ); } + Add( + XCA_PEAK, + allowedTypes // + ); + Add( + XCA_VALE, + allowedTypes // + ); int decisionPivotsCount = detector.FillPivots( conditions.decisionZone, decisionPivots, @@ -480,6 +488,27 @@ class XCXCAEASignaller : XCBase cTime // ); + // + // Draw Pivots of Decision Zone only when + // it's Too Large ... + if (false && + allowDraws && + isTooLarge && + HasChild(decisionPivots)) + { + // + for (int i = 0; i < decisionPivotsCount; i++) + { + // + drawer.DrawBox( + decisionPivots[i], + cTime, + false, // Draw Middle ... + true // Ignore Type ... + ); + } + } + // // Define a Temparory Objects // Array instance for Holding Drawn Objects ... @@ -849,7 +878,7 @@ class XCXCAEASignaller : XCBase inputs.x3maInputs.fastLength = 5; // - inputs.x3maInputs.showFast = false; + inputs.x3maInputs.showFast = true; inputs.x3maInputs.showSlow = false; inputs.x3maInputs.showMedium = false; @@ -870,9 +899,9 @@ class XCXCAEASignaller : XCBase inputs.caInputs.showMAH = false; inputs.caInputs.showMAL = false; inputs.caInputs.showMAC = false; - inputs.caInputs.showSar = false; + inputs.caInputs.showSar = true; inputs.caInputs.showVidya = false; - inputs.caInputs.showTrend = false; + inputs.caInputs.showTrend = true; inputs.caInputs.showSwings = true; inputs.caInputs.showFiboLevel1 = false; inputs.caInputs.showFiboLevel2 = false;