From f048bd3d37394dc4f9cb1a25f323face521efef2 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Wed, 26 Jun 2024 18:04:28 +0330 Subject: [PATCH] last ... --- Classes/x-saherelm.x121.setup.xea.mq5 | 438 ++++++++++++++++++-------- Documents/BKP/usefull.mq5 | 206 ++++++++++++ Experts/x-saherelm.x121.ea.mq5 | 28 +- Libraries/x-saherelm.xtrade.lib.mq5 | 307 +++++++++++++++++- 4 files changed, 814 insertions(+), 165 deletions(-) diff --git a/Classes/x-saherelm.x121.setup.xea.mq5 b/Classes/x-saherelm.x121.setup.xea.mq5 index 0c7c3d84..7b27c9b6 100644 --- a/Classes/x-saherelm.x121.setup.xea.mq5 +++ b/Classes/x-saherelm.x121.setup.xea.mq5 @@ -298,7 +298,29 @@ struct XTradeInfo } // - string ToString() + string GetSignalFileName() + { + // + string result = NULL; + + // + result = + // + symbol + "\\" + + ToString(type) + "\\" + + provider + "_" + + ToFormatString(time) + // + ; + + // + return result; + } + + // + string ToString( + bool onlySignals = false // + ) { // string result = NULL; @@ -346,7 +368,9 @@ struct XTradeInfo // result = // - ToString("Ticket", ticket) + + (onlySignals + ? "" + : ToString("Ticket", ticket)) + ToString("Symbol", symbol) + ToString("Period", period) + ToString("Entry", entry) + @@ -354,14 +378,16 @@ struct XTradeInfo ToString("Type", ToString(type)) + ToString("Time", time) + ToString("Pushers", pushers) + - "-------------" + "\n" + - ToString("Volume", volume) + - ToString("Profit", profit) + - ToString("Commission", commission) + - ToString("Swap", swap) + - ToString("End Time", endTime) + - ToString("Age", age) + - ToString("Message", message) + + (onlySignals + ? "" + : "-------------" + "\n" + + ToString("Volume", volume) + + ToString("Profit", profit) + + ToString("Commission", commission) + + ToString("Swap", swap) + + ToString("End Time", endTime) + + ToString("Age", age) + + ToString("Message", message)) + "-------------" + "\n" + "Conditions" + "\n" + "-------------" + "\n" + @@ -932,6 +958,37 @@ public: return result; } + // + bool SaveSignal(XTradeInfo &item) + { + // + bool result = false; + + // + string content = item.ToString(); + result = IsValid(content); + if (!result) + { + return result; + } + + // + int mHandler = GetSignalFileHandlerForWrite(item); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + // // Protected ... protected: @@ -964,7 +1021,32 @@ private: // result = // - mPath + "\\" + fileName + ".x121.log" + mPath + "\\" + "Trades" + "\\" + fileName + ".x121.log" + // + ; + + // + return result; + } + + // + string GetSignalFilePath(XTradeInfo &item) + { + // + string fileName = item.GetSignalFileName(); + + // + return GetSignalFilePath(fileName); + } + string GetSignalFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + mPath + "\\" + "Signals" + "\\" + fileName + ".x121.log" // ; @@ -1015,6 +1097,50 @@ private: // return result; } + + // + int GetSignalFileHandlerForRead(XTradeInfo &item) + { + // + int result = INVALID_HANDLE; + + // + string filePath = GetSignalFilePath(item); + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_TXT // + ); + + // + return result; + } + int GetSignalFileHandlerForWrite(XTradeInfo &item) + { + // + int result = INVALID_HANDLE; + + // + string filePath = GetSignalFilePath(item); + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT // + ); + + // + return result; + } }; // @@ -1063,6 +1189,65 @@ public: mSave = value; } + // + bool GetSaveSignalsOnly() + { + return mSaveSignalsOnly; + } + + // + void SetSaveSignalsOnly(bool value) + { + mSaveSignalsOnly = value; + } + + // + // Hedging ... + + // + double MinProfitPerTrade() + { + return mMinProfitPerTrade; + } + + // + void MinProfitPerTrade(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMinProfitPerTrade = value; + } + + // + double MinProfitPerVolumeFactor() + { + return mMinProfitPerVolumeFactor; + } + + // + void MinProfitPerVolumeFactor(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + if (value > 0 && value < 0.01) + { + value = 0.01; + } + + // + mMinProfitPerVolumeFactor = value; + } + // // Trailling Stop ... @@ -1684,6 +1869,12 @@ public: info, data // ); + + // + if (GetSaveSignalsOnly()) + { + collector.SaveSignal(info); + } } // @@ -2162,7 +2353,13 @@ protected: XTradeInfoCollector *collector; // - bool mSave; // Save Results ... + bool mSave; // Save Results ... + bool mSaveSignalsOnly; // Save Only Signals and COnditions + + // + // Hedging ... + double mMinProfitPerTrade; // Minimum Required Profit for Hedging + double mMinProfitPerVolumeFactor; // Minimum Required Profit for Hedging Per Volume // // Trailling ... @@ -3497,6 +3694,18 @@ public: mTradeHandler.SetSave(value); } + // + bool SaveSignalsOnly() + { + return mTradeHandler.GetSaveSignalsOnly(); + } + + // + void SaveSignalsOnly(bool value) + { + mTradeHandler.SetSaveSignalsOnly(value); + } + // double MinFreeMargingForOpenTrades() { @@ -3516,6 +3725,37 @@ public: mMinFreeMargingForOpenTrades = value; } + // + // Hedging ... + + // + double MinProfitPerTrade() + { + return mTradeHandler.MinProfitPerTrade(); + } + + // + void MinProfitPerTrade(double value) + { + // + MinRequiredProfitPerTrade(value); + mTradeHandler.MinProfitPerTrade(value); + } + + // + double MinProfitPerVolumeFactor() + { + return mTradeHandler.MinProfitPerVolumeFactor(); + } + + // + void MinProfitPerVolumeFactor(double value) + { + // + MinRequiredProfitPerVolumeFactor(value); + mTradeHandler.MinProfitPerVolumeFactor(value); + } + // // Overrides ... @@ -4384,7 +4624,7 @@ public: bool HandleStateManagement(XSignal &signals[]) override { // - const bool result = false; + bool result = false; // // Do all State Management here ... @@ -4395,7 +4635,11 @@ public: // Youngest Age of Positions longest as enough // Make State of Signalling to Force State for Recieving // Signal and Clear their Tp and SL for allowing hedges ... - EQMHandleForceState(); + EQMHandleForceState(signals); + if (mForce) + { + result = true; + } // DoHedge(); @@ -4582,6 +4826,9 @@ protected: // Alert(message); + // + EQMHandleForceState(signals); + // return; } @@ -4843,6 +5090,7 @@ private: // SaveResults(false); + SaveSignalsOnly(true); } // @@ -4990,7 +5238,8 @@ private: XSignal supports[]; int supportsCount = mTradeHandler.DoProtect( supports, - mSetups); + mSetups // + ); // if (IsValidSize(supportsCount)) @@ -5038,146 +5287,65 @@ private: // // Handle Force State Management ... - void EQMHandleForceState() + bool mForce; + void EQMHandleForceState(XSignal &forceSignals[]) { // + // Validate Force Marigin ... + double marigin = mTrader.mAccount.GetMargin(); + double minFreeMarigin = MinFreeMargingForOpenTrades(); + double forceMargin = 3 * minFreeMarigin; // TODO: Make It Configurable + + // + // Retrieving Positions ... XPosition positions[]; int positionsCount = mTrader.GetPositions(positions); - if (!IsValidSize(positionsCount) || positionsCount <= 4) + if (!IsValidSize(positionsCount)) { return; } // - double minRequiredProfitPerTrade = MinRequiredProfitPerTrade(); - double minRequiredProfitPerVolumeFactor = MinRequiredProfitPerVolumeFactor(); + XPosition oldest; + int oldestAge = GetOldest( + oldest, + positions // + ); + + // + mForce = marigin >= forceMargin && oldestAge >= 288; + if (!mForce) + { + return; + } + + // + double minProfitPerTrade = MinProfitPerTrade(); + double minProfitPerVolumeFactor = MinProfitPerVolumeFactor(); // double profit = SpecifiedCalculatePositionsProfit(positions); double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( positions, - minRequiredProfitPerTrade, - minRequiredProfitPerVolumeFactor // + minProfitPerTrade, + minProfitPerVolumeFactor // ); // - bool canClose = - profit > 0 && - (profit == requiredProfit || - profit >= requiredProfit / 2); - if (canClose) { - DoEQMForceClose(); + XSymbolPositions symbolPositions[]; + int symbolPositionsCount = ExtractSymbolPositions( + positions, + symbolPositions, + minProfitPerTrade, + minProfitPerVolumeFactor // + ); + if (!IsValidSize(symbolPositionsCount)) + { + return; } - return; - - // // - // XPosition positions[]; - // int positionsCount = mTrader.GetPositions(positions); - // if (!IsValidSize(positionsCount)) - // { - // // - // EQMClearAllForceStates(); - - // // - // return; - // } - - // // - // // Search For Force State Per Each Setup ... - // // - // int forceCount = 0; - // int setupsCount = CountSetups(); - // if (IsValidSize(setupsCount)) - // { - // // - // int maxAllowed = MaxAllowedTrades(); - // bool perDirection = UseMaxAllowedPerDirection(); - - // // - // for (int i = 0; i < setupsCount; i++) - // { - // // - // string iSymbol = mSetups[i].GetSymbol(); - // ENUM_TIMEFRAMES iPeriod = mSetups[i].GetPeriod(); - - // // - // XPosition iPositions[]; - // int iPositionsCount = mTrader.GetPositions( - // iPositions, - // iSymbol, - // NULL, // All Providers ... - // NULL, // All Periods ... - // NULL, // All Types ... - // true // Filter By Magic ... - // ); - // if (!IsValidSize(iPositionsCount)) - // { - // continue; - // } - - // // - // // Counting Positions ... - // int longs; - // double longProfits; - // double longVolumes; - - // // - // int shorts; - // double shortProfits; - // double shortVolumes; - - // // - // CountPositions( - // iPositions, - // // - // longs, - // longProfits, - // longVolumes, - // // - // shorts, - // shortProfits, - // shortVolumes // - // ); - - // // - // bool isMaxReached = - // maxAllowed <= 0 - // ? false - // : !perDirection - // ? longs + shorts >= maxAllowed - // : longs >= maxAllowed && shorts >= maxAllowed; - // double volumeSummary = longVolumes + shortVolumes; - // double profitsSummary = longProfits + shortProfits; - - // // - // bool isIInForce = - // // - // maxAllowed <= 0 - // ? profitsSummary < 0 && - // longVolumes == shortVolumes - // : isMaxReached && - // profitsSummary < 0 && - // longVolumes == shortVolumes - // // - // ; - // if (isIInForce) - // { - // // - // forceCount++; - // mSetups[i].ForceState(true); - // } - // } - // } - - // // - // bool isForce = forceCount >= 1; - // if (!isForce) - // { - // return; - // } - // + Log("symbolPositionsCount: " + ToString(symbolPositionsCount)); } // diff --git a/Documents/BKP/usefull.mq5 b/Documents/BKP/usefull.mq5 index 0396f0c5..aa21b405 100644 --- a/Documents/BKP/usefull.mq5 +++ b/Documents/BKP/usefull.mq5 @@ -4866,3 +4866,209 @@ int pivotsCount = ArraySize(pivots); } } } + +//////////////////////////////////////////////////////////////////////////////////// + + void EQMHandleForceState() + { + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions(positions); + if (!IsValidSize(positionsCount) || positionsCount <= 4) + { + return; + } + + // + double minRequiredProfitPerTrade = MinRequiredProfitPerTrade(); + double minRequiredProfitPerVolumeFactor = MinRequiredProfitPerVolumeFactor(); + + // + double profit = SpecifiedCalculatePositionsProfit(positions); + double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( + positions, + minRequiredProfitPerTrade, + minRequiredProfitPerVolumeFactor // + ); + + // + bool canClose = + profit > 0 && + (profit == requiredProfit || + profit >= requiredProfit / 2); + if (canClose) + { + DoEQMForceClose(); + } + + return; + + // // + // XPosition positions[]; + // int positionsCount = mTrader.GetPositions(positions); + // if (!IsValidSize(positionsCount)) + // { + // // + // EQMClearAllForceStates(); + + // // + // return; + // } + + // // + // // Search For Force State Per Each Setup ... + // // + // int forceCount = 0; + // int setupsCount = CountSetups(); + // if (IsValidSize(setupsCount)) + // { + // // + // int maxAllowed = MaxAllowedTrades(); + // bool perDirection = UseMaxAllowedPerDirection(); + + // // + // for (int i = 0; i < setupsCount; i++) + // { + // // + // string iSymbol = mSetups[i].GetSymbol(); + // ENUM_TIMEFRAMES iPeriod = mSetups[i].GetPeriod(); + + // // + // XPosition iPositions[]; + // int iPositionsCount = mTrader.GetPositions( + // iPositions, + // iSymbol, + // NULL, // All Providers ... + // NULL, // All Periods ... + // NULL, // All Types ... + // true // Filter By Magic ... + // ); + // if (!IsValidSize(iPositionsCount)) + // { + // continue; + // } + + // // + // // Counting Positions ... + // int longs; + // double longProfits; + // double longVolumes; + + // // + // int shorts; + // double shortProfits; + // double shortVolumes; + + // // + // CountPositions( + // iPositions, + // // + // longs, + // longProfits, + // longVolumes, + // // + // shorts, + // shortProfits, + // shortVolumes // + // ); + + // // + // bool isMaxReached = + // maxAllowed <= 0 + // ? false + // : !perDirection + // ? longs + shorts >= maxAllowed + // : longs >= maxAllowed && shorts >= maxAllowed; + // double volumeSummary = longVolumes + shortVolumes; + // double profitsSummary = longProfits + shortProfits; + + // // + // bool isIInForce = + // // + // maxAllowed <= 0 + // ? profitsSummary < 0 && + // longVolumes == shortVolumes + // : isMaxReached && + // profitsSummary < 0 && + // longVolumes == shortVolumes + // // + // ; + // if (isIInForce) + // { + // // + // forceCount++; + // mSetups[i].ForceState(true); + // } + // } + // } + + // // + // bool isForce = forceCount >= 1; + // if (!isForce) + // { + // return; + // } + + // + } + + + // + void EQMHandleForceSignals( + XSignal &signals[] // + ) + { + // + // Validate Signals Count ... + int signalsCount = ArraySize(signals); + if (!IsValidSize(signalsCount)) + { + return; + } + + // + // Validate Force Marigin ... + double marigin = mTrader.mAccount.GetMargin(); + double forceMargin = 100; // TODO: Make It Configurable + bool isInForceMarigin = marigin >= forceMargin; + if (!isInForceMarigin) + { + return; + } + + // + // Now we are Sure we in Force State Margin amd we Have Signals ... + + // + // here we Must Symbol Categorized Positions ... + int setupsCount = CountSetups(); + if (!IsValidSize(setupsCount)) + { + return; + } + + // + // Retrieving Positions ... + XPosition positions[]; + int positionsCount = mTrader.GetPositions(positions); + if (!IsValidSize(positionsCount)) + { + return; + } + + // + XSymbolPositions symbolPositions[]; + int symbolPositionsCount = ExtractSymbolPositions( + positions, + symbolPositions // + ); + if (!IsValidSize(symbolPositionsCount)) + { + return; + } + + // + Log("symbolPositionsCount: " + ToString(symbolPositionsCount)); + + // + } diff --git a/Experts/x-saherelm.x121.ea.mq5 b/Experts/x-saherelm.x121.ea.mq5 index da93cc7b..b3ed0529 100644 --- a/Experts/x-saherelm.x121.ea.mq5 +++ b/Experts/x-saherelm.x121.ea.mq5 @@ -44,15 +44,15 @@ input group "Signals"; //,USDCHFb,EURCHFb,USDJPYb,EURJPYb,GBPUSDb // EURUSDb,USDCHFb,EURCHFb,USDJPYb,EURJPYb,GBPUSDb // EURUSDb,USDCHFb,EURCHFb,USDJPYb,EURJPYb,GBPUSDb,XAUUSDb,NZDUSDb,AUDUSDb,USDCADb,BTCUSD,ETHUSD -input string x121EASymbols = "USDCHFb,EURCHFb,USDJPYb,EURJPYb,GBPUSDb"; // Symbols -input bool x121EAUseAllSymbols = false; // Use All Available Symbols -input bool x121EAUseAllWatchListSymbols = false; // Use All WatchList Symbols -input bool x121EAAllowLong = true; // Allow Long Trades -input bool x121EAAllowShort = true; // Allow Short Trades -input bool x121EAExecuteSignalsOnBreakout = false; // Execute Signals On Breakouts -input int x121EADelayBetweenTwoSignal = 10; // Delay Between two Same Signals -input int x121EAReuiredSignalVerifications = 3; // Required Verifications for Signals -input bool x121EAGetVerificationFromOtherTimeFrames = true; // Get Verifications from Other Time Frames +input string x121EASymbols = "EURUSDb,USDCHFb,EURCHFb,USDJPYb,EURJPYb,GBPUSDb"; // Symbols +input bool x121EAUseAllSymbols = false; // Use All Available Symbols +input bool x121EAUseAllWatchListSymbols = false; // Use All WatchList Symbols +input bool x121EAAllowLong = true; // Allow Long Trades +input bool x121EAAllowShort = true; // Allow Short Trades +input bool x121EAExecuteSignalsOnBreakout = false; // Execute Signals On Breakouts +input int x121EADelayBetweenTwoSignal = 10; // Delay Between two Same Signals +input int x121EAReuiredSignalVerifications = 3; // Required Verifications for Signals +input bool x121EAGetVerificationFromOtherTimeFrames = true; // Get Verifications from Other Time Frames // // Risk Management ... @@ -60,8 +60,8 @@ input group "Risk Management"; input double x121EAVolume = 0.01; // Static Volume input double x121EATPPoint = 1000; // TP Point input double x121EASLPoint = 1000; // SL Point -input int x121EAMaxAllowedTrades = 2; // Max Allowed Positions Per Symbol -input int x121EAMinFreeMargingForOpenTrades = 500; // Min Margin For Opening Trades +input int x121EAMaxAllowedTrades = 0; // Max Allowed Positions Per Symbol +input int x121EAMinFreeMargingForOpenTrades = 50; // Min Margin For Opening Trades input bool x121EAUseMaxAllowedPerDirection = true; // Use Max Allowed Positions Per Direction input bool x121EAIgnoreSL = true; // Ignore Calculated SL input bool x121EAIgnoreTP = true; // Ignore Calculated TP @@ -377,8 +377,8 @@ bool InitialEA() // // Hedging ... x121EA.RestingAfterHedge(x121EARestingAfterHedge); - x121EA.MinRequiredProfitPerTrade(x121EAMinRequiredProfitPerTrade); - x121EA.MinRequiredProfitPerVolumeFactor(x121EAMinRequiredProfitPerVolumeFactor); + x121EA.MinProfitPerTrade(x121EAMinRequiredProfitPerTrade); + x121EA.MinProfitPerVolumeFactor(x121EAMinRequiredProfitPerVolumeFactor); // // Alert ... @@ -438,7 +438,7 @@ void X121PreConfigureStyles(X121SetupInputs &inputs) // // XATSL ... - inputs.atslInputs.show = true; + inputs.atslInputs.show = false; // // XSLN ... diff --git a/Libraries/x-saherelm.xtrade.lib.mq5 b/Libraries/x-saherelm.xtrade.lib.mq5 index bdfd60f2..a53e7e16 100644 --- a/Libraries/x-saherelm.xtrade.lib.mq5 +++ b/Libraries/x-saherelm.xtrade.lib.mq5 @@ -637,12 +637,12 @@ struct XPosition // // Check Items Passed Specific Filters or not ... bool IsFiltersPassed( - string mSymbol = NULL, // Trading Symbol - string mProvider = NULL, // Signal Provider - ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe ENUM_X_POSITION_TYPES mType = NULL, // Long (Buy), Short (Sell) - ulong mMagic = NULL, // Magic Number - bool mFilterByMagic = true // Get Only Self Open Positions + ulong mMagic = NULL, // Magic Number + bool mFilterByMagic = true // Get Only Self Open Positions ) { // @@ -1922,13 +1922,13 @@ struct XOrder // // Check Items Passed Specific Filters or not ... bool IsFiltersPassed( - string mSymbol = NULL, // Trading Symbol - string mProvider = NULL, // Signal Provider - ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe ENUM_X_POSITION_TYPES mType = NULL, // Long (Buy), Short (Sell) - ENUM_ORDER_STATE mState = NULL, // Order State - ulong mMagic = NULL, // Magic Number - bool mFilterByMagic = true // Get Only Self Open Positions + ENUM_ORDER_STATE mState = NULL, // Order State + ulong mMagic = NULL, // Magic Number + bool mFilterByMagic = true // Get Only Self Open Positions ) { // @@ -2476,7 +2476,7 @@ struct XGuard string symbol; // Trading Symbol ... string provider; // Signal Provider ... ENUM_TIMEFRAMES period; // Trading Timeframe ... - ENUM_X_POSITION_TYPES type; // Position Type ... + ENUM_X_POSITION_TYPES type; // Position Type ... ENUM_X_GUARD_ACTIONS action; // Which Action to Do ... // @@ -2496,11 +2496,11 @@ struct XGuard // // Global Initializer ... bool Init( - string mSymbol, // Trading Symbol ... - ENUM_TIMEFRAMES mPeriod, // Trading Timeframe ... - ENUM_X_GUARD_ACTIONS mAction, // Which Action to Do ... + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod, // Trading Timeframe ... + ENUM_X_GUARD_ACTIONS mAction, // Which Action to Do ... ENUM_X_POSITION_TYPES mType = NULL, // Position Type ... - string mProvider = NULL, // Signal Provider ... + string mProvider = NULL, // Signal Provider ... double mDblPayLoad = NULL, string mStrPayload = NULL // ) @@ -2773,6 +2773,161 @@ struct XTrail } }; +// +struct XSymbolPositions +{ + // + string symbol; + + // + double profit; + double longsProfit; + double shortsProfit; + + // + double volume; + double longsVolume; + double shortsVolume; + + // + double requiredProfitForHedge; + + // + XPosition longs[]; + XPosition shorts[]; + XPosition positions[]; + + // + XSymbolPositions() + { + Clean(); + } + + // + bool Update( + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // + ) + { + // + bool result = false; + + // + bool hasChild = HasChild(); + if (!hasChild) + { + return result; + } + + // + // Extract Types ... + ExtractPositions( + positions, + longs, + shorts // + ); + + // + int numOfLongs = 0; + int numOfShorts = 0; + CountPositions( + positions, + numOfLongs, + longsProfit, + longsVolume, + numOfShorts, + shortsProfit, + shortsVolume // + ); + + // + profit = longsProfit + shortsProfit; + volume = longsVolume + shortsVolume; + requiredProfitForHedge = SpecifiedCalculateRequiredProfitForHedge( + positions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + + // + profit = 0; + longsProfit = 0; + shortsProfit = 0; + + // + volume = 0; + longsVolume = 0; + shortsVolume = 0; + + // + requiredProfitForHedge = 0; + + // + Clean(longs); + Clean(shorts); + Clean(positions); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(symbol); + + // + return result; + } + + // + // Has Child ... + bool HasChild() + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int count = Count(); + result = IsValidSize(count); + + // + return result; + } + + // + // Count ... + int Count() + { + return ArraySize(positions); + } + + // +}; + // // TypeDefs ... @@ -4646,6 +4801,126 @@ void ExtractPositions( } } +// +int FindSymbolIndex( + string mSymbol, + XSymbolPositions &mItems[] // +) +{ + // + int result = -1; + + // + if (!IsValid(mSymbol)) + { + return result; + } + + // + int count = ArraySize(mItems); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XSymbolPositions iItem = mItems[i]; + + // + if (iItem.symbol == mSymbol) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +int ExtractSymbolPositions( + XPosition &positions[], + XSymbolPositions &items[], // Holds Result + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + int result = 0; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + Clean(items); + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (!iPosition.IsValid()) + { + continue; + } + + // + int itemIDX = FindSymbolIndex( + iPosition.symbol, + items // + ); + if (!IsValidIndex(itemIDX)) + { + // + // Add New One ... + XSymbolPositions item; + item.symbol = iPosition.symbol; + + // + AddRef( + item, + items // + ); + itemIDX = FindSymbolIndex(iPosition.symbol, items); + } + + // + AddRef( + iPosition, + items[itemIDX].positions // + ); + } + + // + result = ArraySize(items); + if (IsValidSize(result)) + { + // + for (int i = 0; i < result; i++) + { + // + items[i].Update( + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + } + } + + // + return result; +} + // // Custom Drawings ... bool DrawTrendState(