/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // -------------------------------------- // Name: XCXSTRCCITradeManager // Description: provides all Requirements for Managing Trades ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // // Imports ... #include "../../Classes/x-saherelm.x-alert.class.mq5" #include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" #include "../../Classes/x-saherelm.x-trade.class.mq5" #include "../Libraries/xstrcci.signaller.lib.mq5" // // Definitions ... // enum ENUM_XSTRCCI_TRADE_FINALIZATION { XSTRCCI_TRADE_FINAL_NONE, XSTRCCI_TRADE_FINAL_TP, XSTRCCI_TRADE_FINAL_SL, XSTRCCI_TRADE_FINAL_CLOSE_IN_PROFIT, XSTRCCI_TRADE_FINAL_CLOSE_IN_LOSE, }; // struct XSTRCCITrade { // // Props ... double swap; double profit; XSignal signal; ulong positionID; double commission; XSTRCCIStrategyConditions conditions; ENUM_XSTRCCI_TRADE_FINALIZATION finalize; // // Constructor ... XSTRCCITrade() { Clean(); } // // Tools ... /** * Cleanup Model ... */ void Clean() { // swap = 0; profit = 0; signal.Clean(); commission = 0; positionID = 0; conditions.Clean(); finalize = XSTRCCI_TRADE_FINAL_NONE; // ZeroMemory(this); } /** * Check Has Signal ... * * @return ( bool ) */ bool HasSignal() { // bool result = false; // result = signal.IsValid(); // return result; } /** * Check Signal Executed or Not ... * * @return ( bool ) */ bool IsExecuted() { // bool result = false; // result = positionID > 0; // return result; } /** * Check a Trade is Finalized or not ... * * @return ( bool ) */ bool IsFinalized() { // bool result = false; // result = HasSignal() && IsExecuted() && finalize != XSTRCCI_TRADE_FINAL_NONE; // return result; } }; // // Implementations ... class XCXSTRCCITradeManager : public XCBaseAlert { // // Public ... public: // // Props ... XCTrade *trader; bool drawSignal; XCPOIDrawer *drawer; // // Constructors ... XCXSTRCCITradeManager(XCTrade *&_trader) { // trader = _trader; drawSignal = true; drawer = new XCPOIDrawer(); } // // De Constructors ... ~XCXSTRCCITradeManager() { // ZeroMemory(trader); ZeroMemory(drawer); } // // Tools ... /** * Do All Position Managing Senaros ... */ void Manage() { // bool has = HasChild(trades); if (!has) { return; } // int count = ArraySize(trades); for (int i = 0; i < count; i++) { // has = trades[i].IsExecuted() && !trades[i].IsFinalized(); if (!has) { continue; } // XPosition iPosition; has = trader.GetPosition( trades[i].positionID, iPosition // ); if (!has) { continue; } // // Update Trade Data ... trades[i].swap = iPosition.swap; trades[i].profit = iPosition.profit; } // // After Update All Trades we can Do Protection ... Protect(); } /** * Do All Position Protection Here ... */ void Protect() { // bool has = HasChild(trades); if (!has) { return; } // XPosition ownPosition[]; XPosition ownLongPosition[]; XPosition ownShortPosition[]; // int count = ArraySize(trades); for (int i = 0; i < count; i++) { // has = trades[i].IsExecuted() && !trades[i].IsFinalized(); if (!has) { continue; } // XPosition iPosition; has = trader.GetPosition( trades[i].positionID, iPosition // ); if (!has) { continue; } // AddRef( iPosition, ownPosition // ); // if (IsLong(iPosition.type)) { // AddRef( iPosition, ownLongPosition // ); } else { // AddRef( iPosition, ownShortPosition // ); } } // has = HasChild(ownPosition); if (!has) { // Clean(ownPosition); Clean(ownLongPosition); Clean(ownShortPosition); // return; } // double swapSum = 0; double profitSum = 0; double commissionSum = 0; // // Calculate Required Data On Collection ... count = ArraySize(ownPosition); for (int i = 0; i < count; i++) { // XPosition iPosition = ownPosition[i]; // swapSum += iPosition.swap; profitSum += iPosition.profit; commissionSum += iPosition.commission; } // // Do Collection Protectiong ... // TODO: Implement this ... // // Do Signle Protections ... for (int i = 0; i < count; i++) { // // Select Position ... XPosition iPosition = ownPosition[i]; // // Handle RF ... } } /** * Execute Specified Signal ... * * @param signal: XSignal instance reference ... * @param conditions: XSTRCCIStrategyConditions instance reference ... * * @return ( bool ) */ bool Execute( XSignal &signal, XSTRCCIStrategyConditions &conditions // ) { // 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; result = trader.ExecuteSignal( signal, executionResult // ); // // Alert Signal Execution ... string executionMessage = ToString(executionResult); Alert(executionMessage); // if (result) { // if (drawSignal) { // XCSignalObject *iObj; isExists = drawer.DrawSignal( signal, iObj // ); // if (isExists) { // mObjects.Add(iObj); ZeroMemory(iObj); } } // XSTRCCITrade iTrade; // ulong positionID = trader.GetLastOpenPositionTicket(); double commission = trader.GetPositionCommission(positionID); // iTrade.signal = signal; iTrade.conditions = conditions; iTrade.positionID = positionID; iTrade.commission = commission; // AddRef( iTrade, trades // ); } // return result; } /** * Handle Position Take Profit ... * * @param deal: XDeal instance reference ... */ void HandleTP(const XDeal &deal) { // // Check Ticket Exists or not ... int idx = -1; bool isExists = HasTrade( idx, deal.positionId // ); if (!isExists) { return; } // // Apply Required Data ... trades[idx].swap = deal.swap; trades[idx].profit = deal.profit; trades[idx].commission = deal.commission; trades[idx].finalize = XSTRCCI_TRADE_FINAL_TP; // tpCount++; managedTPCount++; // } /** * Handle Position Stop Loss ... * * @param deal: XDeal instance reference ... */ void HandleSL(const XDeal &deal) { // // Check Ticket Exists or not ... int idx = -1; bool isExists = HasTrade( idx, deal.positionId // ); if (!isExists) { return; } // // Apply Required Data ... trades[idx].swap = deal.swap; trades[idx].profit = deal.profit; trades[idx].commission = deal.commission; trades[idx].finalize = XSTRCCI_TRADE_FINAL_SL; // slCount++; managedSLCount++; // } /** * Handle Position Force Close ... * * @param deal: XDeal instance reference ... */ void HandleForceClose(const XPosition &position) { // // Check Ticket Exists or not ... int idx = -1; bool isExists = HasTrade( idx, position.ticket // ); if (!isExists) { return; } // bool isInProfit = position.profit > 0; // // Apply Required Data ... trades[idx].swap = position.swap; trades[idx].profit = position.profit; trades[idx].commission = position.commission; trades[idx].finalize = isInProfit ? XSTRCCI_TRADE_FINAL_CLOSE_IN_PROFIT : XSTRCCI_TRADE_FINAL_CLOSE_IN_LOSE; // if (isInProfit) { // tpCount++; managedTPCount++; } else { // slCount++; managedSLCount++; } // } // // TODO: Complete this ... void HandleGuard() { } /** * Find Executed Trade by Providing Position Ticket ... * * @param index: int reference, holding founded item index ... * @param ticket: ulong, Specified Position Ticket ... * * @return ( bool ) */ bool HasTrade( int &index, ulong ticket // ) { // bool result = false; // index = -1; // result = ticket > 0 && HasChild(trades); if (!result) { return result; } // int count = ArraySize(trades); for (int i = 0; i < count; i++) { // XSTRCCITrade iTrade = trades[i]; // result = iTrade.HasSignal() && iTrade.IsExecuted() && iTrade.positionID == ticket; if (result) { // index = i; // iTrade.Clean(); break; } // iTrade.Clean(); } // result = IsValidIndex(index); // return result; } /** * Find Trade Item By Signal ... * * @param index: int reference, holding founded item index ... * * @return ( bool ) */ bool HasTrade( int &index, XSignal &signal // ) { // bool result = false; // index = -1; // result = signal.IsValid() && HasChild(trades); if (!result) { return result; } // int count = ArraySize(trades); for (int i = 0; i < count; i++) { // XSTRCCITrade iTrade = trades[i]; // result = iTrade.HasSignal() && iTrade.signal.IsSameAs(signal); if (result) { // index = i; // iTrade.Clean(); break; } // iTrade.Clean(); } // result = IsValidIndex(index); // return result; } // // Protected ... protected: // // Tools ... // // Private ... private: // // Props ... // int slCount; int tpCount; // int managedSLCount; int managedTPCount; // CArrayObj mObjects; // XSTRCCITrade trades[]; }; //