From 5872d9f29b09a0d1eb78c575475d0dbcad95a9c2 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Fri, 19 Sep 2025 15:10:55 +0330 Subject: [PATCH] last works on FIMA Back Tester ... --- Classes/x-saherelm.x-market.pattern.class.mq5 | 116 ++++++++++++++ Classes/x-saherelm.x-signaller.class.mq5 | 71 ++++++++- Experts/x-saherelm.xfima.backtester.ea.mq5 | 144 ++++++++++++------ .../x-saherelm.xfima.signaller.class.mq5 | 112 +++++++++++++- 4 files changed, 395 insertions(+), 48 deletions(-) diff --git a/Classes/x-saherelm.x-market.pattern.class.mq5 b/Classes/x-saherelm.x-market.pattern.class.mq5 index 88bd8d3a..a5366ef7 100644 --- a/Classes/x-saherelm.x-market.pattern.class.mq5 +++ b/Classes/x-saherelm.x-market.pattern.class.mq5 @@ -22,6 +22,8 @@ // // Imports ... #include "../Classes/x-saherelm.base.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" // // Definitions ... @@ -40,12 +42,16 @@ class XCMarketPatternDetector : public XCBase // Constructor ... XCMarketPatternDetector() { + barAnalyser = new XCBarAnalyser(); } // // Deconstructor ... ~XCMarketPatternDetector() { + // + delete barAnalyser; + ZeroMemory(barAnalyser); } // @@ -999,6 +1005,114 @@ class XCMarketPatternDetector : public XCBase return result; } + // + // FVG ... + + /** + * Check For FVG Exists in Specified Loopback Period ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param fvg: XBoxZone, reference for Holding FVG ... + * @param maxLoopback: int, Max Allowed Loopback to Lookup FVG ... + * + * @return ( bool ) + */ + bool HasFVG( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &fvg, + int maxLoopback = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalize ... + maxLoopback = NormalizeInt(maxLoopback, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + int start = bar.Index(); + int end = start + maxLoopback; + for (int i = start; i < end; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!has) + { + continue; + } + + // + // Check iBar is FVG or not ... + has = barAnalyser.IsFVG( + iBar, + fvg, + true // Force Bar Type ... + ); + if (!has) + { + // + fvg.Clean(); + iBar.Clean(); + CleanDirection(dir); + + // + continue; + } + + // + iBar.Clean(); + dir = fvg.dir; + + // + break; + } + + // + // Check FVG Exists ... + result = fvg.IsValid(); + + // + // Check Direction Exists ... + result = + result && + HasDirection(dir); + + // + // Cleanup Resources ... + if (!result) + { + // + fvg.Clean(); + CleanDirection(dir); + } + iBar.Clean(); + + // + return result; + } + // // Trending ... @@ -1465,6 +1579,8 @@ class XCMarketPatternDetector : public XCBase // Private ... private: // + // Props ... + XCBarAnalyser *barAnalyser; // // Helpers ... diff --git a/Classes/x-saherelm.x-signaller.class.mq5 b/Classes/x-saherelm.x-signaller.class.mq5 index c84594bc..a09c6d33 100644 --- a/Classes/x-saherelm.x-signaller.class.mq5 +++ b/Classes/x-saherelm.x-signaller.class.mq5 @@ -11,6 +11,7 @@ // - [] ProcessTick: Processing All Ticks // - [] ProcessNewBar: Processing All New Bars // - [] CheckForGuard: Check For Guards +// - [] NormalizeSignal: Normalizing Prepared Signal ... // - [] CheckAdditionslSignallerValidations: Additional Class Validations // // - Dont Forget to Call OnSignal Event in Process Methods when @@ -37,6 +38,7 @@ // Imports ... #include "../Classes/x-saherelm.base.class.mq5" #include "../Libraries/x-saherelm.x-trade.lib.mq5" +#include "../Classes/x-saherelm.x-market.pattern.class.mq5" // // Definitions ... @@ -57,6 +59,9 @@ class XCBaseSignaller : public XCBase // TCanAnalyse canAnalyseEventListener; + // + XCMarketPatternDetector *patternDetector; + // // Constructor ... XCBaseSignaller( @@ -92,6 +97,9 @@ class XCBaseSignaller : public XCBase // Set Dfault Values ... mProcessedTicksCount = 0; mLastCheckedBarTime = NULL; + + // + patternDetector = new XCMarketPatternDetector(); } // @@ -101,6 +109,10 @@ class XCBaseSignaller : public XCBase // // Cleanup Event Listeners ... SpecifiedClean(onSignalEventListeners); + + // + delete patternDetector; + ZeroMemory(patternDetector); } // @@ -286,6 +298,15 @@ class XCBaseSignaller : public XCBase return true; } + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + // // Protected ... protected: @@ -381,11 +402,20 @@ class XCBaseSignaller : public XCBase * * @param signal: XSignal, holding result Signal ... * @param forDir: ENUM_X_DIRECTION + * @param targets: XTarget Array, Provides Signal Targets (Price) ... + * @param r2r: double, Provides Signal (r2r), if not Provided uses Default R2R ... + * @param slPrice: double, Provides Signal SL Price, if not Provided uses riskInPoint ... + * @param riskInPoint: double, Provides Signal Risk Amount which Multiplied to Points, if not Provided uses DefaultRiskInPoint ... + * * @return ( bool ) */ bool PrepareSignal( XSignal &signal, - ENUM_X_DIRECTION forDir // + ENUM_X_DIRECTION forDir, + XTarget &targets[], // + double r2r = 0, + double slPrice = 0, + double riskInPoint = 0 // ) { // @@ -417,8 +447,19 @@ class XCBaseSignaller : public XCBase double entry = GetEntry(symbol, forDir); // - double risk = (defaultSignalRiskInPoint * point); - double reward = (risk * defaultSignalR2R) + spread; + riskInPoint = riskInPoint > 0 && slPrice <= 0 + ? riskInPoint + : defaultSignalRiskInPoint; + double risk = (riskInPoint * point); + risk = slPrice > 0 + ? MathAbs(entry - slPrice) + : risk; + + // + r2r = r2r > 0 + ? r2r + : defaultSignalR2R; + double reward = (risk * r2r) + spread; // double tp = @@ -448,9 +489,33 @@ class XCBaseSignaller : public XCBase : POSITION_TYPE_SELL; signal.mode = X_ORDER_MODE_MARKET; + // + // Apply Targets ... + if (HasChild(targets)) + { + // + ApplyTargetsOnSignal( + forDir, + targets, + signal // + ); + } + // // Validate Signal ... result = signal.IsValid(); + if (result) + { + // + NormalizeSignal(signal); + result = signal.IsValid(); + } + + // + if (!result) + { + signal.Clean(); + } // return result; diff --git a/Experts/x-saherelm.xfima.backtester.ea.mq5 b/Experts/x-saherelm.xfima.backtester.ea.mq5 index 41328ec1..0a14d72b 100644 --- a/Experts/x-saherelm.xfima.backtester.ea.mq5 +++ b/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -27,7 +27,7 @@ #include "../Classes/x-saherelm.x-backtester.expert.class.mq5" #include "../Classes/x-saherelm.x-market.pattern.class.mq5" #include "../Classes/x-saherelm.x-poi.drawer.class.mq5" -#include "../Helpers/x-saherelm.xom1.helper.mq5" +#include "../XFIMA/Classes/x-saherelm.xfima.signaller.class.mq5" // // Definitions ... @@ -132,6 +132,7 @@ input int valeArrowCode = 159; // Vales Arrow Code // string eaLogTag; // EA Log Prefix ... XCBackTesterEA *eaExpert; // EA Expert ... +XCXFIMAStrategy1Signaller *fima1Signaller; // XFIMA1 Signaller ... XCMarketPatternDetector *eaPatternDetector; // EA Pattern Detector ... // @@ -235,50 +236,70 @@ int OnInit() } // - // Initial Indicator Handler ... - eaHandler = iCustom( + // Here Instantiate Signaller Class ... + + // + // Preparing Indicator Inputs ... + XFIMAInputs fimaInputs; + + // + // This is Default Configuration ... + fimaInputs.Default(); + fimaInputs.Hide(); + fimaInputs.showZigZag = true; + + // + // Here we Attach Inputs to Indicator ... + fimaInputs.scMethod = scMethod; + fimaInputs.scPeriod = scPeriod; + fimaInputs.mcMethod = mcMethod; + fimaInputs.mcPeriod = mcPeriod; + fimaInputs.lcMethod = lcMethod; + fimaInputs.lcPeriod = lcPeriod; + fimaInputs.hcMethod = hcMethod; + fimaInputs.hcPeriod = hcPeriod; + fimaInputs.upperMode = upperMode; + fimaInputs.lowerMode = lowerMode; + fimaInputs.fiboUpperZoneLevel = fiboUpperZoneLevel; + fimaInputs.fiboMiddleZoneLevel = fiboMiddleZoneLevel; + fimaInputs.fiboLowerZoneLevel = fiboLowerZoneLevel; + fimaInputs.sarStep = sarStep; + fimaInputs.sarMax = sarMax; + fimaInputs.maMethod = maMethod; + fimaInputs.maAppliedTo = maAppliedTo; + fimaInputs.maFastLength = maFastLength; + fimaInputs.maSlowLength = maSlowLength; + fimaInputs.zigzagDepth = zigzagDepth; + fimaInputs.zigzagDeviation = zigzagDeviation; + fimaInputs.zigzagBackStep = zigzagBackStep; + fimaInputs.zigzagUppersMode = zigzagUppersMode; + fimaInputs.zigzagLowersMode = zigzagLowersMode; + fimaInputs.showPV = showPV; + fimaInputs.showSAR = showSAR; + fimaInputs.showMAFast = showMAFast; + fimaInputs.showMASlow = showMASlow; + fimaInputs.showZigZag = showZigZag; + fimaInputs.showFiboZone = showFiboZone; + fimaInputs.startCalculationForLastBars = startCalculationForLastBars; + fimaInputs.sarArrowCode = sarArrowCode; + fimaInputs.peakArrowCode = peakArrowCode; + fimaInputs.valeArrowCode = valeArrowCode; + + // + // Instantiate Signaller ... + fima1Signaller = new XCXFIMAStrategy1Signaller( _Symbol, _Period, - "x-saherelm.xfima", - "", // Calculation ... - scMethod, - scPeriod, - mcMethod, - mcPeriod, - lcMethod, - lcPeriod, - hcMethod, - hcPeriod, - upperMode, - lowerMode, - fiboUpperZoneLevel, - fiboMiddleZoneLevel, - fiboLowerZoneLevel, - sarStep, - sarMax, - maMethod, - maAppliedTo, - maFastLength, - maSlowLength, - zigzagDepth, - zigzagDeviation, - zigzagBackStep, - zigzagUppersMode, - zigzagLowersMode, - "", // Presentation ... - showPV, - showSAR, - showMAFast, - showMASlow, - showZigZag, - showFiboZone, - startCalculationForLastBars, - sarArrowCode, - peakArrowCode, - valeArrowCode - // + fimaInputs, + true, // Process All Ticks ... + 2.0, // Signaller Risk to Reward Ratio ... + 50, // Default Risk In Points ... + 0.01 // Defaul Volume ... ); - isInited = eaHandler != INVALID_HANDLE; + fima1Signaller.AddOnSignalEventHandler(OnSignalTriggered); + + // + isInited = fima1Signaller.IsValid(); if (!isInited) { // @@ -387,6 +408,9 @@ void OnTick() // DetectPatterns(); + + // + fima1Signaller.OnTick(); } // @@ -526,6 +550,38 @@ void DestroyTimer() // EventKillTimer(); } +/** + * Trigger OnSignal Event ... + * + * @param signal: XSignal + */ +void OnSignalTriggered(XSignal &signal) +{ + // + CChartObjectVLine *iObj = new CChartObjectVLine(); + + // + string iName = signal.GetTag(); + color iColor = IsLong(signal.type) ? clrLime : clrRed; + + // + bool has = iObj.Create( + eaDrawer.ChartIdentification(), + iName, + eaDrawer.SubWindowIdentification(), + signal.time // + ); + if (has) + { + // + iObj.Width(2); + iObj.Color(iColor); + + // + draws.Add(iObj); + } +} + // // Trade Event Handlers ... @@ -704,8 +760,8 @@ void DetectPatterns() bool detectSwingTrendBreakes = false; // - bool detectSupports = false; - bool detectResistance = false; + bool detectSupports = true; + bool detectResistance = true; // // Checking Momentum Bar ... diff --git a/XFIMA/Classes/x-saherelm.xfima.signaller.class.mq5 b/XFIMA/Classes/x-saherelm.xfima.signaller.class.mq5 index 892a5e48..7972a61e 100644 --- a/XFIMA/Classes/x-saherelm.xfima.signaller.class.mq5 +++ b/XFIMA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -188,6 +188,15 @@ class XCXFIMABaseSignaller : public XCBaseSignaller return result; } + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + // // Protected ... protected: @@ -208,6 +217,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller public: // // Props ... + int fvgLookupLenght; // Maximum Lenght for Looking up FVG before Crosses // // Constructor ... @@ -229,6 +239,8 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller _defaultSignalVolume // ) { + // + fvgLookupLenght = 5; } // @@ -323,20 +335,95 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // // Do Conditions Validating ... + // + // Validate MA Positions ... + double iFastMa = fimaConditions.maFastBuffer[cIdx]; + double iSlowMa = fimaConditions.maSlowBuffer[cIdx]; + double iFiboUpper = fimaConditions.fiboUpperBuffer[cIdx]; + double iFiboLower = fimaConditions.fiboLowerBuffer[cIdx]; + + // + // Checking Has FVG ... + XBoxZone fvg; + ENUM_X_DIRECTION fvgDir; + bool hasFVG = patternDetector.HasFVG( + bar, + fvgDir, + fvg, + fvgLookupLenght // + ); + + // + // Checking Crossed On Shadow ... + + // + bool isCrossedOverHappensOnShadow = + isFastCrossedOverSlow && + iFastMa <= bar.GetDown() && + iFastMa >= bar.low; + + // + bool isCrossedUnderHappensOnShadow = + isFastCrossedUnderSlow && + iFastMa <= bar.high && + iFastMa >= bar.GetUp(); + // // Bullish Validation ... bool isBullish = // + // Has Cross ... isFastCrossedOverSlow // + && + // + // Cross Places Based on Fibo ... + MathMax(iFastMa, iSlowMa) < iFiboLower + // + && + // + ( + // + // Checking FVG ... + (hasFVG && + fvg.IsBullish()) + // + || + // + // Checking Crossed Place ... + isCrossedOverHappensOnShadow + // + ) + // ; // // Bearish Validation ... bool isBearish = // + // Has Cross ... isFastCrossedUnderSlow // + && + // + // Cross Places Based on Fibo ... + MathMin(iFastMa, iSlowMa) > iFiboUpper + // + && + // + ( + // + // Checking FVG ... + (hasFVG && + fvg.IsBearish()) + // + || + // + // Checking Crossed Place ... + isCrossedUnderHappensOnShadow + // + ) + // ; // @@ -360,9 +447,11 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller { // // Prepare Founded Signal ... + XTarget targets[]; has = PrepareSignal( signal, - signalDir // + signalDir, + targets // ); if (has) { @@ -405,6 +494,27 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller return result; } + // + // Private ... + private: + // + // Props ... + + // + // Lookup FVG ... + bool LookupFVG( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &fvgBox // + ) + { + // + bool result = false; + + // + return result; + } + // };