From f4067df926cfc0ae361c89e5970f225c7906817e Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Sun, 28 Sep 2025 19:57:03 +0330 Subject: [PATCH] last ... --- Experts/x-saherelm.xfima.backtester.ea.mq5 | 1 + .../x-saherelm.xfima.signaller.class.mq5 | 819 ++++++++++++++++-- 2 files changed, 767 insertions(+), 53 deletions(-) diff --git a/Experts/x-saherelm.xfima.backtester.ea.mq5 b/Experts/x-saherelm.xfima.backtester.ea.mq5 index 618f7717..a7692f35 100644 --- a/Experts/x-saherelm.xfima.backtester.ea.mq5 +++ b/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -909,6 +909,7 @@ void AnalyseMarket(int barIndex = 0) // // Handle Signal Looking Up ... +// Register it as XFIMA Signaller 2 ... void HandleSignalLookup(XOHCL &bar) { // diff --git a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 index e142c726..1ade2d49 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -41,8 +41,8 @@ class XCXFIMABaseSignaller : public XCBaseSignaller // Props ... // - XFIMAInputs fimaInputs; // XFIMA Inputs ... - XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... + XFIMAInputs fimaInputs; // XFIMA Inputs ... + XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... @@ -351,7 +351,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller { // // Do Conditions Validating ... - // TODO: Igmore All Validations for Testing Purposes ... + // TODO: Igmore All Validations for Testing Purposes ... // // Validate MA Positions ... @@ -545,6 +545,7 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller public: // // Props ... + XFIMAPatternDetectorConfig analyserConfig; // // Constructor ... @@ -566,6 +567,21 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller _defaultSignalVolume // ) { + // + // Configure Detector ... + analyserConfig.Default(); + analyserConfig.FullDetect(); + } + + // + // Deconstructor ... + ~XCXFIMAStrategy2Signaller() + { + // + Destroy(); + + // + analyserConfig.Clean(); } // @@ -611,10 +627,20 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller // XOHCL bar; XSignal signal; + XBoxZone iZone; bool has = false; int cIdx = barIndex + 1; int pIdx = cIdx + 1; - ENUM_X_DIRECTION signalDir = X_DIRECTION_NONE; + string iName = NULL; + bool isBullish = false; + bool isBearish = false; + double iPrice = EMPTY_VALUE; + XBoxZone supports[]; + XBoxZone resistances[]; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + XFIMAMarketStructure structure; + XFIMAConditions fimaConditions; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; // // Initialize Bar as CBar ... @@ -632,7 +658,6 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller // // Retrieve Conditions ... - XFIMAConditions fimaConditions; has = fimaHelper.GetConditions( fimaConditions, barIndex, @@ -649,12 +674,98 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller } // - // Analyse Conditions for Finding Signal ... - bool isBullish = false; - bool isBearish = false; + // Analyse Market ... + poiDetector.AnalyseMarket( + bar, + structure, + analyserConfig // + ); // - // Chekc Bullish or Bearish Starter Conditions ... + // Check Required Pattern Exists ... + bool hasPinnedBar = HasDirection(structure.pinnedDir); + bool hasEngulfedBar = HasDirection(structure.engulfedDir); + bool hasFlagPattern = HasDirection(structure.flagPatternDir); + bool hasStarPattern = HasDirection(structure.starPatternDir); + bool hasRisingPattern = HasDirection(structure.risingPatternDir); + bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); + bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); + + // + // Check Bar Pattern Exists ... + has = hasPinnedBar || + hasEngulfedBar || + hasFlagPattern || + hasStarPattern || + hasSignalKeyBar || + hasRisingPattern || + hasPiercingPattern; + + // + // Select Pattern Direction and Price and Price Type ... + if (has) + { + // + if (hasPinnedBar) + { + // + iDir = structure.pinnedDir; + iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasEngulfedBar) + { + // + iDir = structure.engulfedDir; + iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasFlagPattern) + { + // + iDir = structure.flagPatternDir; + iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasStarPattern) + { + // + iDir = structure.starPatternDir; + iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasSignalKeyBar) + { + // + iDir = structure.risingPatternDir; + iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasRisingPattern) + { + // + iDir = structure.piercingPatternDir; + iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasPiercingPattern) + { + // + iDir = structure.signalKeyBarPatternDir; + iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + + // + isBullish = IsSpecifiedBullish(iDir); + isBearish = IsSpecifiedBearish(iDir); + + // + // Retrieve Price Type for Validate ... + iPriceType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + iPrice = bar.GetPrice(iPriceType); + + // + has = HasDirection(iDir); + } + + // + // Chekc Bullish or Bearish Starter Conditions Exists ... has = isBullish || isBearish; @@ -664,57 +775,659 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller // Do Conditions Validating ... // - // Bullish Validation ... - isBullish = - // - isBullish - // - && - // - // Validations ... - ( - // - false - // - ) - // - ; + // Retrieve MA Band for Validation ... + double iMABandUpper = fimaHelper.GetMABandUpper(barIndex); + double iMABandLower = fimaHelper.GetMABandLower(barIndex); // - // Bearish Validation ... - isBearish = - // - isBearish - // - && - // - // Validations ... - ( - // - false - // - ) - // - ; - - // - has = - (isBullish && !isBearish) || - (isBearish && !isBullish); - if (has) + // Validate ... + has = isBullish + ? iPrice < iMABandLower + : iPrice > iMABandUpper; + if (!has) { - // - // Specified Signal Directions ... - signalDir = - isBullish - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; + iDir = X_DIRECTION_NONE; } } + // + // Collect Support and Resistance Zones and Validate by them ... + + // + // PV Trend Line ... + string pvTrendName = "XXIFMA2PVTrend"; + CChartObjectTrend *pvTrendLine = NULL; + ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; + bool hasPVAnalysis = structure.pvAnalysis.IsValid(); + if (hasPVAnalysis) + { + // + // Support ... + XBoxZone supportBox; + XCBoxObject *iSupportObj; + has = structure.pvAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + has = poiDrawer.DrawBox( + supportBox, + iSupportObj, + true, // Ignore At ... + supportBox.type // Name ... + ); + if (has) + { + // + XPOIStyle iStyle; + poiDrawer.GetBoxStyle( + iStyle, + supportBox.dir // + ); + poiDrawer.ApplyBoxStyle( + iSupportObj, + iStyle // + ); + iStyle.Clean(); + } + } + + // + // Resistance ... + XBoxZone resistanceBox; + XCBoxObject *iResistanceObj; + has = structure.pvAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + has = poiDrawer.DrawBox( + resistanceBox, + iResistanceObj, + true, // Ignore At ... + resistanceBox.type // Name ... + ); + if (has) + { + // + XPOIStyle iStyle; + poiDrawer.GetBoxStyle( + iStyle, + resistanceBox.dir // + ); + poiDrawer.ApplyBoxStyle( + iResistanceObj, + iStyle // + ); + iStyle.Clean(); + } + } + + // + // Pivots ... + XPivot pivots[]; + int pivotsCount = poiDetector.ExtractPVPivots( + pivots, + barIndex, + 50 // + ); + has = IsValidSize(pivotsCount); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + pvTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(pvTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(pvTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + pvTrendLine, + pvTrendName, + true // Ray Right ... + ); + if (has) + { + pvTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + pivotsCount = poiDrawer.DrawPivots( + pivots, + drawnPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // ZigZag Trend Line ... + string zgTrendName = "XFIMA2ZGTrend"; + CChartObjectTrend *zgTrendLine = NULL; + ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; + bool hasZGAnalysis = structure.zigzagAnalysis.IsValid(); + if (hasZGAnalysis) + { + // + // Support ... + XBoxZone supportBox; + XCBoxObject *iSupportObj; + has = structure.zigzagAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + has = poiDrawer.DrawBox( + supportBox, + iSupportObj, + true, // Ignore At ... + supportBox.type // Name ... + ); + if (has) + { + // + XPOIStyle iStyle; + poiDrawer.GetBoxStyle( + iStyle, + supportBox.dir // + ); + poiDrawer.ApplyBoxStyle( + iSupportObj, + iStyle // + ); + iStyle.Clean(); + } + } + + // + // Resistance ... + XBoxZone resistanceBox; + XCBoxObject *iResistanceObj; + has = structure.zigzagAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + has = poiDrawer.DrawBox( + resistanceBox, + iResistanceObj, + true, // Ignore At ... + resistanceBox.type // Name ... + ); + if (has) + { + // + XPOIStyle iStyle; + poiDrawer.GetBoxStyle( + iStyle, + resistanceBox.dir // + ); + poiDrawer.ApplyBoxStyle( + iResistanceObj, + iStyle // + ); + iStyle.Clean(); + } + } + + // + // Pivots ... + XPivot pivots[]; + int pivotsCount = poiDetector.ExtractZigZagPivots( + pivots, + barIndex, + 10 // + ); + has = IsValidSize(pivotsCount); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + zgTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(zgTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(zgTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + zgTrendLine, + zgTrendName, + true // Ray Right ... + ); + if (has) + { + zgTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + pivotsCount = fima2Signaller.poiDrawer.DrawPivots( + pivots, + drawnPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // Support ... + bool hasSupport = structure.support.IsValid(); + if (hasSupport) + { + // + AddIfNotExists( + structure.support, + supports // + ); + + // + XCBoxObject *iObj; + has = fima2Signaller.poiDrawer.DrawBox( + structure.support, + iObj); + if (has) + { + } + } + + // + // Resistance ... + bool hasResistance = structure.resistance.IsValid(); + if (hasResistance) + { + // + AddIfNotExists( + structure.resistance, + resistances // + ); + + // + XCBoxObject *iObj; + has = fima2Signaller.poiDrawer.DrawBox( + structure.resistance, + iObj); + if (has) + { + } + } + + // + // Validate Positions Support and Resistance Zone ... + int insideZoneIDX = -1; + has = has && + (isBullish + ? HasInside( + insideZoneIDX, + bar, + supports // + ) + : HasInside( + insideZoneIDX, + bar, + resistances // + )); + + // + // Validate Selected Inside Zone ... + // whith Bars Edge ... + has = IsValidIndex(insideZoneIDX); + if (has) + { + // + if (isBullish) + { + iZone = supports[insideZoneIDX]; + } + else + { + iZone = resistances[insideZoneIDX]; + } + + // + has = isBullish + ? bar.high > supports[insideZoneIDX].upper + : bar.low < resistances[insideZoneIDX].lower; + if (!has) + { + iDir = X_DIRECTION_NONE; + } + } + + // + // Checking Liquidities ... + + // + // Do all Draws Here ... + // // Check Signal Founded ... - has = HasDirection(signalDir); + has = HasDirection(iDir); if (has) { // @@ -725,7 +1438,7 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller XTarget targets[]; has = PrepareSignal( signal, - signalDir, + iDir, targets // ); if (has)