From 4565082b27e2552f803f92ab66785e8412e1e5c8 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Mon, 27 May 2024 10:20:40 +0330 Subject: [PATCH] last ... --- Classes/x-saherelm.x121.xea.class.mq5 | 1201 +++++++------------------ Classes/x-saherelm.xea.class.mq5 | 946 +++++++++++++++++++ Experts/x-test.x121ea.mq5 | 10 +- 3 files changed, 1282 insertions(+), 875 deletions(-) diff --git a/Classes/x-saherelm.x121.xea.class.mq5 b/Classes/x-saherelm.x121.xea.class.mq5 index 4005d0f9..613dfa77 100644 --- a/Classes/x-saherelm.x121.xea.class.mq5 +++ b/Classes/x-saherelm.x121.xea.class.mq5 @@ -22,7 +22,6 @@ // // Imports ... -#include #include "../Classes/x-saherelm.xea.class.mq5" #include "../Classes/x-saherelm.x121.provider.class.mq5" @@ -30,450 +29,6 @@ // Define On Signal Event Handler Type Specified for X5 ... typedef void (*TX121OnSignal)(X121ProviderDescriptor &descriptor); -// -class XSCPositionHolder -{ - // - // Public ... -public: - // - // Props ... - - // - // Constructor(s) ... - - // - XSCPositionHolder() - { - Clear(); - } - - // - // Tools ... - - // - // Cleanup ... - void Clear() - { - Clean(mItems); - } - - // - bool AddItem(XPosition &item) - { - // - bool result = false; - - // - result = item.IsValid(); - if (!result) - { - return result; - } - - // - result = !HasItem(item); - if (!result) - { - return result; - } - - // - AddRef( - item, - mItems // - ); - - // - return result; - } - - // - int AddItems(XPosition &items[]) - { - // - int result = 0; - - // - int itemsCount = ArraySize(items); - if (itemsCount <= 0) - { - return result; - } - - // - for (int i = 0; i < itemsCount; i++) - { - // - XPosition iItem = items[i]; - - // - bool isAdded = AddItem(iItem); - if (isAdded) - { - result++; - } - } - - // - return result; - } - - // - bool AddOrUpdateItem(XPosition &item) - { - // - bool result = false; - - // - result = item.IsValid(); - if (!result) - { - return result; - } - - // - bool hasItem = HasItem(item); - if (!hasItem) - { - result = AddItem(item); - } - else - { - // - result = RemoveItem(item); - if (result) - { - result = AddItem(item); - } - } - - // - return result; - } - - // - int AddOrUpdateItem(XPosition &items[]) - { - // - int result = 0; - - // - int itemsCount = ArraySize(items); - if (itemsCount <= 0) - { - return result; - } - - // - for (int i = 0; i < itemsCount; i++) - { - // - XPosition iItem = items[i]; - - // - bool isAddOrUpdated = AddOrUpdateItem(iItem); - if (isAddOrUpdated) - { - result++; - } - } - - // - return result; - } - - // - bool HasItem(XPosition &item) - { - // - bool result = false; - - // - int itemIDX = FindItem(item); - result = itemIDX >= 0; - - // - return result; - } - - // - int FindItem(XPosition &item) - { - // - int result = -1; - - // - if (!item.IsValid()) - { - return result; - } - - // - int itemsCount = CountItems(); - if (itemsCount <= 0) - { - return result; - } - - // - for (int i = 0; i < itemsCount; i++) - { - // - XPosition iItem = mItems[i]; - - // - bool isSame = IsItemSameAs(item, iItem); - if (isSame) - { - // - result = i; - break; - } - } - - // - return result; - } - - // - bool GetByIndex( - int index, - XPosition &item // - ) - { - // - bool result = false; - - // - NormalizeIndex( - index, - mItems // - ); - - // - item = mItems[index]; - - // - result = item.IsValid(); - - // - return result; - } - - // - bool RemoveItem(XPosition &item) - { - // - bool result = false; - - // - result = HasItem(item); - if (!result) - { - return result; - } - - // - int itemIDX = FindItem(item); - result = ArrayRemove( - mItems, - itemIDX, - 1 // - ); - - // - return result; - } - - // - int RemoveItems(XPosition &items[]) - { - // - int result = 0; - - // - int itemsCount = ArraySize(items); - if (itemsCount <= 0) - { - return result; - } - - // - for (int i = 0; i < itemsCount; i++) - { - // - XPosition iItem = items[i]; - - // - bool isRemoved = RemoveItem(iItem); - if (isRemoved) - { - result++; - } - } - - // - return result; - } - - // - int CountItems() - { - return ArraySize(mItems); - } - - // - bool IsItemSameAs( - XPosition &source, - XPosition &dest // Compare Source with this ... - ) - { - // - bool result = false; - - // - result = - // - dest.IsValid() && - source.IsValid() && - source.symbol == dest.symbol && - source.period == dest.period && - source.ticket == dest.ticket && - source.openAt == dest.openAt && - source.provider == dest.provider - // - ; - - // - return result; - } - - // - // Custom Functions ... - - // - bool GetMaxInDrawdown( - XPosition &item // Result - ) - { - // - bool result = false; - - // - item.Clean(); - - // - int itemsCount = CountItems(); - result = IsValidSize(itemsCount); - if (!result) - { - return result; - } - - // - int maxIDX = -1; - for (int i = 0; i < itemsCount; i++) - { - // - XPosition iItem = mItems[i]; - - // - bool canSelect = - // - iItem.profit < 0 - // - && - // - ( - // - (maxIDX == -1 && !item.IsValid()) - ? true - : item.profit < iItem.profit - // - ) - // - ; - if (canSelect) - { - // - maxIDX = i; - item = iItem; - } - } - - // - result = maxIDX > -1 && item.IsValid(); - - // - return result; - } - - // - bool GetMaxInProfit( - XPosition &item // Result - ) - { - // - bool result = false; - - // - item.Clean(); - - // - int itemsCount = CountItems(); - result = IsValidSize(itemsCount); - if (!result) - { - return result; - } - - // - int maxIDX = -1; - for (int i = 0; i < itemsCount; i++) - { - // - XPosition iItem = mItems[i]; - - // - bool canSelect = - // - iItem.profit > 0 - // - && - // - ( - // - (maxIDX == -1 && !item.IsValid()) - ? true - : item.profit < iItem.profit - // - ) - // - ; - if (canSelect) - { - // - maxIDX = i; - item = iItem; - } - } - - // - result = maxIDX > -1 && item.IsValid(); - - // - return result; - } - - // - // Private ... -private: - // - // Props ... - XPosition mItems[]; -}; - // // Class Definition ... @@ -857,88 +412,41 @@ public: bool equityReached = !mTrader.CheckEquityForTrade(); bool maxAllowedReached = !mTrader.CheckPositionsForTrade(); bool enableEQM = equityReached || maxAllowedReached; - if (!enableEQM) + // if (!enableEQM) + // { + // // + // return; + // } + + // + string mSymbols[]; + XSCPositionHolder *mHolders[]; + int symbolsCount = FilterSymbolBasedPositions( + mSymbols, + mHolders // + ); + + // + for (int i = 0; i < symbolsCount; i++) { // - return; + string iSymbol = mSymbols[i]; + XSCPositionHolder *iHolder = mHolders[i]; + + // + XPosition iMaxInDP; + bool hasMaxInDP = iHolder.GetMaxInDrawdown(iMaxInDP); + if (!hasMaxInDP) + { + continue; + } + + // + // Try to Protect a Position ... + ProtectPosition(iMaxInDP); } // - string eqmMessage = "EQM Enabled: " + "\n"; - if (equityReached) - { - eqmMessage += "- Max Equity Reached ..." + "\n"; - } - if (maxAllowedReached) - { - eqmMessage += "- Max Allowed Positions Reached ..."; - } - // mAlert.Alert(eqmMessage); - - // - // Retrieve InDrawdown Positions Count ... - // Separate based on Directions and Symbols ... - // Accept Only One Signal based on each symbol Indirect ... - // for Fittion Positions to HedgeEnable in Long Time Positions ... - - // // - // int descriptorsCount = CountDescriptors(); - // if (descriptorsCount <= 0) - // { - // return; - // } - - // // - // XSignal supportSignals[]; - // for (int i = 0; i < descriptorsCount; i++) - // { - // // - // X121ProviderDescriptor iDescriptor = mDescriptors[i]; - - // // - // XSignal iSupportSignals[]; - // int iSupportSignalsCount = iDescriptor - // .provider - // .GenerateEQMSupportSignals( - // iSupportSignals // - // ); - // if (iSupportSignalsCount <= 0) - // { - // continue; - // } - - // // - // Copy( - // iSupportSignals, - // supportSignals, - // false // - // ); - // } - - // // - // int supportSignalsCount = ArraySize(supportSignals); - // if (supportSignalsCount <= 0) - // { - // return; - // } - - // // - // ENUM_X_SIGNAL_EXECUTION_RESULT states[]; - // int executedSupports = mTrader.ExecuteSignals( - // supportSignals, - // states, - // ORDER_TIME_GTC, - // NULL, - // false // Ignore Policies ... - // ); - // if (executedSupports > 0) - // { - // // - // string message = "EQM Execute (" + ToString(executedSupports) + ") Support Signals ..."; - - // // - // mAlert.Alert(message); - // } } // @@ -958,6 +466,9 @@ public: return; } + // + double profit = CalculatePositionsProfit(positions); + // // Trail Positions Stop ... for (int i = 0; i < positionsCount; i++) @@ -978,323 +489,331 @@ public: { // // When Position in Profit, Trail SL ... - if (iPosition.profit > 0) + if (profit > 0) { // - XTrail trail; - bool isTrailedBefore = GetSLTrail( - iPosition.ticket, - trail // - ); - - // - if (!isTrailedBefore) + if (iPosition.profit > 0) { // - // Add First Time ... - - // - // Check Position Age ... - int iPositionAge = iPosition.GetAge(iPosition.period); - if (iPositionAge < requiredAgeForTrail) - { - continue; - } - - // - // Check Position Profit Distance ... - double priceDistanceInPoint = PriceToPoint(iPosition.profit / iPosition.volume, iPosition.symbol); - double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol); - if (priceDistance < requiredDistanceForTrail) - { - continue; - } - - // - double slDiff = PointToPrice(priceDistance, iPosition.symbol); - double appliedSL = slDiff / 2; - - // - double sl = - IsLong(iPosition.type) - ? iPosition.sl + slDiff - : iPosition.sl - slDiff; - - // - // double sl = - // IsLong(iPosition.type) - // ? iPosition.entry + appliedSL - // : iPosition.entry - appliedSL; - - // - bool isInit = trail.Init( + XTrail trail; + bool isTrailedBefore = GetSLTrail( iPosition.ticket, - iPosition.type, - iPosition.profit, - iPosition.sl, - sl // + trail // ); - if (!isInit) - { - continue; - } - } - else - { - // - // Update Exists ... // - // Check Profit ... - bool isProfitPassed = iPosition.profit > trail.profit; - if (!isProfitPassed) + if (!isTrailedBefore) { - continue; - } + // + // Add First Time ... - // - // Check Age Distance from Last ... - int age = iBarShift( - iPosition.symbol, - iPosition.period, - trail.time, - false // - ); - if (age < requiredAgeForTrail) - { - continue; - } + // + // Check Position Age ... + int iPositionAge = iPosition.GetAge(iPosition.period); + if (iPositionAge < requiredAgeForTrail) + { + continue; + } - // - double priceDistanceInPoint = PriceToPoint((iPosition.profit - trail.profit) / iPosition.volume, iPosition.symbol); - double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol); - if (priceDistance < (requiredDistanceForTrail / 2)) + // + // Check Position Profit Distance ... + double priceDistanceInPoint = PriceToPoint(iPosition.profit / iPosition.volume, iPosition.symbol); + double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol); + if (priceDistance < requiredDistanceForTrail) + { + continue; + } + + // + double slDiff = PointToPrice(priceDistance, iPosition.symbol); + double appliedSL = slDiff / 2; + + // + double sl = + IsLong(iPosition.type) + ? iPosition.sl + slDiff + : iPosition.sl - slDiff; + + // + // double sl = + // IsLong(iPosition.type) + // ? iPosition.entry + appliedSL + // : iPosition.entry - appliedSL; + + // + bool isInit = trail.Init( + iPosition.ticket, + iPosition.type, + iPosition.profit, + iPosition.sl, + sl // + ); + if (!isInit) + { + continue; + } + } + else { + // + // Update Exists ... + + // + // Check Profit ... + bool isProfitPassed = iPosition.profit > trail.profit; + if (!isProfitPassed) + { + continue; + } + + // + // Check Age Distance from Last ... + int age = iBarShift( + iPosition.symbol, + iPosition.period, + trail.time, + false // + ); + if (age < requiredAgeForTrail) + { + continue; + } + + // + double priceDistanceInPoint = PriceToPoint((iPosition.profit - trail.profit) / iPosition.volume, iPosition.symbol); + double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol); + if (priceDistance < (requiredDistanceForTrail / 2)) + { + // // + // // int positionAge = iPosition.GetAge(iPosition.period); + // if (trail.level >= levelsOnClose) + // { + // // + // string comment = "EQM Close In Profit ..."; + // bool isClosed = mTrader.ClosePositionPack( + // iPosition.ticket, + // iPosition.symbol, + // iPosition.period, + // comment, + // true, + // GetMinProfitPerTrade(), + // GetMinProfitPerVolumeFactor() // + // ); + // if (isClosed) + // { + // // + // RemoveTrail(iPosition.ticket); + + // // + // string message = "EQM Close (" + ToString(iPosition.ticket) + ") In Profit ..."; + // mAlert.Alert(message); + // } + // } + continue; + } + + // + bool isLong = IsLong(iPosition.type); + + // + double slDiff = PointToPrice(priceDistance, iPosition.symbol); + double appliedSL = slDiff / 2; + + // + double selectedValue = iPosition.sl; + + // // + // double selectedValue = // // - // // int positionAge = iPosition.GetAge(iPosition.period); - // if (trail.level >= levelsOnClose) - // { - // // - // string comment = "EQM Close In Profit ..."; - // bool isClosed = mTrader.ClosePositionPack( - // iPosition.ticket, - // iPosition.symbol, - // iPosition.period, - // comment, - // true, - // GetMinProfitPerTrade(), - // GetMinProfitPerVolumeFactor() // - // ); - // if (isClosed) - // { - // // - // RemoveTrail(iPosition.ticket); + // trail.level == 1 || (isLong + // ? iPosition.sl < iPosition.entry + // : iPosition.sl > iPosition.entry) + // ? iPosition.entry + // : iPosition.sl + // // + // ; - // // - // string message = "EQM Close (" + ToString(iPosition.ticket) + ") In Profit ..."; - // mAlert.Alert(message); - // } - // } - continue; + // + double sl = + isLong + ? selectedValue + appliedSL + : selectedValue - appliedSL; + + // + // Update Trail Values ... + bool isUpdated = trail.Update( + sl, + iPosition.profit // + ); + if (!isUpdated) + { + continue; + } } // - bool isLong = IsLong(iPosition.type); - - // - double slDiff = PointToPrice(priceDistance, iPosition.symbol); - double appliedSL = slDiff / 2; - - // - double selectedValue = iPosition.sl; - - // // - // double selectedValue = - // // - // trail.level == 1 || (isLong - // ? iPosition.sl < iPosition.entry - // : iPosition.sl > iPosition.entry) - // ? iPosition.entry - // : iPosition.sl - // // - // ; - - // - double sl = - isLong - ? selectedValue + appliedSL - : selectedValue - appliedSL; - - // - // Update Trail Values ... - bool isUpdated = trail.Update( - sl, - iPosition.profit // - ); - if (!isUpdated) - { - continue; - } - } - - // - if (trail.IsValid()) - { - // - string comment = trail.GenerateTag(); - bool isModified = mTrader.Modify( - trail.ticket, - trail.after, - iPosition.tp, - comment // - ); - if (isModified) + if (trail.IsValid()) { // - RemoveTrail(trail.ticket); + string comment = trail.GenerateTag(); + bool isModified = mTrader.Modify( + trail.ticket, + trail.after, + iPosition.tp, + comment // + ); + if (isModified) + { + // + RemoveTrail(trail.ticket); - // - AddSLTrail(trail); + // + AddSLTrail(trail); - // - string message = "Position (" + ToString(trail.ticket) + ") Trailed SL on Level: " + ToString(trail.level); - mAlert.Alert(message); + // + string message = "Position (" + ToString(trail.ticket) + ") Trailed SL on Level: " + ToString(trail.level); + mAlert.Alert(message); + } } } } // // When Position in Drawdown Trail TP ... - if (iPosition.profit < 0) + if (profit < 0) { // - XTrail trail; - bool isTrailedBefore = GetTPTrail( - iPosition.ticket, - trail // - ); - - // - if (!isTrailedBefore) + if (iPosition.profit < 0) { // - // Add First Time ... - - // - // Check Position Age ... - int iPositionAge = iPosition.GetAge(iPosition.period); - if (iPositionAge < requiredAgeForTrail) - { - continue; - } - - // - // Check Position Profit Distance ... - double priceDistanceInPoint = PriceToPoint(MathAbs(iPosition.profit) / iPosition.volume, iPosition.symbol); - double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol); - if (priceDistance < requiredDistanceForTrail) - { - continue; - } - - // - double tpDiff = PointToPrice(priceDistance, iPosition.symbol); - - // - double tp = - IsLong(iPosition.type) - ? iPosition.tp - tpDiff - : iPosition.tp + tpDiff; - - // - bool isInit = trail.Init( + XTrail trail; + bool isTrailedBefore = GetTPTrail( iPosition.ticket, - iPosition.type, - iPosition.profit, - iPosition.tp, - tp // + trail // ); - if (!isInit) - { - continue; - } - } - else - { - // - // Update Exists ... // - // Check Profit ... - bool isProfitPassed = MathAbs(iPosition.profit) > MathAbs(trail.profit); - if (!isProfitPassed) - { - continue; - } - - // - // Check Age Distance from Last ... - int age = iBarShift( - iPosition.symbol, - iPosition.period, - trail.time, - false // - ); - if (age < requiredAgeForTrail) - { - continue; - } - - // - double priceDistanceInPoint = PriceToPoint((MathAbs(iPosition.profit) - MathAbs(trail.profit)) / iPosition.volume, iPosition.symbol); - double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol); - - // - bool isLong = IsLong(iPosition.type); - - // - double tpDiff = PointToPrice(priceDistance, iPosition.symbol); - - // - double tp = - isLong - ? iPosition.tp - tpDiff - : iPosition.tp + tpDiff; - - // - // Update Trail Values ... - bool isUpdated = trail.Update( - tp, - iPosition.profit // - ); - if (!isUpdated) - { - continue; - } - } - - // - if (trail.IsValid()) - { - // - string comment = trail.GenerateTag(); - bool isModified = mTrader.Modify( - trail.ticket, - iPosition.sl, - trail.after, - comment // - ); - if (isModified) + if (!isTrailedBefore) { // - RemoveTrail(trail.ticket); + // Add First Time ... // - AddTPTrail(trail); + // Check Position Age ... + int iPositionAge = iPosition.GetAge(iPosition.period); + if (iPositionAge < requiredAgeForTrail) + { + continue; + } // - string message = "Position (" + ToString(trail.ticket) + ") Trailed TP on Level: " + ToString(trail.level); - mAlert.Alert(message); + // Check Position Profit Distance ... + double priceDistanceInPoint = PriceToPoint(MathAbs(iPosition.profit) / iPosition.volume, iPosition.symbol); + double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol); + if (priceDistance < requiredDistanceForTrail) + { + continue; + } + + // + double tpDiff = PointToPrice(priceDistance, iPosition.symbol); + + // + double tp = + IsLong(iPosition.type) + ? iPosition.tp - tpDiff + : iPosition.tp + tpDiff; + + // + bool isInit = trail.Init( + iPosition.ticket, + iPosition.type, + iPosition.profit, + iPosition.tp, + tp // + ); + if (!isInit) + { + continue; + } + } + else + { + // + // Update Exists ... + + // + // Check Profit ... + bool isProfitPassed = MathAbs(iPosition.profit) > MathAbs(trail.profit); + if (!isProfitPassed) + { + continue; + } + + // + // Check Age Distance from Last ... + int age = iBarShift( + iPosition.symbol, + iPosition.period, + trail.time, + false // + ); + if (age < requiredAgeForTrail) + { + continue; + } + + // + double priceDistanceInPoint = PriceToPoint((MathAbs(iPosition.profit) - MathAbs(trail.profit)) / iPosition.volume, iPosition.symbol); + double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol); + + // + bool isLong = IsLong(iPosition.type); + + // + double tpDiff = PointToPrice(priceDistance, iPosition.symbol); + + // + double tp = + isLong + ? iPosition.tp - tpDiff + : iPosition.tp + tpDiff; + + // + // Update Trail Values ... + bool isUpdated = trail.Update( + tp, + iPosition.profit // + ); + if (!isUpdated) + { + continue; + } + } + + // + if (trail.IsValid()) + { + // + string comment = trail.GenerateTag(); + bool isModified = mTrader.Modify( + trail.ticket, + iPosition.sl, + trail.after, + comment // + ); + if (isModified) + { + // + RemoveTrail(trail.ticket); + + // + AddTPTrail(trail); + + // + string message = "Position (" + ToString(trail.ticket) + ") Trailed TP on Level: " + ToString(trail.level); + mAlert.Alert(message); + } } } } @@ -1402,14 +921,14 @@ public: // continue; } - else if (profit > 0 && symbolProfit > 0) - { - // - AddRef( - iSignal, - signals // - ); - } + // else if (profit > 0 && symbolProfit > 0) + // { + // // + // AddRef( + // iSignal, + // signals // + // ); + // } } // @@ -1461,6 +980,8 @@ public: { // string message = "Position (" + ToString(track.ticket) + ", " + track.symbol + ") Dropped in Profit ..."; + + // mAlert.Alert(message); } @@ -1470,6 +991,8 @@ public: { // string message = "Position (" + ToString(track.ticket) + ", " + track.symbol + ") Dropped in Drawdown ..."; + + // mAlert.Alert(message); } @@ -1497,78 +1020,16 @@ public: // // Here i Have to Detect In DrawDown Positions ... - // - XPosition positions[]; - int positionsCount = mTrader.GetInDrawdownPositions( - positions); - if (!IsValidSize(positionsCount)) - { - return; - } - - // - // Create a HashMap for Holding Positions ... - CHashMap symbolMap; - - // - // Loop Through Positions ... - for (int i = 0; i < positionsCount; i++) - { - // - XPosition iPosition = positions[i]; - - // - bool hasIKey = symbolMap.ContainsKey(iPosition.symbol); - - // - // Empty Class Pointer ... - XSCPositionHolder *mHolder = NULL; - - // - // Add new to Map ... - if (!hasIKey) - { - // - mHolder = new XSCPositionHolder(); - if (symbolMap.TrySetValue(iPosition.symbol, mHolder)) - { - mHolder.AddOrUpdateItem(iPosition); - } - } - // - // Update Exists in Map ... - else - { - // - if (symbolMap.TryGetValue(iPosition.symbol, mHolder)) - { - mHolder.AddOrUpdateItem(iPosition); - } - } - } - - // - // Now we Have a Map which Filled Based on Separate Symbols and InDrawDown Positions ... - int mapCount = symbolMap.Count(); - if (!IsValidSize(mapCount)) - { - return; - } - // string mSymbols[]; XSCPositionHolder *mHolders[]; - mapCount = symbolMap.CopyTo( + int symbolsCount = FilterSymbolBasedPositions( mSymbols, mHolders // ); - if (!IsValidSize(mapCount)) - { - return; - } // - for (int i = 0; i < mapCount; i++) + for (int i = 0; i < symbolsCount; i++) { // string iSymbol = mSymbols[i]; diff --git a/Classes/x-saherelm.xea.class.mq5 b/Classes/x-saherelm.xea.class.mq5 index f19e932c..2d59995d 100644 --- a/Classes/x-saherelm.xea.class.mq5 +++ b/Classes/x-saherelm.xea.class.mq5 @@ -21,6 +21,7 @@ // // Imports ... +#include #include "../Classes/x-saherelm.base.class.mq5" #include "../Classes/x-saherelm.xalert.class.mq5" #include "../Classes/x-saherelm.xtrade.class.mq5" @@ -1265,6 +1266,870 @@ private: } }; +// +class XSCPositionHolder +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor(s) ... + + // + XSCPositionHolder() + { + Clear(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clear() + { + Clean(mItems); + } + + // + bool AddItem(XPosition &item) + { + // + bool result = false; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + result = !HasItem(item); + if (!result) + { + return result; + } + + // + AddRef( + item, + mItems // + ); + + // + return result; + } + + // + int AddItems(XPosition &items[]) + { + // + int result = 0; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = items[i]; + + // + bool isAdded = AddItem(iItem); + if (isAdded) + { + result++; + } + } + + // + return result; + } + + // + bool AddOrUpdateItem(XPosition &item) + { + // + bool result = false; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + bool hasItem = HasItem(item); + if (!hasItem) + { + result = AddItem(item); + } + else + { + // + result = RemoveItem(item); + if (result) + { + result = AddItem(item); + } + } + + // + return result; + } + + // + int AddOrUpdateItem(XPosition &items[]) + { + // + int result = 0; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = items[i]; + + // + bool isAddOrUpdated = AddOrUpdateItem(iItem); + if (isAddOrUpdated) + { + result++; + } + } + + // + return result; + } + + // + bool HasItem(XPosition &item) + { + // + bool result = false; + + // + int itemIDX = FindItem(item); + result = itemIDX >= 0; + + // + return result; + } + + // + int FindItem(XPosition &item) + { + // + int result = -1; + + // + if (!item.IsValid()) + { + return result; + } + + // + int itemsCount = CountItems(); + if (itemsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isSame = IsItemSameAs(item, iItem); + if (isSame) + { + // + result = i; + break; + } + } + + // + return result; + } + + // + bool GetByIndex( + int index, + XPosition &item // + ) + { + // + bool result = false; + + // + NormalizeIndex( + index, + mItems // + ); + + // + item = mItems[index]; + + // + result = item.IsValid(); + + // + return result; + } + + // + bool RemoveItem(XPosition &item) + { + // + bool result = false; + + // + result = HasItem(item); + if (!result) + { + return result; + } + + // + int itemIDX = FindItem(item); + result = ArrayRemove( + mItems, + itemIDX, + 1 // + ); + + // + return result; + } + + // + int RemoveItems(XPosition &items[]) + { + // + int result = 0; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = items[i]; + + // + bool isRemoved = RemoveItem(iItem); + if (isRemoved) + { + result++; + } + } + + // + return result; + } + + // + int CountItems() + { + return ArraySize(mItems); + } + + // + bool IsItemSameAs( + XPosition &source, + XPosition &dest // Compare Source with this ... + ) + { + // + bool result = false; + + // + result = + // + dest.IsValid() && + source.IsValid() && + source.symbol == dest.symbol && + source.period == dest.period && + source.ticket == dest.ticket && + source.openAt == dest.openAt && + source.provider == dest.provider + // + ; + + // + return result; + } + + // + // Custom Functions ... + + // + bool GetMaxInDrawdown( + XPosition &item // Result + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + int maxIDX = -1; + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool canSelect = + // + iItem.profit < 0 + // + && + // + ( + // + (maxIDX == -1 && !item.IsValid()) + ? true + : item.profit < iItem.profit + // + ) + // + ; + if (canSelect) + { + // + maxIDX = i; + item = iItem; + } + } + + // + result = maxIDX > -1 && item.IsValid(); + + // + return result; + } + + // + bool GetMaxInProfit( + XPosition &item // Result + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + int maxIDX = -1; + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool canSelect = + // + iItem.profit > 0 + // + && + // + ( + // + (maxIDX == -1 && !item.IsValid()) + ? true + : item.profit < iItem.profit + // + ) + // + ; + if (canSelect) + { + // + maxIDX = i; + item = iItem; + } + } + + // + result = maxIDX > -1 && item.IsValid(); + + // + return result; + } + + // + bool GetFarestEntry( + XPosition &item, // Result + string symbol = NULL, + string provider = NULL, + ENUM_TIMEFRAMES period = NULL, + ENUM_POSITION_TYPE type = NULL // + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isFiltersPassed = + // + iItem.IsFiltersPassed( + symbol, + provider, + period, + type // + ) + // + ; + + // + if (!isFiltersPassed) + { + continue; + } + + // + // Do Additional Filtering ... + bool isValidEntry = + // + !item.IsValid() + ? true + : item.entry < iItem.entry + // + ; + if (isValidEntry) + { + // + item = iItem; + } + } + + // + result = item.IsValid(); + + // + return result; + } + + // + bool GetNearestEntry( + XPosition &item, // Result + string symbol = NULL, + string provider = NULL, + ENUM_TIMEFRAMES period = NULL, + ENUM_POSITION_TYPE type = NULL // + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isFiltersPassed = + // + iItem.IsFiltersPassed( + symbol, + provider, + period, + type // + ) + // + ; + + // + if (!isFiltersPassed) + { + continue; + } + + // + // Do Additional Filtering ... + bool isValidEntry = + // + !item.IsValid() + ? true + : item.entry > iItem.entry + // + ; + if (isValidEntry) + { + // + item = iItem; + } + } + + // + result = item.IsValid(); + + // + return result; + } + + // + bool GetFarestSL( + XPosition &item, // Result + string symbol = NULL, + string provider = NULL, + ENUM_TIMEFRAMES period = NULL, + ENUM_POSITION_TYPE type = NULL // + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isFiltersPassed = + // + iItem.IsFiltersPassed( + symbol, + provider, + period, + type // + ) + // + ; + + // + if (!isFiltersPassed) + { + continue; + } + + // + // Do Additional Filtering ... + bool isValidEntry = + // + !item.IsValid() + ? true + : item.sl < iItem.sl + // + ; + if (isValidEntry) + { + // + item = iItem; + } + } + + // + result = item.IsValid(); + + // + return result; + } + + // + bool GetNearestSL( + XPosition &item, // Result + string symbol = NULL, + string provider = NULL, + ENUM_TIMEFRAMES period = NULL, + ENUM_POSITION_TYPE type = NULL // + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isFiltersPassed = + // + iItem.IsFiltersPassed( + symbol, + provider, + period, + type // + ) + // + ; + + // + if (!isFiltersPassed) + { + continue; + } + + // + // Do Additional Filtering ... + bool isValidEntry = + // + !item.IsValid() + ? true + : item.sl > iItem.sl + // + ; + if (isValidEntry) + { + // + item = iItem; + } + } + + // + result = item.IsValid(); + + // + return result; + } + + // + bool GetFarestTP( + XPosition &item, // Result + string symbol = NULL, + string provider = NULL, + ENUM_TIMEFRAMES period = NULL, + ENUM_POSITION_TYPE type = NULL // + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isFiltersPassed = + // + iItem.IsFiltersPassed( + symbol, + provider, + period, + type // + ) + // + ; + + // + if (!isFiltersPassed) + { + continue; + } + + // + // Do Additional Filtering ... + bool isValidEntry = + // + !item.IsValid() + ? true + : item.tp < iItem.tp + // + ; + if (isValidEntry) + { + // + item = iItem; + } + } + + // + result = item.IsValid(); + + // + return result; + } + + // + bool GetNearestTP( + XPosition &item, // Result + string symbol = NULL, + string provider = NULL, + ENUM_TIMEFRAMES period = NULL, + ENUM_POSITION_TYPE type = NULL // + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isFiltersPassed = + // + iItem.IsFiltersPassed( + symbol, + provider, + period, + type // + ) + // + ; + + // + if (!isFiltersPassed) + { + continue; + } + + // + // Do Additional Filtering ... + bool isValidEntry = + // + !item.IsValid() + ? true + : item.tp > iItem.tp + // + ; + if (isValidEntry) + { + // + item = iItem; + } + } + + // + result = item.IsValid(); + + // + return result; + } + + // + // Private ... +private: + // + // Props ... + XPosition mItems[]; +}; + // // Class Definition ... @@ -2973,6 +3838,87 @@ protected: } } + // + // Position Filter ... + + // + int FilterSymbolBasedPositions( + string &symbols[], // Hold Symbols ... + XSCPositionHolder *&holders[] // Holder Class Instances ... + ) + { + // + int result = 0; + + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions( + positions // + ); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Create a HashMap for Holding Positions ... + CHashMap symbolMap; + + // + // Loop Through Positions ... + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool hasIKey = symbolMap.ContainsKey(iPosition.symbol); + + // + // Empty Class Pointer ... + XSCPositionHolder *mHolder = NULL; + + // + // Add new to Map ... + if (!hasIKey) + { + // + mHolder = new XSCPositionHolder(); + if (symbolMap.TrySetValue(iPosition.symbol, mHolder)) + { + mHolder.AddOrUpdateItem(iPosition); + } + } + // + // Update Exists in Map ... + else + { + // + if (symbolMap.TryGetValue(iPosition.symbol, mHolder)) + { + mHolder.AddOrUpdateItem(iPosition); + } + } + } + + // + // Now we Have a Map which Filled Based on Separate Symbols and InDrawDown Positions ... + int mapCount = symbolMap.Count(); + if (!IsValidSize(mapCount)) + { + return result; + } + + // + result = symbolMap.CopyTo( + symbols, + holders // + ); + + // + return result; + } + // // Private ... private: diff --git a/Experts/x-test.x121ea.mq5 b/Experts/x-test.x121ea.mq5 index b8a5774d..fdddc9fe 100644 --- a/Experts/x-test.x121ea.mq5 +++ b/Experts/x-test.x121ea.mq5 @@ -31,14 +31,14 @@ // // Inputs ... -long x121EAMagicNumber = 78692110; // Magic Number -int x121EASlippage = 10; // Slippgae -string x121EASymbols = "EURUSDb,USDCHFb,USDJPYb,GBPUSDb,XAUUSDb,AUDUSDb,USDCADb,NZDUSDb"; // Symbols +long x121EAMagicNumber = 78692110; // Magic Number +int x121EASlippage = 10; // Slippgae +string x121EASymbols = "EURUSDb,USDCHFb,USDJPYb,GBPUSDb"; // Symbols // bool x121EAAllowLong = true; // Allow Long Trades bool x121EAAllowShort = true; // Allow Short Trades int x121EAManageInterval = 0; // Manager Check Intervals Seconds -int x121EAMaxAllowedPositions = 10; // Max Allowed Positions +int x121EAMaxAllowedPositions = 5; // Max Allowed Positions double x121EAMaxAllowedSpread = 0; // Max Allowed Spred for Opening Trades double x121EAMinProfitPerTrade = 3; // Min Profit Per Trade based On Volume Factor (Hedge) double x121EAMinProfitPerVolumeFactor = 0.01; // Min Volume Factor for Calculating Profit (Hedge) @@ -291,7 +291,7 @@ void ConfigureDescriptor( // // XHK ... iDescriptor.inputs.hkInputs.drawHikenAshi = false; - iDescriptor.inputs.hkInputs.drawSmoothedHikenAshi = true; + iDescriptor.inputs.hkInputs.drawSmoothedHikenAshi = false; // // XMC ...