From 46f8009ca5c3fb54a564f93cbab98fd8482f6604 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Thu, 19 Sep 2024 14:49:24 +0330 Subject: [PATCH] last ... --- .../x-saherelm.x121.xtrade.handler.class.mq5 | 596 +++++++++++------- Documents/BKP/canRecover.mq5 | 108 ++++ Experts/x-saherelm.x121.ea.mq5 | 18 +- pack.js | 2 +- package.json | 2 +- 5 files changed, 478 insertions(+), 248 deletions(-) create mode 100644 Documents/BKP/canRecover.mq5 diff --git a/Classes/x-saherelm.x121.xtrade.handler.class.mq5 b/Classes/x-saherelm.x121.xtrade.handler.class.mq5 index cc8d878e..20f047e5 100644 --- a/Classes/x-saherelm.x121.xtrade.handler.class.mq5 +++ b/Classes/x-saherelm.x121.xtrade.handler.class.mq5 @@ -54,10 +54,12 @@ struct X121TradeData string conditions; // Signal Conditions // - int trailStep; // Trail Step - int protectionStep; // Protection Step - double lastProtectedVolume; // Last Protected Volume - bool partiallyClosed; // Partially Closed or not + int trailStep; // Trail Step + int protectionStep; // Protection Step + datetime lastProtectedOn; // Last Protection Date + double lastProtectedInProfit; // Last Protection In Profit + double lastProtectedInDrawdown; // Last Protection In Drawdown + bool partiallyClosed; // Partially Closed or not // // Constructor ... @@ -199,7 +201,9 @@ struct X121TradeData trailStep = 0; protectionStep = 0; partiallyClosed = false; - lastProtectedVolume = 0; + lastProtectedOn = NULL; + lastProtectedInProfit = 0; + lastProtectedInDrawdown = 0; // signal.Clean(); @@ -1233,6 +1237,44 @@ class X121SCTradeHandler : public XSCBaseAlert mRecoveryMultiplier = value; } + // + int RecoveryDelayInMinute() + { + return mRecoveryDelayInMinute; + } + + // + void RecoveryDelayInMinute(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mRecoveryDelayInMinute = value; + } + + // + double RecoveryDistanceInPoint() + { + return mRecoveryDistanceInPoint; + } + + // + void RecoveryDistanceInPoint(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mRecoveryDistanceInPoint = value; + } + // double PartialCloseOnSpecificPointOfDrawdown() { @@ -2288,59 +2330,51 @@ class X121SCTradeHandler : public XSCBaseAlert // Check Main Positions Count and also not Support Positions ... result = supportsCount == 0 && positionsCount >= minOpenPositions; - if (!result) - { - return result; - } - - // - // Check Profits ... - result = profits > 0; - if (!result) - { - return result; - } - - // - // Calculate Required Profit ... - double volumeSteps = volumes / minVolumeStep; - double minRequiredProfit = (volumeSteps * heMinProfitPerVolumeStep) + - commissions + (-1 * swaps); - - // - // Check Profits Satisfied Required Profit's For Hedge or not ... - result = profits >= minRequiredProfit; - if (!result) - { - return result; - } - - // - int flatPositionsCount = ArraySize(flatPositions); - result = IsValidSize(flatPositionsCount); - if (!result) - { - return result; - } - - // - string comment = "EQM HE Hedge ..."; - int closed = mTrader.Close( - flatPositions, - comment // - ); - - // - result = closed > 0; if (result) { // - string message = "EQM HE Hedge Close (" + ToString(flatPositionsCount) + ") Positions by: " + ToString(profits); - Alert(message); - } + // Check Profits ... + result = profits > 0; + if (result) + { + // + // Calculate Required Profit ... + double volumeSteps = volumes / minVolumeStep; + double minRequiredProfit = (volumeSteps * heMinProfitPerVolumeStep) + + commissions + (-1 * swaps); - // - return result; + // + // Check Profits Satisfied Required Profit's For Hedge or not ... + result = profits >= minRequiredProfit; + if (result) + { + // + int flatPositionsCount = ArraySize(flatPositions); + result = IsValidSize(flatPositionsCount); + if (result) + { + // + string comment = "EQM HE Hedge ..."; + int closed = mTrader.Close( + flatPositions, + comment // + ); + + // + result = closed > 0; + if (result) + { + // + string message = "EQM HE Hedge Close (" + ToString(flatPositionsCount) + ") Positions by: " + ToString(profits); + Alert(message); + + // + return result; + } + } + } + } + } } // @@ -2356,47 +2390,44 @@ class X121SCTradeHandler : public XSCBaseAlert // // Check Profits ... result = profits > 0; - if (!result) - { - return result; - } - - // - // Calculate Required Profit ... - double volumeSteps = volumes / minVolumeStep; - double minRequiredProfit = (volumeSteps * beMinProfitPerVolumeStep) + - commissions + (-1 * swaps); - - // - // Check Profits Satisfied Required Profit's For Hedge or not ... - result = profits >= minRequiredProfit; - if (!result) - { - return result; - } - - // - int flatPositionsCount = ArraySize(flatPositions); - result = IsValidSize(flatPositionsCount); - if (!result) - { - return result; - } - - // - string comment = "EQM BE Hedge ..."; - int closed = mTrader.Close( - flatPositions, - comment // - ); - - // - result = closed > 0; if (result) { // - string message = "EQM BE Hedge Close (" + ToString(flatPositionsCount) + ") Positions by: " + ToString(profits); - Alert(message); + // Calculate Required Profit ... + double volumeSteps = volumes / minVolumeStep; + double minRequiredProfit = (volumeSteps * beMinProfitPerVolumeStep) + + commissions + (-1 * swaps); + + // + // Check Profits Satisfied Required Profit's For Hedge or not ... + result = profits >= minRequiredProfit; + if (result) + { + // + int flatPositionsCount = ArraySize(flatPositions); + result = IsValidSize(flatPositionsCount); + if (result) + { + // + string comment = "EQM BE Hedge ..."; + int closed = mTrader.Close( + flatPositions, + comment // + ); + + // + result = closed > 0; + if (result) + { + // + string message = "EQM BE Hedge Close (" + ToString(flatPositionsCount) + ") Positions by: " + ToString(profits); + Alert(message); + + // + return result; + } + } + } } // @@ -2769,6 +2800,140 @@ class X121SCTradeHandler : public XSCBaseAlert } } + // + bool allowRecover = AllowRecoverInDrawdowns(); + double volumeMultiplier = RecoveryMultiplier(); + if (allowRecover && volumeMultiplier > 0 && supportsCount > 0) + { + // + bool canRecover = false; + int delayMinutes = RecoveryDelayInMinute(); + double recoveryDistancePoint = RecoveryDistanceInPoint(); + + // + // Temparory Requirement for Recover Signal ... + double sl = 0; + double tp = 0; + double entry = 0; + ENUM_POSITION_TYPE type = NULL; + ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET; + double lastStep = mData[iDX].protectionStep; + double volume = position.volume * volumeMultiplier; + // supportsCount <= 0 + // ? position.volume * volumeMultiplier + // : position.volume * ((supportsCount + 1) * volumeMultiplier); + + // + datetime currentTime = TimeCurrent(); + double currentProfit = position.GetProfitInPoint(); + datetime lastProtectedOn = mData[iDX].lastProtectedOn; + double lastProtectedProfit = mData[iDX].lastProtectedInProfit; + bool isRecoveryConditionsPassed = + // + // Check Regular Conditions ... + delayMinutes > 0 && + recoveryDistancePoint > 0 && + IsValid(lastProtectedOn) && + // + // Check Time Delay Passed ... + (TimeToSeconds(currentTime) - TimeToSeconds(lastProtectedOn)) >= ulong(delayMinutes * 60) && + // + // Check Recovery Distance Passed ... + MathAbs(currentProfit) - MathAbs(lastProtectedProfit) >= recoveryDistancePoint; + + // + if (isRecoveryConditionsPassed) + { + // + // Long Recovery ... + if (isLong) + { + // + // Same Direction ... + canRecover = true; + if (canRecover) + { + // + sl = position.sl; + tp = position.tp; + type = POSITION_TYPE_BUY; + } + } + // + // Short Recovery ... + else + { + // + // Same Direction ... + canRecover = true; + if (canRecover) + { + // + sl = position.sl; + tp = position.tp; + type = POSITION_TYPE_SELL; + } + } + + // + if (canRecover) + { + // + XSignal signal; + entry = GetEntry( + position.symbol, + type // + ); + + // + // Prepare Signal ... + result = signal.Prepare( + position.symbol, + position.provider, + position.period, + type, + mode, + entry, + volume, + sl, + tp // + ); + + // + if (result) + { + // + // Generate Comment for Recover and Support ... + string comment = GenerateSupportTag(position.ticket); + + // + signal.comment = comment; + + // + ENUM_X_SIGNAL_EXECUTION_RESULT state; + result = ExecuteSignal( + signal, + state, + true // Support Signal need to Ignore Policies ... + ); + if (result) + { + // + mData[iDX].protectionStep++; + mData[iDX].lastProtectedOn = currentTime; + mData[iDX].lastProtectedInProfit = currentProfit; + + // + string message = "EQM Open " + (IsLong(type) ? "Long" : "Short") + " Recovery Position in Level: " + + ToString(lastStep + 1) + + " for (" + ToString(position.ticket) + ")"; + Alert(message); + } + } + } + } + } + // // Check Points of Profit and Do Partial Closing ... double partialCloseVolume = PartialCloseVolumeInProfit(); @@ -2817,6 +2982,8 @@ class X121SCTradeHandler : public XSCBaseAlert { // bool canRecover = false; + int delayMinutes = RecoveryDelayInMinute(); + double recoveryDistancePoint = RecoveryDistanceInPoint(); // // Temparory Requirement for Recover Signal ... @@ -2826,171 +2993,120 @@ class X121SCTradeHandler : public XSCBaseAlert ENUM_POSITION_TYPE type = NULL; ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET; double lastStep = mData[iDX].protectionStep; - double volume = supportsCount <= 0 - ? position.volume * volumeMultiplier - : position.volume * ((supportsCount + 1) * volumeMultiplier); + double volume = position.volume * volumeMultiplier; + // supportsCount <= 0 + // ? position.volume * volumeMultiplier + // : position.volume * ((supportsCount + 1) * volumeMultiplier); // - // Long Recovery ... - if (isLong) + datetime currentTime = TimeCurrent(); + double currentDrawdown = position.GetProfitInPoint(); + datetime lastProtectedOn = mData[iDX].lastProtectedOn; + double lastProtectedDrawdown = mData[iDX].lastProtectedInDrawdown; + bool isRecoveryConditionsPassed = supportsCount <= 0 + ? true + : + // + // Check Regular Conditions ... + delayMinutes > 0 && + recoveryDistancePoint > 0 && + IsValid(lastProtectedOn) && + lastProtectedDrawdown < 0 && + // + // Check Time Delay Passed ... + (TimeToSeconds(currentTime) - TimeToSeconds(lastProtectedOn)) >= ulong(delayMinutes * 60) && + // + // Check Recovery Distance Passed ... + MathAbs(currentDrawdown) - MathAbs(lastProtectedDrawdown) >= recoveryDistancePoint; + + // + if (isRecoveryConditionsPassed) { // - // Opposit Direction ... - canRecover = - // - isTicksBearishForShort && - ( - // - hasBearishTrend && - (hasBearishPower || - hasBearishPattern || - hasBearishPressure) - // - ) - // - ; - if (canRecover) + // Long Recovery ... + if (isLong) { // - sl = position.tp; - tp = position.sl; - type = POSITION_TYPE_SELL; + // Opposit Direction ... + canRecover = true; + if (canRecover) + { + // + sl = position.tp; + tp = position.sl; + type = POSITION_TYPE_SELL; + } + } + // + // Short Recovery ... + else + { + // + // Opposit Direction ... + canRecover = true; + if (canRecover) + { + // + sl = position.tp; + tp = position.sl; + type = POSITION_TYPE_BUY; + } } // - // Same Direction ... - // if (!canRecover) - // { - // // - // canRecover = - // // - // isTicksBullishForLong && - // ( - // // - // hasBullishTrend && - // (hasBullishPower || - // hasBullishPattern || - // hasBullishPressure) - // // - // ) - // // - // ; - // if (canRecover) - // { - // // - // sl = position.sl; - // tp = position.entry; - // type = POSITION_TYPE_BUY; - // } - // } - } - // - // Short Recovery ... - else - { - // - // Opposit Direction ... - canRecover = - // - isTicksBullishForLong && - ( - // - hasBullishTrend && - (hasBullishPower || - hasBullishPattern || - hasBullishPressure) - // - ) - // - ; if (canRecover) { // - sl = position.tp; - tp = position.sl; - type = POSITION_TYPE_BUY; - } - - // - // Same Direction ... - // if (!canRecover) - // { - // // - // canRecover = - // // - // isTicksBearishForShort && - // ( - // // - // hasBearishTrend && - // (hasBearishPower || - // hasBearishPattern || - // hasBearishPressure) - // // - // ) - // // - // ; - // if (canRecover) - // { - // // - // sl = position.sl; - // tp = position.entry; - // type = POSITION_TYPE_SELL; - // } - // } - } - - // - if (canRecover) - { - // - XSignal signal; - entry = GetEntry( - position.symbol, - type // - ); - - // - // Prepare Signal ... - result = signal.Prepare( - position.symbol, - position.provider, - position.period, - type, - mode, - entry, - volume, - sl, - tp // - ); - - // - if (result) - { - // - // Generate Comment for Recover and Support ... - string comment = GenerateSupportTag(position.ticket); - - // - signal.comment = comment; - - // - ENUM_X_SIGNAL_EXECUTION_RESULT state; - result = ExecuteSignal( - signal, - state, - true // Support Signal need to Ignore Policies ... + XSignal signal; + entry = GetEntry( + position.symbol, + type // ); + + // + // Prepare Signal ... + result = signal.Prepare( + position.symbol, + position.provider, + position.period, + type, + mode, + entry, + volume, + sl, + tp // + ); + + // if (result) { // - mData[iDX].protectionStep++; - mData[iDX].lastProtectedVolume = volume; + // Generate Comment for Recover and Support ... + string comment = GenerateSupportTag(position.ticket); // - string message = "EQM Open " + (IsLong(type) ? "Long" : "Short") + " Recovery Position in Level: " + - ToString(lastStep + 1) + - " for (" + ToString(position.ticket) + ")"; - Alert(message); + signal.comment = comment; + + // + ENUM_X_SIGNAL_EXECUTION_RESULT state; + result = ExecuteSignal( + signal, + state, + true // Support Signal need to Ignore Policies ... + ); + if (result) + { + // + mData[iDX].protectionStep++; + mData[iDX].lastProtectedOn = currentTime; + mData[iDX].lastProtectedInDrawdown = currentDrawdown; + + // + string message = "EQM Open " + (IsLong(type) ? "Long" : "Short") + " Recovery Position in Level: " + + ToString(lastStep + 1) + + " for (" + ToString(position.ticket) + ")"; + Alert(message); + } } } } @@ -3076,6 +3192,8 @@ class X121SCTradeHandler : public XSCBaseAlert // In Drawdown Positions Protecting ... bool mAllowRecoverInDrawdowns; // Allow Recovery For In Drawdown Positions double mRecoveryMultiplier; // Recovery Volume Multiplier + int mRecoveryDelayInMinute; // Delay Between Two Recovery in Minutes + double mRecoveryDistanceInPoint; // Distance Between Two Recovery in Point double mPartialCloseOnSpecificPointOfDrawdown; // Partial Close Position on Specific Points of Drawdown double mPartialCloseVolumeInDrawdown; // Partial Close Volume diff --git a/Documents/BKP/canRecover.mq5 b/Documents/BKP/canRecover.mq5 new file mode 100644 index 00000000..26f3e771 --- /dev/null +++ b/Documents/BKP/canRecover.mq5 @@ -0,0 +1,108 @@ + // + // Long Recovery ... + if (isLong) + { + // + // Opposit Direction ... + // canRecover = + // // + // isTicksBearishForShort && + // ( + // // + // hasBearishTrend && + // (hasBearishPower || + // hasBearishPattern || + // hasBearishPressure) + // // + // ) + // // + // ; + // if (canRecover) + // { + // // + // sl = position.tp; + // tp = position.sl; + // type = POSITION_TYPE_SELL; + // } + + // + // Same Direction ... + // if (!canRecover) + // { + // // + // canRecover = + // // + // isTicksBullishForLong && + // ( + // // + // hasBullishTrend && + // (hasBullishPower || + // hasBullishPattern || + // hasBullishPressure) + // // + // ) + // // + // ; + // if (canRecover) + // { + // // + // sl = position.sl; + // tp = position.entry; + // type = POSITION_TYPE_BUY; + // } + // } + } + // + // Short Recovery ... + else + { + // + // Opposit Direction ... + // canRecover = + // // + // isTicksBullishForLong && + // ( + // // + // hasBullishTrend && + // (hasBullishPower || + // hasBullishPattern || + // hasBullishPressure) + // // + // ) + // // + // ; + // if (canRecover) + // { + // // + // sl = position.tp; + // tp = position.sl; + // type = POSITION_TYPE_BUY; + // } + + // + // Same Direction ... + // if (!canRecover) + // { + // // + // canRecover = + // // + // isTicksBearishForShort && + // ( + // // + // hasBearishTrend && + // (hasBearishPower || + // hasBearishPattern || + // hasBearishPressure) + // // + // ) + // // + // ; + // if (canRecover) + // { + // // + // sl = position.sl; + // tp = position.entry; + // type = POSITION_TYPE_SELL; + // } + // } + } diff --git a/Experts/x-saherelm.x121.ea.mq5 b/Experts/x-saherelm.x121.ea.mq5 index 88f3a475..152eea44 100644 --- a/Experts/x-saherelm.x121.ea.mq5 +++ b/Experts/x-saherelm.x121.ea.mq5 @@ -91,11 +91,11 @@ input double eaProtectorStartDistanceInPoint = 35; // Protector Start Distance i // // Protector > Hedging Properties ... input group "Hedging"; -input bool eaAllowHedge = false; // Allow Protector to Hedge Positions -input double eaHedgeMinVolumeStep = 0.01; // Minimum Volume Step For Hedge -input int eaMinimumOpenPositionsForHEHedge = 2; // Minimum Open Positions For HE Hedge -input double eaHedgeHEMinProfitPerVolumeStep = 0.2; // Minimum Required Profit For HE Hedge Per Volume Step -input double eaHedgeBEMinProfitPerVolumeStep = 0.05; // Minimum Required Profit For BE Hedge Per Volume Step +input bool eaAllowHedge = false; // Allow Protector to Hedge Positions +input double eaHedgeMinVolumeStep = 0.01; // Minimum Volume Step For Hedge +input int eaMinimumOpenPositionsForHEHedge = 2; // Minimum Open Positions For HE Hedge +input double eaHedgeHEMinProfitPerVolumeStep = 1; // Minimum Required Profit For HE Hedge Per Volume Step +input double eaHedgeBEMinProfitPerVolumeStep = 0.1; // Minimum Required Profit For BE Hedge Per Volume Step // // Protector > In Profit Positions Protecting ... @@ -103,7 +103,7 @@ input group "In Profit Positions Protecting"; input bool eaAllowTrailStopInProfits = true; // Allow Trail Stops for In Profit Positions input bool eaOnlyTrailUnprotectedPositions = true; // Only Trail UnProtected Positions input double eaTrailStopStepsInPoint = 10; // Trail Stop Steps in Point -input int eaRmoveTPOnTrailStep = 0; // Remove Position TP if Trailed specific times +input int eaRmoveTPOnTrailStep = 5; // Remove Position TP if Trailed specific times input double eaPartialCloseOnSpecificPointOfProfit = 0; // Partial Close Position on Specific Points of Profit input double eaPartialCloseVolumeInProfit = 0; // Partial Close Volume @@ -111,7 +111,9 @@ input double eaPartialCloseVolumeInProfit = 0; // Partial Close Volume // Protector > In Drawdown Positions Protecting ... input group "In Drawdown Positions Protecting"; input bool eaAllowRecoverInDrawdowns = true; // Allow Recovery For In Drawdown Positions -input double eaRecoveryMultiplier = 2; // Recovery Volume Multiplier +input double eaRecoveryMultiplier = 1; // Recovery Volume Multiplier +input int eaRecoveryDelayInMinute = 1; // Delay Between Two Recovery in Minutes +input double eaRecoveryDistanceInPoint = 30; // Distance Between Two Recovery in Point input double eaPartialCloseOnSpecificPointOfDrawdown = 0; // Partial Close Position on Specific Points of Drawdown input double eaPartialCloseVolumeInDrawdown = 0; // Partial Close Volume @@ -499,6 +501,8 @@ bool InitialEA() // Protector > In Drawdown Positions Protecting ... eaTradeHandler.AllowRecoverInDrawdowns(eaAllowRecoverInDrawdowns); eaTradeHandler.RecoveryMultiplier(eaRecoveryMultiplier); + eaTradeHandler.RecoveryDelayInMinute(eaRecoveryDelayInMinute); + eaTradeHandler.RecoveryDistanceInPoint(eaRecoveryDistanceInPoint); eaTradeHandler.PartialCloseOnSpecificPointOfDrawdown(eaPartialCloseOnSpecificPointOfDrawdown); eaTradeHandler.PartialCloseVolumeInDrawdown(eaPartialCloseVolumeInDrawdown); diff --git a/pack.js b/pack.js index 6b53bd5d..52dc8a9c 100644 --- a/pack.js +++ b/pack.js @@ -16,7 +16,7 @@ async function handlePack() { // var year = date.getFullYear(); - var month = date.getMonth(); + var month = date.getMonth() + 1; var day = date.getDate(); var hour = date.getHours(); var min = date.getMinutes(); diff --git a/package.json b/package.json index a0cd5064..6fffa526 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "rmClassesEx": "shx --silent rm -r ./Classes/*.ex5 || npm run true", "rmIndicatorsEx": "shx --silent rm -r ./Indicators/*.ex5 || npm run true", "prepareWorkspace": "npm run cleanupEx && npm run compileEA", - "generatePack": "npm run prepareWorkspace && npm run pack" + "generatePack": "npm run prepareWorkspace && npm run pack && npm run cleanupEx && npm run compileIndicators" }, "repository": { "type": "git",