From 2669790493b6bdaaac00d192b0604c628f989a71 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Wed, 1 Oct 2025 17:16:13 +0330 Subject: [PATCH] add XTargetManager Class and use it in XBacktesterEA Class ... also i have to implement it's usage on XCExpert Class ... extends XTarget approaches and add support to Distances ... --- .../x-saherelm.x-backtester.expert.class.mq5 | 94 ++- Classes/x-saherelm.x-target.manager.class.mq5 | 620 ++++++++++++++++++ Classes/x-saherelm.x-trade.class.mq5 | 53 +- Documents/BKP/tmp.backtester.codes.mq5 | 113 ++++ Experts/x-saherelm.xfima.backtester.ea.mq5 | 192 +----- Libraries/x-saherelm.x-trade.lib.mq5 | 41 ++ .../x-saherelm.xfima.signaller.class.mq5 | 142 +++- 7 files changed, 1054 insertions(+), 201 deletions(-) create mode 100644 Classes/x-saherelm.x-target.manager.class.mq5 diff --git a/Classes/x-saherelm.x-backtester.expert.class.mq5 b/Classes/x-saherelm.x-backtester.expert.class.mq5 index c6e57bd7..aba66e3f 100644 --- a/Classes/x-saherelm.x-backtester.expert.class.mq5 +++ b/Classes/x-saherelm.x-backtester.expert.class.mq5 @@ -23,6 +23,7 @@ #include "../Classes/x-saherelm.base.class.mq5" #include "../Classes/x-saherelm.x-alert.class.mq5" #include "../Classes/x-saherelm.x-chart.helper.class.mq5" +#include "../Classes/x-saherelm.x-target.manager.class.mq5" #include "../Classes/x-saherelm.x-trade.class.mq5" #include "../Classes/x-saherelm.x-volume.class.mq5" @@ -80,8 +81,11 @@ class XCBackTesterEA : public XCBase double volume; // Default volume Per Trade ... // - XCAlert *eaAlert; // EA Scope Alert Handler ... - XCTrade *eaTrader; // EA Scope Trade Handler ... + XCAlert *eaAlert; // EA Scope Alert Handler ... + XCTrade *eaTrader; // EA Scope Trade Handler ... + XCTargetManager *eaTargetManager; // EA Scope Target Manager ... + + // XCChartHelper *eaChartHelper; // Chart Helper Class ... // @@ -273,6 +277,23 @@ class XCBackTesterEA : public XCBase } } + // + // Signal Executed Event Handlers ... + count = ArraySize(mOnSignalExecutedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrader.AddOnSignalExecutedEventHandler(mOnSignalExecutedEventHandlers[i]); + } + } + + // + // Init Target Managers ... + eaTargetManager = new XCTargetManager(eaTrader); + // // Initial GUI ... result = InitGUI(); @@ -294,6 +315,11 @@ class XCBackTesterEA : public XCBase */ void HandleOnDeInit() { + // + eaTargetManager.Destroy(); + delete eaTargetManager; + ZeroMemory(eaTargetManager); + // delete eaTrader; ZeroMemory(eaTrader); @@ -326,7 +352,12 @@ class XCBackTesterEA : public XCBase */ void HandleOnTick() { + // UpdateGUI(); + + // + // Managing Targets ... + eaTargetManager.Manage(); } /** @@ -395,6 +426,9 @@ class XCBackTesterEA : public XCBase // // Update Position Buttons ... UpdatePositionButtons(); + + // + eaTargetManager.HandleOnStopLossTriggered(deal); } /** @@ -407,6 +441,9 @@ class XCBackTesterEA : public XCBase // // Update Position Buttons ... UpdatePositionButtons(); + + // + eaTargetManager.HandleOnTakeProfitTriggered(deal); } /** @@ -425,6 +462,13 @@ class XCBackTesterEA : public XCBase // // Update Position Buttons ... UpdatePositionButtons(); + + // + eaTargetManager.HandleOnPositionForceClosed( + ticket, + position, + comment // + ); } /** @@ -502,6 +546,34 @@ class XCBackTesterEA : public XCBase { } + /** + * Handle New Signal Recieved ... + * + * @param signal: XSignal, reference to recieved Signal ... + */ + void HandleOnSignalTriggered(XSignal &signal) + { + // + ENUM_X_SIGNAL_EXECUTION_RESULT result; + bool isExcuted = eaTrader.ExecuteSignal( + signal, + result // + ); + if (isExcuted) + { + } + } + + /** + * Handle Signal Executed Event ... + * + * @param signal: XSignal, reference to Executed Signal ... + */ + void HandleOnSignalExecuted(XSignal &signal) + { + eaTargetManager.AddExecutedSignal(signal); + } + // // Props and Setter / Getter (s) ... @@ -652,6 +724,23 @@ class XCBackTesterEA : public XCBase ); } + // + // Add New Signal Executed Event Handler ... + void AddOnSignalExecutedEventHandler(TOnSignal handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnSignalExecutedEventHandlers // + ); + } + // // Protected ... protected: @@ -667,6 +756,7 @@ class XCBackTesterEA : public XCBase TOnStopLoss mStopLossEventHandlers[]; TOnTakeProfit mTakeProfitEventHandlers[]; TOnForceClose mOnForceCloseEventHandlers[]; + TOnSignal mOnSignalExecutedEventHandlers[]; TOnDealsChanged mDealsChangedEventHandlers[]; TOnOrdersChanged mOrdersChangedEventHandlers[]; TOnPartialClose mOnPartialCloseEventHandlers[]; diff --git a/Classes/x-saherelm.x-target.manager.class.mq5 b/Classes/x-saherelm.x-target.manager.class.mq5 new file mode 100644 index 00000000..a04dd93c --- /dev/null +++ b/Classes/x-saherelm.x-target.manager.class.mq5 @@ -0,0 +1,620 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XCTargetManager +// Description: provides all Positions Target requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" + +// +// Implementation ... +class XCTargetManager : public XCBase +{ + // + // Public ... + public: + // + XCTrade *trader; + XSignal signals[]; + + // + // Constructor ... + XCTargetManager( + XCTrade *_trader // + ) : XCBase() + { + // + trader = _trader; + XClean(signals); + } + + // + // Deconstructor ... + ~XCTargetManager() + { + Destroy(); + } + + // + void Destroy() + { + // + XClean(signals); + } + + // + // Actions ... + + /** + * Manage Positions ... + * + * @param barIndex: int, Bar Index ... + */ + void Manage(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Extract In Profit Positions ... + XPosition positions[]; + int count = GetInProfitPositions(positions); + bool has = IsValidIndex(count); + if (!has) + { + return; + } + + // + XSignal iSignal; + XTarget iTarget; + int signalIDX = -1; + int targetIDX = -1; + XPosition iPosition; + + // + // Loop through Positions ... + for (int i = 0; i < count; i++) + { + // + // Select Positions ... + iPosition = positions[i]; + has = FindSignal( + signalIDX, + iPosition.ticket // + ); + if (!has) + { + continue; + } + iSignal = signals[signalIDX]; + + // + // Selecting Target ... + targetIDX = iSignal.appliedTargetIDX; + if (iSignal.isTargetApplied) + { + targetIDX++; + } + + // + // Validate Targets Size ... + has = HasChild(iSignal.targets) && + targetIDX < ArraySize(iSignal.targets); + if (has) + { + // + // Select Target ... + iTarget = iSignal.targets[targetIDX]; + + // + // Check Can Apply Target and Apply it ... + has = HandleApplyTarget(iTarget, iPosition); + if (has) + { + // + // Update Target IDX ... + iSignal.appliedTargetIDX++; + } + } + + // + // Update Signal ... + signals[signalIDX] = iSignal; + + // + // Cleanup ... + iSignal.Clean(); + iTarget.Clean(); + iPosition.Clean(); + } + + // + // Cleanup Resources ... + iSignal.Clean(); + iTarget.Clean(); + iPosition.Clean(); + } + + /** + * Extract in Profit Positions ... + * + * @param positions: XPosition, reference collection to holds result ... + * + * @return ( int ) + */ + int GetInProfitPositions( + XPosition &positions[] // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(positions); + + // + // Validate ... + if (trader == NULL) + { + return result; + } + + // + result = trader.GetInProfitPositions( + positions, + NULL, // All Symbols ... + NULL, // All Providers ... + NULL, // All Periods ... + NULL, // All Position Types ... + X_POSITION_SELECT_ALL, // Select Method ... + true, // Filter by Magic ... + true // Force Clean ... + ); + if (IsValidSize(result)) + { + // + XPosition iPos; + XPosition tmp[]; + Copy( + positions, + tmp // + ); + XClean(positions); + while (HasChild(tmp)) + { + // + iPos = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + int idx = -1; + bool has = FindSignal( + idx, + iPos.ticket // + ); + if (has) + { + // + AddRef( + iPos, + positions // + ); + } + } + + // + XClean(tmp); + iPos.Clean(); + + // + result = ArraySize(positions); + } + + // + return result; + } + + /** + * Add Executed Signal ... + * + * @param signal: XSignal, reference to Executed Signal ... + */ + void AddExecutedSignal(XSignal &signal) + { + // + // Validate ... + if (!signal.IsValid() || !signal.IsExecuted()) + { + return; + } + + // + AddRef( + signal, + signals // + ); + } + + // + // Trade Event Handlers ... + + /** + * Handle Stop Loss Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) + { + RemoveSignal(deal.positionId); + } + + /** + * Handle Take Profit Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) + { + RemoveSignal(deal.positionId); + } + + /** + * Handle Position Force Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param position: XPosition instance refrence, Triggered Position ... + * @param comment: string, Comment ... + */ + void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + RemoveSignal(ticket); + } + + // + // Event Handlers Registration ... + + // + void AddOnStopLossEventHandler(TOnStopLoss handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mStopLossEventHandlers + // + ); + } + + // + void AddOnTakeProfitEventHandler(TOnTakeProfit handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTakeProfitEventHandlers + // + ); + } + + // + void AddOnForceClosePositionEventHandler(TOnForceClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnForceCloseEventHandlers + // + ); + } + + // + // Protected ... + protected: + // + + /** + * Find Specified Signal ... + * + * @param index: int, reference to holds detected index ... + * @param signal: XSignal, reference to Specified Signal ... + * + * @return ( bool ) + */ + bool FindSignal( + int &index, + XSignal &signal // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Validate ... + result = signal.IsValid() && + HasChild(signals); + if (!result) + { + return result; + } + + // + // Looping Through Signals ... + int count = ArraySize(signals); + for (int i = 0; i < count; i++) + { + // + result = signals[i] + .IsSameAs(signal); + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Find Specified Signal ... + * + * @param index: int, reference to holds detected index ... + * @param ticket: ulong, Specified Signal Position ID ... + * + * @return ( bool ) + */ + bool FindSignal( + int &index, + ulong ticket // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Validate ... + result = NotEmptyZero(ticket) && + HasChild(signals); + if (!result) + { + return result; + } + + // + // Looping Through Signals ... + int count = ArraySize(signals); + for (int i = 0; i < count; i++) + { + // + result = signals[i].IsValid() && + signals[i].IsExecuted() && + signals[i].positionId == ticket; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Remove Specified Signal ... + * + * @param ticket: ulong, Specified Ticket ... + */ + void RemoveSignal(ulong ticket) + { + // + bool has = NotEmptyZero(ticket) && + HasChild(signals); + if (!has) + { + return; + } + + // + int idx = -1; + has = FindSignal( + idx, + ticket // + ); + if (!has) + { + return; + } + + // + ArrayRemove( + signals, + idx, + 1 // + ); + } + + /** + * Check Can Apply Specified Target on Specified Position or not ... + * + * @param target: XTarget, reference to Specified Target for Apply ... + * @param position: XPosition, reference to Specified Position ... + * + * @return ( bool ) + */ + bool CanApplyTarget( + XTarget &target, + XPosition &position // + ) + { + // + bool result = false; + + // + // Validate ... + result = + target.IsValid() && + position.IsValid(); + if (!result) + { + return result; + } + + // + // Check Price Reached Targets Value and Distance ... + double targetDistance = (target.actingDistance > 0 ? target.actingDistance : 0) * position.GetPointsValue(); + result = + IsLong(position.type) + ? position.price >= target.target + targetDistance + : position.price <= target.target - targetDistance; + + // + return result; + } + + /** + * Apply Specified Target on Specified Position ... + * + * @param target: XTarget, reference to Specified Target for Apply ... + * @param position: XPosition, reference to Specified Position ... + * + * @return ( bool ) + */ + bool HandleApplyTarget( + XTarget &target, + XPosition &position // + ) + { + // + bool result = false; + + // + // Validate ... + result = + target.IsValid() && + position.IsValid() && + CanApplyTarget( + target, + position // + ); + if (!result) + { + return result; + } + + // + // Apply Target ... + string comment = NULL; + + // + // Do Risk Free if Provided ... + if (target.doRF) + { + // + comment = "Taregt Manager do RF ..."; + result = trader.Modify( + position.ticket, + target.target, // SL ... + position.tp, // TP ... + comment // + ); + } + + // + // Do Partial Close if Provided ... + if (result && target.volumeMultiplier > 0) + { + // + double volume = NormalizeVolume((position.volume * target.volumeMultiplier), position.symbol); + if (volume != position.volume) + { + // + comment = "Target Manager do Partial Close ..."; + result = trader.ClosePartial( + position.ticket, + volume, + comment // + ); + } + } + + // + return result; + } + + // + // Private ... + private: + // + + // + // Required Event Handlers ... + TOnStopLoss mStopLossEventHandlers[]; + TOnTakeProfit mTakeProfitEventHandlers[]; + TOnForceClose mOnForceCloseEventHandlers[]; +}; + +// diff --git a/Classes/x-saherelm.x-trade.class.mq5 b/Classes/x-saherelm.x-trade.class.mq5 index 4fd81d05..12a60119 100644 --- a/Classes/x-saherelm.x-trade.class.mq5 +++ b/Classes/x-saherelm.x-trade.class.mq5 @@ -814,6 +814,23 @@ class XCTrade : public XCBase ); } + // + // Add New Signal Executed Event Handler ... + void AddOnSignalExecutedEventHandler(TOnSignal handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnSignalExecutedEventHandlers // + ); + } + // // Functions ... @@ -1355,11 +1372,10 @@ class XCTrade : public XCBase mSignal.positionId = ticket; // - // Handle Store XPositionInfo ... + // Notify Signal Execution ... if (mSignal.mode == X_ORDER_MODE_MARKET) { - // - // TODO: Implement this ... + NotifySignalExecuted(mSignal); } } @@ -3568,6 +3584,33 @@ class XCTrade : public XCBase } } + // + void NotifySignalExecuted(XSignal &signal) + { + // + bool has = signal.IsValid() && + signal.IsExecuted(); + if (!has) + { + return; + } + + // + int count = ArraySize(mOnSignalExecutedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnSignal iHandler = mOnSignalExecutedEventHandlers[i]; + iHandler(signal); + } + } + // // Tools ... @@ -3728,6 +3771,10 @@ class XCTrade : public XCBase // Trade State Changed Event Handlers ... TOnTradeStateChanged mTradeStateChangedEventHandlers[]; + // + // Signal Executed Event Handlers ... + TOnSignal mOnSignalExecutedEventHandlers[]; + // TOnModify mOnModifyEventHandlers[]; TOnForceClose mOnForceCloseEventHandlers[]; diff --git a/Documents/BKP/tmp.backtester.codes.mq5 b/Documents/BKP/tmp.backtester.codes.mq5 index 18634326..55c7c9a6 100644 --- a/Documents/BKP/tmp.backtester.codes.mq5 +++ b/Documents/BKP/tmp.backtester.codes.mq5 @@ -1274,3 +1274,116 @@ void OnTick() // cBar.Clean(); } + +// +void AnalyseMarket(int barIndex = 0) +{ + // + bool has = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + string symbol = fima1Signaller.symbol; + ENUM_TIMEFRAMES period = fima1Signaller.period; + + // + // Retrieve Signal Bar ... + XOHCL bar; + has = bar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + bar.Clean(); + return; + } + + // + // TODO: Remove this and add in OnInit() Method ... + + // + // Configuring Detector ... + + + // + detectorConfig.detectSwingTrend = true; + + // + detectorConfig.detectPinned = true; + detectorConfig.detectMomentum = true; + detectorConfig.detectEngulfed = true; + detectorConfig.detectTrueGaped = true; + + // + detectorConfig.detectStarPattern = true; + detectorConfig.detectFlagPattern = true; + detectorConfig.detectRisingPattern = true; + detectorConfig.detectPiercingPattern = true; + detectorConfig.detectSignalKeyBarPattern = true; + + // + detectorConfig.analyseFIMAPVPivots = true; + detectorConfig.analyseFIMAZigZagPivots = true; + + // + // Configure Drawer ... + + // + marketStructureDrawerConfig.drawOB = false; + marketStructureDrawerConfig.drawFVG = false; + + // + marketStructureDrawerConfig.drawPinned = false; + marketStructureDrawerConfig.drawEngulfed = true; + marketStructureDrawerConfig.drawTrueGaped = false; + marketStructureDrawerConfig.drawMomentum = false; + marketStructureDrawerConfig.drawFlagPattern = false; + marketStructureDrawerConfig.drawStarPattern = false; + marketStructureDrawerConfig.drawRisingPattern = false; + marketStructureDrawerConfig.drawPiercingPattern = false; + marketStructureDrawerConfig.drawSignalKeyBarPattern = true; + + // + // Recents ... + marketStructureDrawerConfig.drawRecentPatterns = false; + marketStructureDrawerConfig.drawFakeBreakedZone = false; + marketStructureDrawerConfig.drawRecentlyTestedZones = false; + marketStructureDrawerConfig.drawRecentlyBreakedZones = false; + + // + // XPV ... + marketStructureDrawerConfig.drawFIMAPVPivotsAnalysis = true; + marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisZones = true; + marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisTrends = true; + marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisPivots = true; + + // + // XSAR ... + marketStructureDrawerConfig.drawFIMASARPivotsAnalysis = false; + marketStructureDrawerConfig.drawFIMASARPivotsAnalysisZones = false; + marketStructureDrawerConfig.drawFIMASARPivotsAnalysisTrends = false; + marketStructureDrawerConfig.drawFIMASARPivotsAnalysisPivots = false; + + // + // XZigZag ... + marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysis = true; + marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisZones = true; + marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisTrends = false; + marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisPivots = false; + + // + // Analyse Market on Signalling Bar ... + fima1Signaller.poiDetector.AnalyseMarket( + bar, + marketStructure, + detectorConfig // + ); + + // + bar.Clean(); +} diff --git a/Experts/x-saherelm.xfima.backtester.ea.mq5 b/Experts/x-saherelm.xfima.backtester.ea.mq5 index d43e58fc..d85fd9f6 100644 --- a/Experts/x-saherelm.xfima.backtester.ea.mq5 +++ b/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -228,6 +228,7 @@ int OnInit() eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); + eaExpert.AddOnSignalExecutedEventHandler(OnSignalExecuted); eaExpert.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); eaExpert.AddOnModifyPositionEventHandler(OnPositionModified); eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged); @@ -440,10 +441,8 @@ void OnTick() int barIndex = 1; // + // Signallers Calling OnTick ... fima1Signaller.OnTick(barIndex); - - // - // AnalyseMarket(barIndex); } // @@ -590,17 +589,6 @@ void DestroyTimer() */ void OnSignalTriggered(XSignal &signal) { - // - // Validate Signal ... - if (!signal.IsValid()) - { - return; - } - - // - // TODO: Fix this ... - // return; - // // Draw Signal on Chart ... XCSignalObject *iSignalObj; @@ -611,60 +599,17 @@ void OnSignalTriggered(XSignal &signal) ); // - if (has) - { - // - ENUM_X_SIGNAL_EXECUTION_RESULT result; - eaExpert.eaTrader.ExecuteSignal( - signal, - result // - ); + eaExpert.HandleOnSignalTriggered(signal); +} - // - Print("Signal Issued: ", signal.GetObjectID()); - } - - // - // Try to Execute Signal ... - - // - // Draw Signal Vertical Line ... - - // // - // CChartObjectVLine *iObj = new CChartObjectVLine(); - - // // - // string iName = signal.GetObjectID(); - // color iColor = IsLong(signal.type) ? clrLime : clrRed; - - // // - // bool has = iObj.Create( - // fima2Signaller.poiDrawer.ChartIdentification(), - // iName, - // fima2Signaller.poiDrawer.SubWindowIdentification(), - // signal.time // - // ); - // if (has) - // { - // // - // iObj.Width(2); - // iObj.Color(iColor); - - // // - // // eaDraws.Add(iObj); - // } - - // // - // // Alert Issued Signal ... - // string message = signal.GetMessage(); - - // - // int signalBarIndex = GetBarIndex( - // signal.symbol, - // signal.period, - // signal.time // - // ); - // AnalyseMarket(signalBarIndex); +/** + * Trigger OnSignal Executed Event ... + * + * @param signal: XSignal + */ +void OnSignalExecuted(XSignal &signal) +{ + eaExpert.HandleOnSignalExecuted(signal); } // @@ -793,117 +738,4 @@ void OnTradeStateChanged(const XOnTradeHandlerState &state) eaExpert.HandleOnTradeStateChanged(state); } -// -void AnalyseMarket(int barIndex = 0) -{ - // - bool has = false; - - // - barIndex = NormalizeInt(barIndex, 0); - - // - string symbol = fima1Signaller.symbol; - ENUM_TIMEFRAMES period = fima1Signaller.period; - - // - // Retrieve Signal Bar ... - XOHCL bar; - has = bar.Init( - symbol, - period, - barIndex // - ); - if (!has) - { - // - bar.Clean(); - return; - } - - // - // TODO: Remove this and add in OnInit() Method ... - - // - // Configuring Detector ... - - - // - detectorConfig.detectSwingTrend = true; - - // - detectorConfig.detectPinned = true; - detectorConfig.detectMomentum = true; - detectorConfig.detectEngulfed = true; - detectorConfig.detectTrueGaped = true; - - // - detectorConfig.detectStarPattern = true; - detectorConfig.detectFlagPattern = true; - detectorConfig.detectRisingPattern = true; - detectorConfig.detectPiercingPattern = true; - detectorConfig.detectSignalKeyBarPattern = true; - - // - detectorConfig.analyseFIMAPVPivots = true; - detectorConfig.analyseFIMAZigZagPivots = true; - - // - // Configure Drawer ... - - // - marketStructureDrawerConfig.drawOB = false; - marketStructureDrawerConfig.drawFVG = false; - - // - marketStructureDrawerConfig.drawPinned = false; - marketStructureDrawerConfig.drawEngulfed = true; - marketStructureDrawerConfig.drawTrueGaped = false; - marketStructureDrawerConfig.drawMomentum = false; - marketStructureDrawerConfig.drawFlagPattern = false; - marketStructureDrawerConfig.drawStarPattern = false; - marketStructureDrawerConfig.drawRisingPattern = false; - marketStructureDrawerConfig.drawPiercingPattern = false; - marketStructureDrawerConfig.drawSignalKeyBarPattern = true; - - // - // Recents ... - marketStructureDrawerConfig.drawRecentPatterns = false; - marketStructureDrawerConfig.drawFakeBreakedZone = false; - marketStructureDrawerConfig.drawRecentlyTestedZones = false; - marketStructureDrawerConfig.drawRecentlyBreakedZones = false; - - // - // XPV ... - marketStructureDrawerConfig.drawFIMAPVPivotsAnalysis = true; - marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisZones = true; - marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisTrends = true; - marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisPivots = true; - - // - // XSAR ... - marketStructureDrawerConfig.drawFIMASARPivotsAnalysis = false; - marketStructureDrawerConfig.drawFIMASARPivotsAnalysisZones = false; - marketStructureDrawerConfig.drawFIMASARPivotsAnalysisTrends = false; - marketStructureDrawerConfig.drawFIMASARPivotsAnalysisPivots = false; - - // - // XZigZag ... - marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysis = true; - marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisZones = true; - marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisTrends = false; - marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisPivots = false; - - // - // Analyse Market on Signalling Bar ... - fima1Signaller.poiDetector.AnalyseMarket( - bar, - marketStructure, - detectorConfig // - ); - - // - bar.Clean(); -} - // \ No newline at end of file diff --git a/Libraries/x-saherelm.x-trade.lib.mq5 b/Libraries/x-saherelm.x-trade.lib.mq5 index 7fef5402..3800b0dc 100644 --- a/Libraries/x-saherelm.x-trade.lib.mq5 +++ b/Libraries/x-saherelm.x-trade.lib.mq5 @@ -719,6 +719,7 @@ struct XTarget // // Props ... bool doRF; // Do RF on Target + double actingDistance; // Acting Distances double target; // Target Price for Actions double volumeMultiplier; // Volume Multiplier for Partial Close @@ -739,6 +740,7 @@ struct XTarget // target = 0; doRF = false; + actingDistance = 0; volumeMultiplier = 0; } @@ -5688,6 +5690,45 @@ void ApplyTargetsOnSignal( targets // ); + // + // Compare TP with Targets ... + int idx = IsLong(signal.type) + ? GetHighest(targets) + : GetLowest(targets); + has = IsValidIndex(idx); + if (has) + { + // + // Compare TP ... + has = IsLong(signal.type) + ? targets[idx].target > signal.tp + : targets[idx].target < signal.tp; + if (has) + { + // + XTarget tpTarget; + tpTarget = targets[idx]; + tpTarget.target = signal.tp; + signal.tp = targets[idx].target; + ArrayRemove( + targets, + idx, + 1 // + ); + AddRef( + tpTarget, + targets // + ); + } + + // + // Sort Targets ... + ApplySortOnTargets( + sortingDir, + targets // + ); + } + // Copy( targets, diff --git a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 index 184c9a5a..409da172 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -804,22 +804,6 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller ); } - // - CArrayObj *zoneObjs; - poiDrawer.DrawBoxes( - supports, - zoneObjs // - ); - poiDrawer.DrawBoxes( - resistances, - zoneObjs // - ); - poiDrawer.DrawBoxes( - structure.fvgs, - zoneObjs, - false // - ); - // // Check Affected Zone ... // Select a Support or Resistance ... @@ -878,6 +862,132 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // // Check Reversal FVGS ... + int idx = -1; + XTarget target; + XBoxZone targetZones[]; + int numberOfTargets = 3; + double actingDistance = 20; + double iValue = EMPTY_VALUE; + bool ignoreFirstTarget = true; + ENUM_X_DIRECTION targetsDir = Opposit(dir); + int count = ExtractByDirection( + targetZones, + structure.fvgs, + targetsDir // + ); + bool has = IsValidSize(count); + if (has) + { + // + // Calculate Value ... + double points = GetPoints(zone.symbol); + double zoneRange = zone.upper - zone.lower; + iValue = IsXBullish(dir) + ? (zone.upper + (zoneRange * defaultSignalR2R)) + : (zone.lower + (zoneRange * defaultSignalR2R)); + double defaultTarget = iValue; + + // + // Looping Back ... + for (int i = 0; i < numberOfTargets; i++) + { + // + // Detect Lowest Above Zone ... + if (IsXBullish(dir)) + { + // + idx = GetLowestAbove(iValue, targetZones); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + iValue = targetZones[idx].lower; + } + // + // Detect Highest below Zone ... + else if (IsXBearish(dir)) + { + // + idx = GetHighestBelow(iValue, targetZones); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + iValue = targetZones[idx].upper; + } + + // + // Validate Target Value ... + has = NotEmptyZero(iValue) && + iValue != defaultTarget; + if (has) + { + // + // Init Target ... + target.Clean(); + target.doRF = true; + target.target = iValue; + target.actingDistance = actingDistance; + has = target.IsValid(); + if (has) + { + // + // Add Target to Targets ... + AddRef( + target, + targets // + ); + } + target.Clean(); + } + } + + // + // Remove Nearest ... + has = ignoreFirstTarget && + HasChild(targets); + if (has) + { + // + ArrayRemove( + targets, + 0, + 1 // + ); + } + } + + // + // Cleanup Resources ... + target.Clean(); + XClean(targetZones); + } + + // + // TODO: Remove this ... + if (result) + { + // + CArrayObj *zoneObjs; + poiDrawer.DrawBoxes( + supports, + zoneObjs // + ); + poiDrawer.DrawBoxes( + resistances, + zoneObjs // + ); + poiDrawer.DrawBoxes( + structure.fvgs, + zoneObjs, + false // + ); } //