From a868160ba2b7713213c772a453484b5a8eb99a48 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Sun, 9 Jun 2024 04:20:08 +0330 Subject: [PATCH] last works ... --- Classes/x-saherelm.x121.xea.class.mq5 | 267 ++++++++++++++++++++------ Classes/x-saherelm.xtrade.class.mq5 | 4 +- Experts/x-test.x121ea.mq5 | 14 +- Libraries/x-saherelm.xtrade.lib.mq5 | 267 ++++++++++++++++++++++++++ 4 files changed, 487 insertions(+), 65 deletions(-) diff --git a/Classes/x-saherelm.x121.xea.class.mq5 b/Classes/x-saherelm.x121.xea.class.mq5 index 14786bb6..7e5b1a2a 100644 --- a/Classes/x-saherelm.x121.xea.class.mq5 +++ b/Classes/x-saherelm.x121.xea.class.mq5 @@ -401,10 +401,14 @@ struct XProtectedPosition // // Volume ... // For Volume Calculating we have to use Recovery Level ... + // double mVolume = + // lastVolume == 0 + // ? volume * 1 + // : lastVolume * 1; double mVolume = - lastVolume == 0 - ? volume * 3 - : lastVolume * 3; + canSameDirectionRecover + ? volume + : volume * 2; // result = signal.Prepare( @@ -538,10 +542,9 @@ public: // // Initial Class ... - bool - Init( + bool Init( XSCTrade *trader, - double mMinRequiredProfitPerTrade = 0.35, + double mMinRequiredProfitPerTrade = 0.5, double mMinRequiredProfitPerTradeVolumeFactor = 0.01 // ) { @@ -645,63 +648,80 @@ public: { // int protectedsCount = ArraySize(protecteds); - if (!IsValidSize(protectedsCount)) - { - return; - } - - // - // Loop through Exists ... - for (int i = 0; i < protectedsCount; i++) + if (IsValidSize(protectedsCount)) { // - // Do Protection ... - HandlePositionsProtecting(protecteds[i]); - } - - // - // Handle Hedging All Positions ... - bool allowHedge = AllowHedge(); - if (!allowHedge) - { - return; - } - - // - XPosition positions[]; - int positionsCount = mTrader.GetPositions(positions); - if (!IsValidSize(positions) || positionsCount <= 1) - { - return; - } - - // - double profit = SpecifiedCalculatePositionsProfit(positions); - double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( - positions, - minRequiredProfitPerTrade, - minRequiredProfitPerTradeVolumeFactor // - ); - bool canHedge = SpecifiedIsPositionsReadyForHedge( - positions, - minRequiredProfitPerTrade, - minRequiredProfitPerTradeVolumeFactor // - ); - if (!canHedge) - { - return; + // Loop through Exists ... + for (int i = 0; i < protectedsCount; i++) + { + // + // Do Protection ... + HandlePositionsProtecting(protecteds[i]); + } } // string comment = XEQMSupportToken + " Hege ..."; - ENUM_X_SIGNAL_EXECUTION_RESULT states[]; - int closed = mTrader.Close( - positions, - comment // - ); - if (IsValidSize(closed)) + + // + // Handle Hedging All Positions ... + bool allowHedge = AllowHedge(); + if (allowHedge) { - Clean(protecteds); + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions(positions); + if (!IsValidSize(positions) || positionsCount <= 1) + { + // + // Here We Can Close if Still Positions is EQM Support ... + bool canClosePosition = + // + positionsCount == 1 && + positions[0].provider == XEQMSupportToken && + positions[0].profit > (-1 * positions[0].swap) + (minRequiredProfitPerTrade * (positions[0].volume / minRequiredProfitPerTradeVolumeFactor)) + // + ; + if (canClosePosition) + { + // + bool isClosed = mTrader.Close( + positions[0].ticket, + comment // + ); + } + return; + } + + // + double profit = SpecifiedCalculatePositionsProfit(positions); + double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( + positions, + minRequiredProfitPerTrade, + minRequiredProfitPerTradeVolumeFactor // + ); + bool canHedge = SpecifiedIsPositionsReadyForHedge( + positions, + minRequiredProfitPerTrade, + minRequiredProfitPerTradeVolumeFactor // + ); + if (!canHedge) + { + // + ProtectMargin(); + return; + } + + // + ENUM_X_SIGNAL_EXECUTION_RESULT states[]; + int closed = mTrader.Close( + positions, + comment // + ); + if (IsValidSize(closed)) + { + Clean(protecteds); + } } } @@ -916,6 +936,11 @@ protected: string comment = GenerateEQMSupportTag(item.ticket); signal.comment = comment; + // + // Remove Support Signal TP and SL ... + signal.tp = 0; + signal.sl = 0; + // ENUM_X_SIGNAL_EXECUTION_RESULT state; bool isExecuted = mTrader.ExecuteSignal( @@ -968,6 +993,136 @@ protected: return result; } + // + // Protecting Margin by Free Coveraged Positions ... + void ProtectMargin() + { + // + double freeMargin = mTrader.mAccount.GetFreeMargin(); + + // + double balance = mTrader.mAccount.GetBalance(); + double equity = mTrader.mAccount.GetEquity(); + + // + double selectedBalance = MathMin(balance, equity); + + // + // Retrieve All Positions ... + XPosition positions[]; + int positionsCount = mTrader.GetPositions(positions); + if (!IsValidSize(positionsCount)) + { + return; + } + + // + bool canForceHedging = + positionsCount >= 25 || + freeMargin <= selectedBalance / 2; + if (!canForceHedging) + { + return; + } + + // + // First Check Hedging By Half of Required Profit ... + double profit = SpecifiedCalculatePositionsProfit(positions); + double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( + positions, + minRequiredProfitPerTrade, + minRequiredProfitPerTradeVolumeFactor // + ); + bool canHedge = + // + profit > requiredProfit / 2 + // + ; + if (canHedge) + { + // + string comment = XEQMSupportToken + " Hege ..."; + int closed = mTrader.Close( + positions, + comment // + ); + + // + return; + } + + // + // TODO: Enable this if we want ... + return; + + // + // Retrieve In Drawdown Positions ... + XPosition inDPositions[]; + int inDPositionsCount = ExtractInDrawdownPositions( + positions, + inDPositions /// + ); + if (!IsValidSize(inDPositionsCount)) + { + return; + } + + // + // Retrieve In Profit Positions ... + XPosition inPPositions[]; + int inPPositionsCount = ExtractInProfitPositions( + positions, + inPPositions // + ); + if (!IsValidSize(inPPositionsCount)) + { + return; + } + + // + // if we can't Hedge all Positions ... + // now we are looking to pair Positions for hedge ... + // - Select Max In Drawdown Position; + // - Looking for Coverage it inside In Profit Positions; + // - Clease All of them ... + int maxInDIDX = FindMaxDrawdownIndex(inDPositions); + if (maxInDIDX < 0) + { + return; + } + + // + string comment = XEQMSupportToken + " Force Hege ..."; + + // + XPosition maxInDCoverages[]; + int maxInDCoveragesCount = FindCoverageDrawdownPosition( + inDPositions[maxInDIDX], + inPPositions, + maxInDCoverages, + minRequiredProfitPerTrade, + minRequiredProfitPerTradeVolumeFactor // + ); + if (!IsValidSize(maxInDCoveragesCount)) + { + return; + } + + // + bool isClosedMaxInD = mTrader.Close( + inDPositions[maxInDIDX].ticket, + comment // + ); + if (isClosedMaxInD) + { + // + int closed = mTrader.Close( + maxInDCoverages, + comment // + ); + } + } + // // Protected Collection Management ... diff --git a/Classes/x-saherelm.xtrade.class.mq5 b/Classes/x-saherelm.xtrade.class.mq5 index c165e84f..b17b40b0 100644 --- a/Classes/x-saherelm.xtrade.class.mq5 +++ b/Classes/x-saherelm.xtrade.class.mq5 @@ -523,6 +523,7 @@ class XSCTrade : public XSCBase public: // // Props ... + XSCAccount *mAccount; // Account Info Provider // // Constructors ... @@ -3182,7 +3183,7 @@ public: // // Tools ... - + // // Retrieve Last Open Position Ticket ... ulong GetLastOpenPositionTicket() @@ -3501,7 +3502,6 @@ private: double mMaxAllowedDrawdownFactor; // Max Allowed Drawdown Factor // - XSCAccount *mAccount; // Account Info Provider XSCTradeBase *mTrader; // Base CTrade Manipulated Instance ... // diff --git a/Experts/x-test.x121ea.mq5 b/Experts/x-test.x121ea.mq5 index ae7cacfe..3e889410 100644 --- a/Experts/x-test.x121ea.mq5 +++ b/Experts/x-test.x121ea.mq5 @@ -325,17 +325,17 @@ bool InitialEA() // int idx = 0; - ArrayResize(iDescriptor.signallers, 1); + ArrayResize(iDescriptor.signallers, 4); // iDescriptor.signallers[idx] = x786Signaller; idx++; - // iDescriptor.signallers[idx] = x121Signaller; - // idx++; - // iDescriptor.signallers[idx] = x110Signaller; - // idx++; - // iDescriptor.signallers[idx] = x92Signaller; - // idx++; + iDescriptor.signallers[idx] = x121Signaller; + idx++; + iDescriptor.signallers[idx] = x110Signaller; + idx++; + iDescriptor.signallers[idx] = x92Signaller; + idx++; // iDescriptor.signallers[idx] = x128Signaller; // idx++; // iDescriptor.signallers[idx] = xSPSignaller; diff --git a/Libraries/x-saherelm.xtrade.lib.mq5 b/Libraries/x-saherelm.xtrade.lib.mq5 index 67f7f632..d16e9245 100644 --- a/Libraries/x-saherelm.xtrade.lib.mq5 +++ b/Libraries/x-saherelm.xtrade.lib.mq5 @@ -3482,6 +3482,172 @@ int GetYoungest( return result; } +// +int FindMaxProfitIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double max = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit <= 0) + { + continue; + } + + // + if (max == 0 || + max < iPosition.profit) + { + // + result = i; + max = iPosition.profit; + } + } + + // + return result; +} + +// +int ExtractInProfitPositions( + XPosition &positions[], // Position Collection + XPosition &inProfits[] // Result +) +{ + // + int result = 0; + + // + Clean(inProfits); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit > 0) + { + // + AddRef( + iPosition, + inProfits // + ); + } + } + + // + result = ArraySize(inProfits); + + // + return result; +} + +// +int FindMaxDrawdownIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double min = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit >= 0) + { + continue; + } + + // + if (min == 0 || + min > iPosition.profit) + { + // + result = i; + min = iPosition.profit; + } + } + + // + return result; +} + +// +int ExtractInDrawdownPositions( + XPosition &positions[], // Position Collection + XPosition &inDradowns[] // Result +) +{ + // + int result = 0; + + // + Clean(inDradowns); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit < 0) + { + // + AddRef( + iPosition, + inDradowns // + ); + } + } + + // + result = ArraySize(inDradowns); + + // + return result; +} + // // Check Filters ... @@ -3819,6 +3985,107 @@ bool SpecifiedIsPositionsReadyForHedge( return result; } +// +int FindCoverageDrawdownPosition( + XPosition &position, // In Drawdown Position + XPosition &inProfits[], // In Profit Positions + XPosition &coverage[], // Coverage Positons + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + int result = 0; + + // + Clean(coverage); + + // + if (!position.IsValid() || position.profit >= 0) + { + return result; + } + + // + int inProfitsCount = ArraySize(inProfits); + if (!IsValidSize(inProfitsCount)) + { + return result; + } + + // + // Copy in Profits to TMP ... + XPosition tmp[]; + Copy( + inProfits, + tmp // + ); + + // + bool isCoverPassed = false; + while (!isCoverPassed || ArraySize(tmp) > 0) + { + // + XPosition max; + int idx = FindMaxProfitIndex(tmp); + if (idx >= 0) + { + // + if (tmp[idx].profit > 0) + { + AddRef( + tmp[idx], + coverage // + ); + + // + ArrayRemove( + tmp, + idx, + 1 // + ); + } + } + + // + // Check Cover Passed ... + XPosition tmpPositions[]; + Copy( + coverage, + tmpPositions // + ); + AddRef( + position, + tmpPositions // + ); + + // + double profits = SpecifiedCalculatePositionsProfit(tmpPositions); + double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( + tmpPositions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + isCoverPassed = profits >= requiredProfit; + if (isCoverPassed) + { + break; + } + + // + if (!isCoverPassed && ArraySize(tmp) == 0) + { + break; + } + } + + // + result = ArraySize(coverage); + + // + return result; +} + // // Extract a Collection of Positions SL ... int ExtractSLs(