From a3016b0c6351ca3049e2c4330a85b57976ba401c Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Wed, 10 Sep 2025 21:02:38 +0330 Subject: [PATCH] last works ... --- Classes/x-saherelm.x-trade-manager.class.mq5 | 241 +++++++++++++------ Documents/BKP/tmp-trade_symbol.info.mq5 | 109 ++++++--- Experts/x-saherelm.xom1.ea.mq5 | 23 ++ Libraries/x-saherelm.x-trade.lib.mq5 | 174 +++++++++++++ XOM1EA/Classes/xom1ea.expert.class.mq5 | 34 ++- XOM1EA/Classes/xom1ea.signaller.class.mq5 | 52 +++- 6 files changed, 515 insertions(+), 118 deletions(-) diff --git a/Classes/x-saherelm.x-trade-manager.class.mq5 b/Classes/x-saherelm.x-trade-manager.class.mq5 index ca7691d7..2dc57078 100644 --- a/Classes/x-saherelm.x-trade-manager.class.mq5 +++ b/Classes/x-saherelm.x-trade-manager.class.mq5 @@ -299,7 +299,8 @@ class XCTradeManager : public XCBase iMaxAllowedPositions, iRestrictionsDescriptor // ); - if (has) { + if (has) + { AddOrUpdateSymbolConfiguration(iConfig); } @@ -377,8 +378,7 @@ class XCTradeManager : public XCBase { // // Handle Restrictions ... - // TODO: Complete this ... - // HandleRestrictions(); + HandleRestrictions(); // // Check Contains Trades for Managing ... @@ -715,39 +715,57 @@ class XCTradeManager : public XCBase } /** - * Check Specified Symbol is Active for - * Analysing or Open Trades ... + * Check Can Analyse Market based on Configurations ... + * + * @param symbol: Symbol + * @param period: Period + * @param time: Analysing Time + * + * @return ( bool ) */ - bool IsActiveSession(string symbol) + bool CanAnalyse( + string symbol, + ENUM_TIMEFRAMES period, + datetime time // + ) { // bool result = false; // - // Validate Args ... - result = IsValid(symbol); + // Finding Symbol Configuration Index ... + int idx = FindSymbolConfigurationIndex( + symbol, + period // + ); + + // + // If Not Exists ... + if (!IsValidIndex(idx)) + { + // + result = true; + return result; + } + + // + // If Exists ... + + // + // Check Session is Active ... + result = symbolTradeConfigs[idx].CanTrade(time); if (!result) { return result; } // - // TODO: Complete this ... - - // // - // // Check Symbol Session Exists or not ... - // int symbolSessionIDX = -1; - // bool isSymbolSessionExists = FindSymbolSession( - // symbolSessionIDX, - // symbol // - // ); - - // // - // // Chack Trade Session Validating ... - // if (isSymbolSessionExists) - // { - // result = sessions[symbolSessionIDX].CanTrade(); - // } + // Check Symbol Restrictions ... + result = symbolTradeConfigs[idx].IsRestricted(time); + if (!result) + { + return result; + } // return result; @@ -838,6 +856,29 @@ class XCTradeManager : public XCBase return result; } + /** + * Handle All Exists Symbol Configurations Restrictions ... + */ + void HandleRestrictions() + { + // + // Count Symbol Configurations ... + int count = ArraySize(symbolTradeConfigs); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + // Handle Restrictions ... + datetime cTime = TimeCurrent(); + for (int i = 0; i < count; i++) + { + symbolTradeConfigs[i].HandleRestrictions(cTime); + } + } + /** * Execute Specified Signal ... * @@ -1071,19 +1112,21 @@ class XCTradeManager : public XCBase HandleReportBalance(prefix); // - // Handle Symbol Info ... + // Handle Symbol Config ... - // // - // XTradeSymbolInfo iSymbolInfo; - - // // - // iSymbolInfo.profits = 1; - // iSymbolInfo.managedTPs = 1; - // iSymbolInfo.symbol = trades[idx].signal.symbol; - // iSymbolInfo.managedProfits = trades[idx].profit; - - // // - // AddOrUpdateSymbolInfo(iSymbolInfo); + // + int configIdx = FindSymbolConfigurationIndex( + trades[idx].symbol, + tardes[idx].period // + ); + isExists = IsValidIndex(configIdx); + if (isExists) + { + // + symbolTradeConfigs[configIdx].profits += 1; + symbolTradeConfigs[configIdx].managedTPs += 1; + symbolTradeConfigs[configIdx].managedProfits += trades[idx].profit; + } // RemoveTrade(idx); @@ -1138,27 +1181,34 @@ class XCTradeManager : public XCBase SaveLost(trades[idx]); } - // // - // XTradeSymbolInfo iSymbolInfo; + // + // Handle Symbol Config ... - // // - // if (isInProfit) - // { - // // - // iSymbolInfo.profits = 1; - // iSymbolInfo.managedTPs = 1; - // } - // else - // { - // // - // iSymbolInfo.losses = 1; - // iSymbolInfo.managedSLs = 1; - // } - // iSymbolInfo.symbol = trades[idx].signal.symbol; - // iSymbolInfo.managedProfits = trades[idx].profit; + // + int configIdx = FindSymbolConfigurationIndex( + trades[idx].symbol, + tardes[idx].period // + ); + isExists = IsValidIndex(configIdx); + if (isExists) + { + // + if (isInProfit) + { + // + symbolTradeConfigs[configIdx].profits += 1; + symbolTradeConfigs[configIdx].managedTPs += 1; + } + else + { + // + symbolTradeConfigs[configIdx].losses += 1; + symbolTradeConfigs[configIdx].managedSLs += 1; + } - // // - // AddOrUpdateSymbolInfo(iSymbolInfo); + // + symbolTradeConfigs[configIdx].managedProfits += trades[idx].profit; + } // RemoveTrade(idx); @@ -1219,29 +1269,33 @@ class XCTradeManager : public XCBase HandleReportBalance(prefix); // - // Handle Symbol Info ... + // Handle Symbol Config ... // - // XTradeSymbolInfo iSymbolInfo; + int configIdx = FindSymbolConfigurationIndex( + trades[idx].symbol, + tardes[idx].period // + ); + isExists = IsValidIndex(configIdx); + if (isExists) + { + // + if (isInProfit) + { + // + symbolTradeConfigs[configIdx].profits += 1; + symbolTradeConfigs[configIdx].managedTPs += 1; + } + else + { + // + symbolTradeConfigs[configIdx].losses += 1; + symbolTradeConfigs[configIdx].managedSLs += 1; + } - // // - // if (isInProfit) - // { - // // - // iSymbolInfo.profits = 1; - // iSymbolInfo.managedTPs = 1; - // } - // else - // { - // // - // iSymbolInfo.losses = 1; - // iSymbolInfo.managedSLs = 1; - // } - // iSymbolInfo.symbol = trades[idx].signal.symbol; - // iSymbolInfo.managedProfits = trades[idx].profit; - - // // - // AddOrUpdateSymbolInfo(iSymbolInfo); + // + symbolTradeConfigs[configIdx].managedProfits += trades[idx].profit; + } // RemoveTrade(idx); @@ -1884,6 +1938,43 @@ class XCTradeManager : public XCBase return result; } + // + int FindSymbolConfigurationIndex( + string symbol, + ENUM_TIMEFRAMES period // + ) + { + // + int result = -1; + + // + // Validate Args ... + if ( + !IsSpecifiedValid(symbol) || + !IsSpecifiedValid(period) || + !HasChild(symbolTradeConfigs)) + { + return result; + } + + // + int count = ArraySize(symbolTradeConfigs); + for (int i = 0; i < count; i++) + { + // + if (symbolTradeConfigs[i].symbol == symbol && + symbolTradeConfigs[i].period == period) + { + // + result = i; + break; + } + } + + // + return result; + } + // // Tools ... diff --git a/Documents/BKP/tmp-trade_symbol.info.mq5 b/Documents/BKP/tmp-trade_symbol.info.mq5 index f4d3da0c..ebc5440b 100644 --- a/Documents/BKP/tmp-trade_symbol.info.mq5 +++ b/Documents/BKP/tmp-trade_symbol.info.mq5 @@ -496,46 +496,46 @@ void HandleRestrictions() } } +// +bool SaveRestrictions(XTradeSymbolInfo &info) +{ // - bool SaveRestrictions(XTradeSymbolInfo &info) + bool result = false; + + // + if (!mSaveRestrictions) { - // - bool result = false; - - // - if (!mSaveRestrictions) - { - return result; - } - - // - result = info.IsValid(); - if (!result) - { - return result; - } - - // - string filePath = GetRestrictionsFilePath(info.symbol); - result = IsValid(filePath); - if (!result) - { - return result; - } - - // - string content = info.GetRestrictionDescription(restrictionsPeriod); - - // - result = collector.Append( - filePath, - content // - ); - - // return result; } + // + result = info.IsValid(); + if (!result) + { + return result; + } + + // + string filePath = GetRestrictionsFilePath(info.symbol); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + string content = info.GetRestrictionDescription(restrictionsPeriod); + + // + result = collector.Append( + filePath, + content // + ); + + // + return result; +} + // // Symbol Session ... @@ -914,6 +914,45 @@ bool Execute(XSignal &signal) return result; } + /** + * Check Specified Symbol is Active for + * Analysing or Open Trades ... + */ + bool IsActiveSession(string symbol) + { + // + bool result = false; + + // + // Validate Args ... + result = IsValid(symbol); + if (!result) + { + return result; + } + + // + // TODO: Complete this ... + + // // + // // Check Symbol Session Exists or not ... + // int symbolSessionIDX = -1; + // bool isSymbolSessionExists = FindSymbolSession( + // symbolSessionIDX, + // symbol // + // ); + + // // + // // Chack Trade Session Validating ... + // if (isSymbolSessionExists) + // { + // result = sessions[symbolSessionIDX].CanTrade(); + // } + + // + return result; + } + // string forceCloseAt; bool isForceCloseAtTime; diff --git a/Experts/x-saherelm.xom1.ea.mq5 b/Experts/x-saherelm.xom1.ea.mq5 index 6ff81e38..c2967a56 100644 --- a/Experts/x-saherelm.xom1.ea.mq5 +++ b/Experts/x-saherelm.xom1.ea.mq5 @@ -210,6 +210,7 @@ int OnInit() eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); + eaExpert.canAnalyseEventHandler = CanAnalyseEventTriggered; eaExpert.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); eaExpert.AddOnModifyPositionEventHandler(OnPositionModified); eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged); @@ -293,6 +294,28 @@ void OnChartEvent( // // Event Listeners ... +/** + * Handle CanAnalyse Event Triggered ... + * + * @param symbol: Symbol ... + * @param period: Period ... + * @param time: Analysing Time ... + * + * @return ( bool ) + */ +bool CanAnalyseEventTriggered( + string symbol, + ENUM_TIMEFRAMES period, + datetime time // +) +{ + return eaExpert.HandleCanAnalyseEventTriggered( + symbol, + period, + time // + ); +} + /** * Trigger OnSignal Event ... * diff --git a/Libraries/x-saherelm.x-trade.lib.mq5 b/Libraries/x-saherelm.x-trade.lib.mq5 index a5a86548..70397627 100644 --- a/Libraries/x-saherelm.x-trade.lib.mq5 +++ b/Libraries/x-saherelm.x-trade.lib.mq5 @@ -375,6 +375,56 @@ ENUM_XTRADE_RESTRICTION_PERIOD ToXRestrictionPeriod(string value) return result; } +// +int GetXRestrictionsPeriodSeconds(ENUM_XTRADE_RESTRICTION_PERIOD value) +{ + // + int result = 0; + + // + if (!HasRestrictions(value)) + { + return result; + } + + // + switch (value) + { + // + // None ... + case XTRADE_RESTRICATION_NONE: + result = 0; + break; + + // + // Hour ... + case XTRADE_RESTRICATION_HOURLY: + result = PeriodSeconds(PERIOD_H1); + break; + + // + // Dayly ... + case XTRADE_RESTRICATION_DAILY: + result = PeriodSeconds(PERIOD_D1); + break; + + // + // Weekly ... + case XTRADE_RESTRICATION_WEEKLY: + result = PeriodSeconds(PERIOD_W1); + break; + + // + // Monthly ... + case XTRADE_RESTRICATION_MONTHLY: + result = PeriodSeconds(PERIOD_M1); + break; + } + + // + return result; +} + /** * Check a Value Has Trade Restrictions or not ... * @@ -3049,6 +3099,68 @@ struct XSymbolTradeConfig return result; } + // + // Checking Restrictions ... + bool IsRestricted(datetime time = NULL) + { + // + bool result = false; + + // + // Normalize Time ... + time = NormalizeTime(time); + + // + // Check Has Restrictions ... + bool has = HasRestrictions(restrictionsPeriod); + result = !has; + if (result) + { + return result; + } + + // + // Check Restrictions Time ... + has = IsSpecifiedValid(managedStart) && + time <= managedStart; + result = !has; + if (result) + { + return result; + } + + // + // Validate Restrictions Timing ... + // Check Restrictions ... + + // + bool isTPAllowed = maxAllowedTPs == 0 + ? true + : managedTPs < maxAllowedTPs; + bool isSLAllowed = maxAllowedSLs == 0 + ? true + : managedSLs < maxAllowedSLs; + bool isTradeAllowed = maxAllowedTrades == 0 + ? true + : managedTrades < maxAllowedTrades; + + // + result = isTPAllowed && + isSLAllowed && + isTradeAllowed; + if (result) + { + return result; + } + + // + // Check Restrictions Reset ... + HandleRestrictions(); + + // + return result; + } + // // Parse Sessions ... void ParseSessions(string descriptor) @@ -3244,6 +3356,61 @@ struct XSymbolTradeConfig restrictionsPeriod = XTRADE_RESTRICATION_NONE; } + // + // Handle Restrictions ... + void HandleRestrictions(datetime time = NULL) + { + // + // Normalize Time ... + time = NormalizeTime(time); + + // + // Check Restrictions Requirements ... + bool has = HasRestrictions(restrictionsPeriod) && + restrictionsPeriodMultiplier >= 1; + if (!has) + { + return; + } + + // + // Check Restrictions Start ... + has = IsSpecifiedValid(managedStart); + if (!has) + { + managedStart = time; + } + + // + // Calculating Expiration Date based on Config ... + int expiredDelay = restrictionsPeriodMultiplier * GetXRestrictionsPeriodSeconds(restrictionsPeriod); + datetime expiredDate = (datetime)(TimeToSeconds(managedStart) + expiredDelay); + + // + // Check Expiration ... + has = time >= expiredDate; + if (!has) + { + return; + } + + // + ResetRestrictions(); + } + + // + // Reset Restrictions ... + void ResetRestrictions() + { + // + managedSLs = 0; + managedTPs = 0; + managedTrades = 0; + managedBalance = 0; + managedProfits = 0; + managedStart = TimeCurrent(); + } + // }; @@ -3576,6 +3743,13 @@ struct XTradeInfo // typedef void (*TOnSignal)(XSignal &signal); +// +typedef bool (*TCanAnalyse)( + string _symbol, + ENUM_TIMEFRAMES _period, + datetime _time // +); + // typedef void (*TOnDealsChanged)(int count); diff --git a/XOM1EA/Classes/xom1ea.expert.class.mq5 b/XOM1EA/Classes/xom1ea.expert.class.mq5 index 230d379a..6cc7a96c 100644 --- a/XOM1EA/Classes/xom1ea.expert.class.mq5 +++ b/XOM1EA/Classes/xom1ea.expert.class.mq5 @@ -113,6 +113,9 @@ class XCXOM1EAExpert : public XCBase // // Tools / Actions / Handlers ... + // + TCanAnalyse canAnalyseEventHandler; + // // Signal Event Handlers ... @@ -587,6 +590,10 @@ class XCXOM1EAExpert : public XCBase } } + // + // Attach Can Analyse Event Handler ... + iDZoneSignaller.canAnalyseEventListener = canAnalyseEventHandler; + // // Register Signaller ... Add( @@ -635,7 +642,17 @@ class XCXOM1EAExpert : public XCBase eaTimeTracker.Clean(); // - Clean(eaSignallers); + SpecifiedClean(eaSignallers); + SpecifiedClean(mOnSignalEventHandlers); + SpecifiedClean(mOnModifyEventHandlers); + SpecifiedClean(mStopLossEventHandlers); + SpecifiedClean(mTakeProfitEventHandlers); + SpecifiedClean(mOnForceCloseEventHandlers); + SpecifiedClean(mDealsChangedEventHandlers); + SpecifiedClean(mOrdersChangedEventHandlers); + SpecifiedClean(mOnPartialCloseEventHandlers); + SpecifiedClean(mPositionsChangedEventHandlers); + SpecifiedClean(mTradeStateChangedEventHandlers); // string message = "DeInitialized Successfully ..."; @@ -707,6 +724,21 @@ class XCXOM1EAExpert : public XCBase eaTradeManager.HandleSignal(signal); } + // + // Check Can Analyse ... + bool HandleCanAnalyseEventTriggered( + string symbol, + ENUM_TIMEFRAMES period, + datetime time // + ) + { + return eaTradeManager.CanAnalyse( + symbol, + period, + time // + ); + } + // // Trade Event Handlers ... diff --git a/XOM1EA/Classes/xom1ea.signaller.class.mq5 b/XOM1EA/Classes/xom1ea.signaller.class.mq5 index b07c309d..416be15d 100644 --- a/XOM1EA/Classes/xom1ea.signaller.class.mq5 +++ b/XOM1EA/Classes/xom1ea.signaller.class.mq5 @@ -70,13 +70,14 @@ class XCXOM1SignallerBase public: // // Props ... - string name; // Name ... - string symbol; // Symbol ... - XOM1Zone zones[]; // Detected Zones ... - XOM1Inputs inputs; // Indicator Inputs ... - ENUM_TIMEFRAMES period; // Period ... - XOM1SignallerConfig config; // Configuration ... - XCXOM1POIDrawer drawer; // POI Drawer ... + string name; // Name ... + string symbol; // Symbol ... + XOM1Zone zones[]; // Detected Zones ... + XOM1Inputs inputs; // Indicator Inputs ... + ENUM_TIMEFRAMES period; // Period ... + XCXOM1POIDrawer drawer; // POI Drawer ... + XOM1SignallerConfig config; // Configuration ... + TCanAnalyse canAnalyseEventListener; // CanAnalyse Event Listener ... // // Constructor ... @@ -222,6 +223,14 @@ class XCXOM1SignallerBase return; } + // + // Check Process Permissions ... + has = CanAnalyse(symbol, period, cBarTime); + if (!has) + { + return; + } + // // Check if new Bar, Reset Processed Ticks Count ... isNewBar = cBarTime > mLastCheckedBarTime; @@ -571,6 +580,35 @@ class XCXOM1SignallerBase int mProcessedTicksCount; // Prcoessed Ticks Count ... datetime mLastCheckedBarTime; // Last Checked Bar Time ... + // + bool CanAnalyse( + string _symbol, + ENUM_TIMEFRAMES _period, + datetime time // + ) + { + // + bool result = false; + + // + if (canAnalyseEventListener != NULL) + { + // + result = canAnalyseEventListener( + _symbol, + _period, + time // + ); + } + else + { + result = true; + } + + // + return result; + } + /** * Handle New Bar's Process ... *