diff --git a/Classes/x-saherelm.x-trade-manager.class.mq5 b/Classes/x-saherelm.x-trade-manager.class.mq5 index 32ea0a25..114b2e5b 100644 --- a/Classes/x-saherelm.x-trade-manager.class.mq5 +++ b/Classes/x-saherelm.x-trade-manager.class.mq5 @@ -66,16 +66,6 @@ class XCTradeManager : public XCBase allowLongs = true; allowShorts = true; - // - forceCloseAt = NULL; - isForceCloseAtTime = false; - - // - maxAllowedTPs = 0; - maxAllowedSLs = 0; - maxAllowedTrades = 0; - restrictionsPeriod = XTRADE_RESTRICATION_NONE; - // reportTrades = true; reportSignals = true; @@ -187,87 +177,143 @@ class XCTradeManager : public XCBase // Setter(s) ... // - void SetForceCloseTradesAt( - string _forceCloseAt // - ) - { - forceCloseAt = _forceCloseAt; - } - - // - void SetTradeSession( - string symbol, - string start, - string end, - string name = NULL // - ) + void SetSymbolConfigurations(string symbolConfiguration) { // - // Validate Args ... - bool has = IsValid(end) && - IsValid(start) && - IsValid(symbol); + int count = 0; + bool has = false; + + // + // If Not Provided ... + has = IsSpecifiedValid(symbolConfiguration); if (!has) { + // + AddDefaultSymbolConfiguration(); return; } // - // Create Session ... - - // - XTradeSession session; - - // - session.end = end; - session.name = name; - session.start = start; - - // - int sessionIDX = -1; - has = FindSymbolSession( - sessionIDX, - symbol // + // Try to Parse Data ... + string symbolData[]; + count = SplitContent( + symbolData, + symbolConfiguration, + "]" // ); - - // + has = IsValidSize(count); if (!has) { // - // Add New Symbol Session ... + AddDefaultSymbolConfiguration(); // - XSymbolSessions iSymbolSession; - iSymbolSession.symbol = symbol; - - // - AddTradingSession( - session, - iSymbolSession // - ); - - // - AddRef( - iSymbolSession, - sessions // - ); - - // - iSymbolSession.Clean(); + SpecifiedClean(symbolData); + return; } - else + + // + // Loop through Exists Symbol Data's ... + for (int i = 0; i < count; i++) { // - // Update Trading Sessions of Exists Symbol Session ... - AddTradingSession( - session, - sessions[sessionIDX] // + string iData = symbolData[i]; + + // + // Extract Data Parts ... + string iParts[]; + int iPartsCount = SplitContent( + iParts, + iData, + "|" // ); + has = IsValidSize(iPartsCount); + if (has) + { + // + // Determines Required Parts ... + bool hasSymbol = iPartsCount >= 1; + bool hasPeriod = iPartsCount >= 2; + bool hasSessionsDescriptor = iPartsCount >= 3; + bool hasMaxAllowedSpred = iPartsCount >= 4; + bool hasMaxAllowedPositios = iPartsCount >= 5; + bool hasRestrictionDescriptor = iPartsCount >= 6; + + // + // Extract Symbol ... + string iSymbol = + hasSymbol + ? iParts[0] + : _Symbol; + iSymbol = EscapeString(iSymbol); + iSymbol = NormalizeSymbol(iSymbol); + + // + // Extract Period ... + ENUM_TIMEFRAMES iPeriod = + hasPeriod + ? ToPeriod(EscapeString(iParts[1])) + : _Period; + iPeriod = NormalizePeriod(iPeriod); + + // + // Extract Max Allowed Sspread ... + double iMaxAllowedSpread = + hasMaxAllowedSpred + ? (double)(EscapeString(iParts[3])) + : 25; + + // + // Extract Max Allowedd Positions ... + int iMaxAllowedPositions = + hasMaxAllowedPositios + ? (int)(EscapeString(iParts[4])) + : 5; + + // + // Extract Sessions Descriptor ... + string iSessionsDescriptor = + hasSessionsDescriptor + ? iParts[2] + : ""; + iSessionsDescriptor = EscapeString(iSessionsDescriptor); + + // + // Extract Restrictions Descriptor ... + string iRestrictionsDescriptor = + hasRestrictionDescriptor + ? iParts[5] + : ""; + iRestrictionsDescriptor = EscapeString(iRestrictionsDescriptor); + } + + // + // Cleanup Resources ... + SpecifiedClean(iParts); } // // Cleanup Resources ... - session.Clean(); + SpecifiedClean(symbolData); + } + + // + int FillSymbolConfigurations(XSymbolTradeConfig &dest[]) + { + // + SpecifiedClean(dest); + + // + Copy( + symbolTradeConfigs, + dest // + ); + + // + int result = ArraySize(dest); + + // + return result; } // @@ -300,27 +346,6 @@ class XCTradeManager : public XCBase allowShorts = _allowShorts; } - // - void SetTradeRestrictions( - ENUM_XTRADE_RESTRICTION_PERIOD _period, - int _maxAllowedTPs, - int _maxAllowedSLs, - int _maxAllowedTrades // - ) - { - // - // Normalizing Args ... - _maxAllowedTPs = NormalizeInt(_maxAllowedTPs, 0); - _maxAllowedSLs = NormalizeInt(_maxAllowedSLs, 0); - _maxAllowedTrades = NormalizeInt(_maxAllowedTrades, 0); - - // - restrictionsPeriod = _period; - maxAllowedTPs = _maxAllowedTPs; - maxAllowedSLs = _maxAllowedSLs; - maxAllowedTrades = _maxAllowedTrades; - } - // // Tools and Helpers ... @@ -331,7 +356,8 @@ class XCTradeManager : public XCBase { // // Handle Restrictions ... - HandleRestrictions(); + // TODO: Complete this ... + // HandleRestrictions(); // // Check Contains Trades for Managing ... @@ -482,26 +508,28 @@ class XCTradeManager : public XCBase // Do Collection Protectiong ... // - // Check Force Close ... - if (IsValid(forceCloseAt)) - { - // - datetime forceCloseTime = ParseDateTimeFromTimeString(forceCloseAt); - bool canForceClose = IsTimeInRange( - TimeCurrent(), - forceCloseTime // - ) && - !isForceCloseAtTime; - if (canForceClose) - { - // - isForceCloseAtTime = HandleForceCloseTrades(ownPosition); + // TODO: Complete this ... + // // + // // Check Force Close ... + // if (IsValid(forceCloseAt)) + // { + // // + // datetime forceCloseTime = ParseDateTimeFromTimeString(forceCloseAt); + // bool canForceClose = IsTimeInRange( + // TimeCurrent(), + // forceCloseTime // + // ) && + // !isForceCloseAtTime; + // if (canForceClose) + // { + // // + // isForceCloseAtTime = HandleForceCloseTrades(ownPosition); - // - // Prevent Moving Forward ... - return; - } - } + // // + // // Prevent Moving Forward ... + // return; + // } + // } // // Do Signle Protections ... @@ -683,19 +711,22 @@ class XCTradeManager : public XCBase } // - // Check Symbol Session Exists or not ... - int symbolSessionIDX = -1; - bool isSymbolSessionExists = FindSymbolSession( - symbolSessionIDX, - symbol // - ); + // TODO: Complete this ... - // - // Chack Trade Session Validating ... - if (isSymbolSessionExists) - { - result = sessions[symbolSessionIDX].CanTrade(); - } + // // + // // 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; @@ -780,75 +811,7 @@ class XCTradeManager : public XCBase } // - // Check Symbol Info Exists or not ... - int symbolInfoIDX = -1; - bool isSymbolInfoExists = FindSymbolIndex( - symbolInfoIDX, - signal.symbol // - ); - - // - // Check Symbol Session Exists or not ... - int symbolSessionIDX = -1; - bool isSymbolSessionExists = FindSymbolSession( - symbolSessionIDX, - signal.symbol // - ); - - // - // Chack Trade Session Validating ... - if (isSymbolSessionExists) - { - // - result = sessions[symbolSessionIDX].CanTrade(); - if (!result) - { - // - executionResult = X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED; - - // - return result; - } - } - - // - // Check Trade Permissions Based on SL(s) Count ... - bool hasRestrictions = restrictionsPeriod != XTRADE_RESTRICATION_NONE; - if (hasRestrictions) - { - // - // Only Can Check Restrictions when - // Symbol Info Exists ... - if (isSymbolInfoExists) - { - // - bool isTPAllowed = maxAllowedTPs == 0 - ? true - : symbols[symbolInfoIDX].managedTPs < maxAllowedTPs; - bool isSLAllowed = maxAllowedSLs == 0 - ? true - : symbols[symbolInfoIDX].managedSLs < maxAllowedSLs; - bool isTradeAllowed = maxAllowedTrades == 0 - ? true - : symbols[symbolInfoIDX].managedTrades < maxAllowedTrades; - - // - result = isTPAllowed && - isSLAllowed && - isTradeAllowed; - } - - // - // Report Error ... - if (!result) - { - // - executionResult = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; - - // - return result; - } - } + // TODO: Complete this ... // return result; @@ -930,39 +893,7 @@ class XCTradeManager : public XCBase if (result) { // - // Create Symbol Info Struct ... - XTradeSymbolInfo iSymbolInfo; - - // - iSymbolInfo.trades = 1; - iSymbolInfo.managedTrades = 1; - iSymbolInfo.symbol = signal.symbol; - - // - bool isLong = IsLong(signal.type); - if (isLong) - { - iSymbolInfo.longs = 1; - } - else - { - iSymbolInfo.shorts = 1; - } - - // - // Fill Balance for Restrications ... - bool hasRestrictions = HasRestrictions(restrictionsPeriod); - if (hasRestrictions) - { - // - // Read Balance ... - double balance = trader.mAccount.GetBalance(); - iSymbolInfo.managedBalance = balance; - iSymbolInfo.managedStart = TimeCurrent(); - } - - // - AddOrUpdateSymbolInfo(iSymbolInfo); + // TODO: Complete this ... // // Create Trade Struct ... @@ -1063,7 +994,8 @@ class XCTradeManager : public XCBase signal, signalExecutionResult // ); - if (canExecute) { + if (canExecute) + { bool isExecuted = Execute(signal); } @@ -1120,17 +1052,17 @@ class XCTradeManager : public XCBase // // Handle Symbol Info ... - // - XTradeSymbolInfo iSymbolInfo; + // // + // XTradeSymbolInfo iSymbolInfo; - // - iSymbolInfo.profits = 1; - iSymbolInfo.managedTPs = 1; - iSymbolInfo.symbol = trades[idx].signal.symbol; - iSymbolInfo.managedProfits = trades[idx].profit; + // // + // iSymbolInfo.profits = 1; + // iSymbolInfo.managedTPs = 1; + // iSymbolInfo.symbol = trades[idx].signal.symbol; + // iSymbolInfo.managedProfits = trades[idx].profit; - // - AddOrUpdateSymbolInfo(iSymbolInfo); + // // + // AddOrUpdateSymbolInfo(iSymbolInfo); // RemoveTrade(idx); @@ -1185,27 +1117,27 @@ class XCTradeManager : public XCBase SaveLost(trades[idx]); } - // - XTradeSymbolInfo iSymbolInfo; + // // + // XTradeSymbolInfo iSymbolInfo; - // - 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; + // // + // 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); + // // + // AddOrUpdateSymbolInfo(iSymbolInfo); // RemoveTrade(idx); @@ -1269,26 +1201,26 @@ class XCTradeManager : public XCBase // Handle Symbol Info ... // - XTradeSymbolInfo iSymbolInfo; + // XTradeSymbolInfo iSymbolInfo; - // - 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; + // // + // 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); + // // + // AddOrUpdateSymbolInfo(iSymbolInfo); // RemoveTrade(idx); @@ -1812,384 +1744,6 @@ class XCTradeManager : public XCBase return result; } - // - bool SaveRestrictions(XTradeSymbolInfo &info) - { - // - 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; - } - - // - // Symbol Info ... - - // - bool FindSymbolIndex( - int &index, - XTradeSymbolInfo &item // - ) - { - // - bool result = false; - - // - index = -1; - - // - result = item.IsValid(); - if (!result) - { - return result; - } - - // - result = HasChild(symbols); - if (!result) - { - return result; - } - - // - index = FindIndex( - item, - symbols // - ); - - // - result = IsValidIndex(index); - - // - return result; - } - - // - bool FindSymbolIndex( - int &index, - string symbol // - ) - { - // - bool result = false; - - // - index = -1; - - // - result = IsValid(symbol) && - HasChild(symbols); - if (!result) - { - return result; - } - - // - int count = ArraySize(symbols); - for (int i = 0; i < count; i++) - { - // - result = symbols[i].symbol == symbol; - if (result) - { - // - index = i; - break; - } - } - - // - result = IsValidIndex(index); - - // - return result; - } - - // - void AddOrUpdateSymbolInfo(XTradeSymbolInfo &item) - { - // - bool has = item.IsValid(); - if (!has) - { - return; - } - - // - int index = -1; - bool isExists = FindSymbolIndex( - index, - item // - ); - if (!isExists) - { - // - AddRef( - item, - symbols // - ); - } - else - { - // - symbols[index].longs += item.longs; - symbols[index].shorts += item.shorts; - symbols[index].trades += item.trades; - symbols[index].losses += item.losses; - symbols[index].profits += item.profits; - symbols[index].managedSLs += item.managedSLs; - symbols[index].managedTPs += item.managedTPs; - symbols[index].managedTrades += item.managedTrades; - symbols[index].managedProfits += item.managedProfits; - - // - // Handle Remove on Managed SL based On Managed TP ... - if (item.managedTPs > 0) - { - // - symbols[index].managedSLs -= item.managedTPs; - if (symbols[index].managedSLs < 0) - { - symbols[index].managedSLs = 0; - } - } - - // - // Handle Remove on Managed TP based On Managed SL ... - if (item.managedSLs > 0) - { - // - symbols[index].managedTPs -= item.managedSLs; - if (symbols[index].managedTPs < 0) - { - symbols[index].managedTPs = 0; - } - } - } - } - - // - void ResetSymbolsRestrictions() - { - // - bool has = HasChild(symbols); - if (has) - { - // - string prefix = "Protector: "; - - // - datetime start = TimeCurrent(); - double balance = trader.mAccount.GetBalance(); - bool hasRestrictions = HasRestrictions(restrictionsPeriod); - if (!hasRestrictions) - { - // - balance = 0; - start = NULL; - } - - // - int count = ArraySize(symbols); - for (int i = 0; i < count; i++) - { - // - XTradeSymbolInfo iInfo = symbols[i]; - if (reportRestrictions) - { - // - string message = iInfo.GetRestrictionDescription(restrictionsPeriod); - alert.SendAlert(message); - } - SaveRestrictions(iInfo); - - // - symbols[i].managedSLs = 0; - symbols[i].managedTPs = 0; - symbols[i].managedTrades = 0; - symbols[i].managedProfits = 0; - symbols[i].managedStart = start; - symbols[i].managedBalance = balance; - - // - iInfo.Clean(); - } - - // - string message = prefix + "Reset Symbols Restrictions"; - HandleReportProtector(message); - } - } - - // - void HandleRestrictions() - { - // - bool isNewDay = timeTracker.IsNewDay(); - bool isNewHour = timeTracker.IsNewHour(); - bool isNewWeek = timeTracker.IsNewWeek(); - bool isNewMonth = timeTracker.IsNewMonth(); - - // - // Reset Force Closed Flag on new Day Starts ... - if (isNewDay) - { - isForceCloseAtTime = false; - } - - // - bool canResetRestrictions = - ( - // - // Hourly ... - (isNewHour && - restrictionsPeriod == XTRADE_RESTRICATION_HOURLY) - // - || - // - // Daily ... - (isNewDay && - restrictionsPeriod == XTRADE_RESTRICATION_DAILY) - // - || - // - // Weekly ... - (isNewWeek && - restrictionsPeriod == XTRADE_RESTRICATION_WEEKLY) - // - || - // - // Monthly ... - (isNewMonth && - restrictionsPeriod == XTRADE_RESTRICATION_MONTHLY) - // - ) - // - ; - if (canResetRestrictions) - { - ResetSymbolsRestrictions(); - } - } - - // - // Symbol Session ... - - // - bool FindSymbolSession( - int &index, - string symbol // - ) - { - // - bool result = false; - - // - index = -1; - - // - result = IsValid(symbol) && - HasChild(sessions); - if (!result) - { - return result; - } - - // - int count = ArraySize(sessions); - for (int i = 0; i < count; i++) - { - // - result = sessions[i].symbol == symbol; - if (result) - { - // - index = i; - break; - } - } - - // - result = IsValidIndex(index); - - // - return result; - } - - // - void AddTradingSession( - XTradeSession &session, - XSymbolSessions &symbolSession // - ) - { - // - bool has = session.IsValid() && - symbolSession.IsValid(); - if (!has) - { - return; - } - - // - // Check Session Exists in Symbol Session ... - bool isExists = false; - if (HasChild(symbolSession.sessions)) - { - // - int count = ArraySize(symbolSession.sessions); - for (int i = 0; i < count; i++) - { - // - isExists = symbolSession.sessions[i].end == session.end && - symbolSession.sessions[i].start == session.start; - if (isExists) - { - break; - } - } - } - - // - if (!isExists) - { - // - AddRef( - session, - symbolSession.sessions // - ); - } - } - // // Private ... private: @@ -2204,16 +1758,6 @@ class XCTradeManager : public XCBase bool allowLongs; bool allowShorts; - // - string forceCloseAt; - bool isForceCloseAtTime; - - // - int maxAllowedTPs; - int maxAllowedSLs; - int maxAllowedTrades; - ENUM_XTRADE_RESTRICTION_PERIOD restrictionsPeriod; - // bool mSaveWins; bool mSaveLosts; @@ -2230,6 +1774,134 @@ class XCTradeManager : public XCBase // XTradeInfo trades[]; - XTradeSymbolInfo symbols[]; - XSymbolSessions sessions[]; + XSymbolTradeConfig symbolTradeConfigs[]; + + // + void AddOrUpdateSymbolConfiguration(XSymbolTradeConfig &config) + { + // + // Check Validation ... + bool has = config.IsValid(); + if (!has) + { + return; + } + + // + // Check Index ... + int idx = FindSymbolConfigurationIndex(config); + has = IsValidIndex(idx); + if (has) + { + // + // Update Exists ... + symbolTradeConfigs[idx] = config; + } + else + { + // + // Add New ... + AddRef( + config, + symbolTradeConfigs // + ); + } + } + + // + void AddDefaultSymbolConfiguration() + { + // + // Define new Configuration ... + XSymbolTradeConfig iConfig; + + // + // Check Initialization ... + bool has = iConfig.Init( + _Symbol, + _Period // + ); + + // + // Add Or Update ... + if (has) + { + AddOrUpdateSymbolConfiguration(iConfig); + } + + // + // Clean Resources ... + iConfig.Clean(); + } + + // + int FindSymbolConfigurationIndex(XSymbolTradeConfig &config) + { + // + int result = -1; + + // + if (!config.IsValid() || !SpecifiedHasChild(symbolTradeConfigs)) + { + return result; + } + + // + int count = ArraySize(symbolTradeConfigs); + for (int i = 0; i < count; i++) + { + // + if (symbolTradeConfigs[i].IsSame(config)) + { + // + result = i; + break; + } + } + + // + return result; + } + + // + // Tools ... + + string EscapeString(string value) + { + // + string result = value; + + // + if (!IsSpecifiedValid(value)) + { + return result; + } + + // + StringReplace( + result, + "[", + "" // + ); + + // + StringReplace( + result, + "]", + "" // + ); + + // + StringReplace( + result, + "|", + "" // + ); + + // + result = Trim(result); + + // + return result; + } }; \ No newline at end of file diff --git a/Documents/BKP/tmp-trade_symbol.info.mq5 b/Documents/BKP/tmp-trade_symbol.info.mq5 index c60afe97..f4d3da0c 100644 --- a/Documents/BKP/tmp-trade_symbol.info.mq5 +++ b/Documents/BKP/tmp-trade_symbol.info.mq5 @@ -1,8 +1,8 @@ ` -// -// an Structure for Holds an Specified Symbols -// Positions Info ... -struct XTradeSymbolInfo + // + // an Structure for Holds an Specified Symbols + // Positions Info ... + struct XTradeSymbolInfo { // // Properties ... @@ -141,3 +141,798 @@ struct XTradeSymbolInfo return result; } }; + +// +void SetForceCloseTradesAt( + string _forceCloseAt // +) +{ + forceCloseAt = _forceCloseAt; +} + +// +void SetTradeSession( + string symbol, + string start, + string end, + string name = NULL // +) +{ + // + // Validate Args ... + bool has = IsValid(end) && + IsValid(start) && + IsValid(symbol); + if (!has) + { + return; + } + + // + // Create Session ... + + // + XTradeSession session; + + // + session.end = end; + session.name = name; + session.start = start; + + // + int sessionIDX = -1; + has = FindSymbolSession( + sessionIDX, + symbol // + ); + + // + if (!has) + { + // + // Add New Symbol Session ... + + // + XSymbolSessions iSymbolSession; + iSymbolSession.symbol = symbol; + + // + AddTradingSession( + session, + iSymbolSession // + ); + + // + AddRef( + iSymbolSession, + sessions // + ); + + // + iSymbolSession.Clean(); + } + else + { + // + // Update Trading Sessions of Exists Symbol Session ... + AddTradingSession( + session, + sessions[sessionIDX] // + ); + } + + // + // Cleanup Resources ... + session.Clean(); +} + +// +void SetTradeRestrictions( + ENUM_XTRADE_RESTRICTION_PERIOD _period, + int _maxAllowedTPs, + int _maxAllowedSLs, + int _maxAllowedTrades // +) +{ + // + // Normalizing Args ... + _maxAllowedTPs = NormalizeInt(_maxAllowedTPs, 0); + _maxAllowedSLs = NormalizeInt(_maxAllowedSLs, 0); + _maxAllowedTrades = NormalizeInt(_maxAllowedTrades, 0); + + // + restrictionsPeriod = _period; + maxAllowedTPs = _maxAllowedTPs; + maxAllowedSLs = _maxAllowedSLs; + maxAllowedTrades = _maxAllowedTrades; +} +// +// Symbol Info ... + +// +bool FindSymbolIndex( + int &index, + XTradeSymbolInfo &item // +) +{ + // + bool result = false; + + // + index = -1; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + result = HasChild(symbols); + if (!result) + { + return result; + } + + // + index = FindIndex( + item, + symbols // + ); + + // + result = IsValidIndex(index); + + // + return result; +} + +// +bool FindSymbolIndex( + int &index, + string symbol // +) +{ + // + bool result = false; + + // + index = -1; + + // + result = IsValid(symbol) && + HasChild(symbols); + if (!result) + { + return result; + } + + // + int count = ArraySize(symbols); + for (int i = 0; i < count; i++) + { + // + result = symbols[i].symbol == symbol; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +// +void AddOrUpdateSymbolInfo(XTradeSymbolInfo &item) +{ + // + bool has = item.IsValid(); + if (!has) + { + return; + } + + // + int index = -1; + bool isExists = FindSymbolIndex( + index, + item // + ); + if (!isExists) + { + // + AddRef( + item, + symbols // + ); + } + else + { + // + symbols[index].longs += item.longs; + symbols[index].shorts += item.shorts; + symbols[index].trades += item.trades; + symbols[index].losses += item.losses; + symbols[index].profits += item.profits; + symbols[index].managedSLs += item.managedSLs; + symbols[index].managedTPs += item.managedTPs; + symbols[index].managedTrades += item.managedTrades; + symbols[index].managedProfits += item.managedProfits; + + // + // Handle Remove on Managed SL based On Managed TP ... + if (item.managedTPs > 0) + { + // + symbols[index].managedSLs -= item.managedTPs; + if (symbols[index].managedSLs < 0) + { + symbols[index].managedSLs = 0; + } + } + + // + // Handle Remove on Managed TP based On Managed SL ... + if (item.managedSLs > 0) + { + // + symbols[index].managedTPs -= item.managedSLs; + if (symbols[index].managedTPs < 0) + { + symbols[index].managedTPs = 0; + } + } + } +} + +// +void ResetSymbolsRestrictions() +{ + // + bool has = HasChild(symbols); + if (has) + { + // + string prefix = "Protector: "; + + // + datetime start = TimeCurrent(); + double balance = trader.mAccount.GetBalance(); + bool hasRestrictions = HasRestrictions(restrictionsPeriod); + if (!hasRestrictions) + { + // + balance = 0; + start = NULL; + } + + // + int count = ArraySize(symbols); + for (int i = 0; i < count; i++) + { + // + XTradeSymbolInfo iInfo = symbols[i]; + if (reportRestrictions) + { + // + string message = iInfo.GetRestrictionDescription(restrictionsPeriod); + alert.SendAlert(message); + } + SaveRestrictions(iInfo); + + // + symbols[i].managedSLs = 0; + symbols[i].managedTPs = 0; + symbols[i].managedTrades = 0; + symbols[i].managedProfits = 0; + symbols[i].managedStart = start; + symbols[i].managedBalance = balance; + + // + iInfo.Clean(); + } + + // + string message = prefix + "Reset Symbols Restrictions"; + HandleReportProtector(message); + } +} + +// +void HandleRestrictions() +{ + // + bool isNewDay = timeTracker.IsNewDay(); + bool isNewHour = timeTracker.IsNewHour(); + bool isNewWeek = timeTracker.IsNewWeek(); + bool isNewMonth = timeTracker.IsNewMonth(); + + // + // Reset Force Closed Flag on new Day Starts ... + if (isNewDay) + { + isForceCloseAtTime = false; + } + + // + bool canResetRestrictions = + ( + // + // Hourly ... + (isNewHour && + restrictionsPeriod == XTRADE_RESTRICATION_HOURLY) + // + || + // + // Daily ... + (isNewDay && + restrictionsPeriod == XTRADE_RESTRICATION_DAILY) + // + || + // + // Weekly ... + (isNewWeek && + restrictionsPeriod == XTRADE_RESTRICATION_WEEKLY) + // + || + // + // Monthly ... + (isNewMonth && + restrictionsPeriod == XTRADE_RESTRICATION_MONTHLY) + // + ) + // + ; + if (canResetRestrictions) + { + ResetSymbolsRestrictions(); + } +} + + // + bool SaveRestrictions(XTradeSymbolInfo &info) + { + // + 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; + } + +// +// Symbol Session ... + +// +bool FindSymbolSession( + int &index, + string symbol // +) +{ + // + bool result = false; + + // + index = -1; + + // + result = IsValid(symbol) && + HasChild(sessions); + if (!result) + { + return result; + } + + // + int count = ArraySize(sessions); + for (int i = 0; i < count; i++) + { + // + result = sessions[i].symbol == symbol; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +// +void AddTradingSession( + XTradeSession &session, + XSymbolSessions &symbolSession // +) +{ + // + bool has = session.IsValid() && + symbolSession.IsValid(); + if (!has) + { + return; + } + + // + // Check Session Exists in Symbol Session ... + bool isExists = false; + if (HasChild(symbolSession.sessions)) + { + // + int count = ArraySize(symbolSession.sessions); + for (int i = 0; i < count; i++) + { + // + isExists = symbolSession.sessions[i].end == session.end && + symbolSession.sessions[i].start == session.start; + if (isExists) + { + break; + } + } + } + + // + if (!isExists) + { + // + AddRef( + session, + symbolSession.sessions // + ); + } +} + +/** + * Check Signal Execution Conditions ... + * + * @param signal: XSignal instance reference ... + * @param executionResult: ENUM_X_SIGNAL_EXECUTION_RESULT member reference ... + * + * @return ( bool ) + */ +bool CheckSignal( + XSignal &signal, + ENUM_X_SIGNAL_EXECUTION_RESULT &executionResult // +) +{ + // + bool result = false; + + // + // Cleanup ... + executionResult = X_SIGNAL_EXECUTION_UNKNOWN; + + // + // Validate Signal ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + // Reporting Signal ... + if (reportSignals) + { + // + string message = signal.GetMessage("Provided"); + alert.SendAlert(message); + } + + // + SaveSignal(signal); + + // + // Check Trade Permission ... + if (!allowTrade) + { + // + result = false; + executionResult = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + + // + return result; + } + + // + bool isLong = IsLong(signal.type); + bool isShort = IsShort(signal.type); + + // + bool isLongAndAllowed = + isLong && + allowLongs; + + // + bool isShortAndAllowed = + isShort && + allowShorts; + + // + result = isLongAndAllowed || + isShortAndAllowed; + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + + // + return result; + } + + // + // Check Symbol Info Exists or not ... + int symbolInfoIDX = -1; + bool isSymbolInfoExists = FindSymbolIndex( + symbolInfoIDX, + signal.symbol // + ); + + // + // Check Symbol Session Exists or not ... + int symbolSessionIDX = -1; + bool isSymbolSessionExists = FindSymbolSession( + symbolSessionIDX, + signal.symbol // + ); + + // + // Chack Trade Session Validating ... + if (isSymbolSessionExists) + { + // + result = sessions[symbolSessionIDX].CanTrade(); + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED; + + // + return result; + } + } + + // + // Check Trade Permissions Based on SL(s) Count ... + bool hasRestrictions = restrictionsPeriod != XTRADE_RESTRICATION_NONE; + if (hasRestrictions) + { + // + // Only Can Check Restrictions when + // Symbol Info Exists ... + if (isSymbolInfoExists) + { + // + bool isTPAllowed = maxAllowedTPs == 0 + ? true + : symbols[symbolInfoIDX].managedTPs < maxAllowedTPs; + bool isSLAllowed = maxAllowedSLs == 0 + ? true + : symbols[symbolInfoIDX].managedSLs < maxAllowedSLs; + bool isTradeAllowed = maxAllowedTrades == 0 + ? true + : symbols[symbolInfoIDX].managedTrades < maxAllowedTrades; + + // + result = isTPAllowed && + isSLAllowed && + isTradeAllowed; + } + + // + // Report Error ... + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + + // + return result; + } + } + + // + return result; +} + +/** + * Execute Specified Signal ... + * + * @param signal: XSignal instance reference ... + * @param conditions: XCATBEAStrategyConditions instance reference ... + * + * @return ( bool ) + */ +bool Execute(XSignal &signal) +{ + // + bool result = false; + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + bool isExists = HasTrade( + idx, + signal // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + ENUM_X_SIGNAL_EXECUTION_RESULT executionResult; + + // + // Checking Signal For Execution ... + result = CheckSignal( + signal, + executionResult // + ); + if (result) + { + // + result = trader.ExecuteSignal( + signal, + executionResult // + ); + } + + // + // Alert Signal Execution ... + if (reportTrades) + { + // + string executionMessage = ToString(executionResult); + + // + string message = NULL; + if (result) + { + message = signal.GetMessage("Executed"); + } + else + { + message = signal.GetMessage("Failed due (" + executionMessage + ")"); + } + + // + alert.SendAlert(message); + } + + // + if (result) + { + // + // Create Symbol Info Struct ... + XTradeSymbolInfo iSymbolInfo; + + // + iSymbolInfo.trades = 1; + iSymbolInfo.managedTrades = 1; + iSymbolInfo.symbol = signal.symbol; + + // + bool isLong = IsLong(signal.type); + if (isLong) + { + iSymbolInfo.longs = 1; + } + else + { + iSymbolInfo.shorts = 1; + } + + // + // Fill Balance for Restrications ... + bool hasRestrictions = HasRestrictions(restrictionsPeriod); + if (hasRestrictions) + { + // + // Read Balance ... + double balance = trader.mAccount.GetBalance(); + iSymbolInfo.managedBalance = balance; + iSymbolInfo.managedStart = TimeCurrent(); + } + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + // Create Trade Struct ... + XTradeInfo iTrade; + + // + ulong positionID = trader.GetLastOpenPositionTicket(); + double commission = trader.GetPositionCommission(positionID); + + // + iTrade.signal = signal; + iTrade.positionID = positionID; + iTrade.commission = commission; + iTrade.signaledAt = signal.time; + iTrade.executedAt = TimeCurrent(); + iTrade.conditions = signal.conditions; + + // + AddRef( + iTrade, + trades // + ); + } + + // + return result; +} + +// +string forceCloseAt; +bool isForceCloseAtTime; + +// +int maxAllowedTPs; +int maxAllowedSLs; +int maxAllowedTrades; +ENUM_XTRADE_RESTRICTION_PERIOD restrictionsPeriod; + +XTradeSymbolInfo symbols[]; +XSymbolSessions sessions[]; + +// +forceCloseAt = NULL; +isForceCloseAtTime = false; + +// +maxAllowedTPs = 0; +maxAllowedSLs = 0; +maxAllowedTrades = 0; +restrictionsPeriod = XTRADE_RESTRICATION_NONE; diff --git a/Libraries/x-saherelm.x-trade.lib.mq5 b/Libraries/x-saherelm.x-trade.lib.mq5 index f8c20d2b..253bd555 100644 --- a/Libraries/x-saherelm.x-trade.lib.mq5 +++ b/Libraries/x-saherelm.x-trade.lib.mq5 @@ -2865,18 +2865,32 @@ struct XSymbolTradeConfig ZeroMemory(this); } - // - // Initial ... + /** + * Initial ... + * + * @param _symbol: Trading Symbol + * @param _period: Trading Period + * @param _sessionsDescriptor: Sessions Description + * @param _maxAllowedSpread: Max Allowed Spread for Open Trade + * @param _maxAllowedPositions: Max Allowed Same Time Position + * @param _closeAllOpenTradesAt: Close All Open Trades + * @param _maxAllowedTPs: Max Allowed TPs in Restrictions Period + * @param _maxAllowedSLs: Max Allowed SLs in Restrictions Period + * @param _restrictionsPeriod: Restrictions Period + * + * @return ( bool ) + */ bool Init( string _symbol = NULL, ENUM_TIMEFRAMES _period = NULL, string _sessionsDescriptor = NULL, double _maxAllowedSpread = 25, int _maxAllowedPositions = 5, - string _closeAllOpenTradesAt = NULL, - int _maxAllowedTPs = 0, - int _maxAllowedSLs = 0, - ENUM_XTRADE_RESTRICTION_PERIOD _restrictionsPeriod = XTRADE_RESTRICATION_NONE // + string _restrictionsDescriptor = NULL // + // string _closeAllOpenTradesAt = NULL, + // int _maxAllowedTPs = 0, + // int _maxAllowedSLs = 0, + // ENUM_XTRADE_RESTRICTION_PERIOD _restrictionsPeriod = XTRADE_RESTRICATION_NONE // ) { // @@ -2890,17 +2904,23 @@ struct XSymbolTradeConfig // symbol = _symbol; period = _period; - maxAllowedTPs = _maxAllowedTPs; - maxAllowedSLs = _maxAllowedSLs; maxAllowedSpread = _maxAllowedSpread; - restrictionsPeriod = _restrictionsPeriod; maxAllowedPositions = _maxAllowedPositions; - closeAllOpenTradesAt = _closeAllOpenTradesAt; + + // + // maxAllowedTPs = _maxAllowedTPs; + // maxAllowedSLs = _maxAllowedSLs; + // restrictionsPeriod = _restrictionsPeriod; + // closeAllOpenTradesAt = _closeAllOpenTradesAt; // // Parse Sessions ... ParseSessions(_sessionsDescriptor); + // + // Parse Restrictions ... + ParseRestrictions(_restrictionsDescriptor); + // result = IsValid(); @@ -2908,6 +2928,24 @@ struct XSymbolTradeConfig return result; } + // + // Check Same ... + bool IsSame(XSymbolTradeConfig &dest) + { + // + bool result = false; + + // + // Validate ... + result = IsValid() && + dest.IsValid() && + symbol == dest.symbol && + period == dest.period; + + // + return result; + } + // // Validate ... bool IsValid() @@ -2916,7 +2954,8 @@ struct XSymbolTradeConfig bool result = false; // - result = IsSpecifiedValid(symbol); + result = IsSpecifiedValid(symbol) && + IsSpecifiedValid(period); // return result; @@ -3057,6 +3096,12 @@ struct XSymbolTradeConfig SpecifiedClean(_sessions); } + // + // Parse Restrictions ... + void ParseRestrictions(string descriptor) { + + } + // }; diff --git a/XOM1EA/Classes/xom1ea.expert.class.mq5 b/XOM1EA/Classes/xom1ea.expert.class.mq5 index a8183d1a..915cca56 100644 --- a/XOM1EA/Classes/xom1ea.expert.class.mq5 +++ b/XOM1EA/Classes/xom1ea.expert.class.mq5 @@ -525,10 +525,6 @@ class XCXOM1EAExpert : public XCBase eaTradeManager.SaveSignals(eaSaveSignals); eaTradeManager.SaveRestrictions(eaSaveRestrictions); - // - // Enable Force Close At ... - eaTradeManager.SetForceCloseTradesAt(eaCloseAllOpenTradesAt); - // // Setting Trade Reports ... eaTradeManager @@ -550,37 +546,12 @@ class XCXOM1EAExpert : public XCBase ); // - // Setting Trade Restrictions ... - eaTradeManager - .SetTradeRestrictions( - eaRestrictionsPeriod, - eaMaxAllowedTPs, - eaMaxAllowedSLs, - eaMaxAllowedTrades // - ); - - // - // Parse Symbols ... - string symbols[]; - ENUM_TIMEFRAMES periods[]; - if (!IsSpecifiedValid(eaSymbolConfiguration)) - { - // - Add( - _Symbol, - symbols // - ); - - // - Add( - _Period, - periods // - ); - } - else - { - } - + // Setting Symbol Configuration ... + XSymbolTradeConfig symbolConfigurations[]; + eaTradeManager.SetSymbolConfigurations(eaSymbolConfiguration); + count = eaTradeManager.FillSymbolConfigurations(symbolConfigurations); + has = IsValidSize(count); + // // Here we Apply Symbols,Periods and Configs ...