/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // -------------------------------------- // Name: XCPositionDrawer // Description: Provides Position // Drawing Tools ... // // 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.base.class.mq5" #include "../Classes/x-saherelm.x-cobject.class.mq5" #include "../Classes/x-saherelm.x-trade.class.mq5" #include "../Libraries/x-saherelm.x-pivot.analysis.lib.mq5" #include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" // // Definitions ... // // Implementation ... class XCPositionDrawer : public XCBase { // // Public ... public: // // Props ... int window; // Window ID of Chart ... ulong chartID; // Chart ID ... XCTrade *trader; // XCTrade Instance ... XPOIStyle riskStyle; // Risk Box Style ... color inProfitColor; // In Profit Price Box Color ... color inDrawdownColor; // In Drawdown Price Box Color ... ENUM_LINE_STYLE priceStyle; // Price Box Style ... XPOIStyle rewardStyle; // Reward Box Style ... CArrayObj positionObjects; // Drawn Positions Object Instances Collection ... CArrayObj finalizedObjects; // Finalized Drawn Positions Object Instances Collection ... // // Constructor ... XCPositionDrawer( XCTrade *_trader, ulong _chartID = 0, int _window = 0 // ) : XCBase() { // Init( _trader, _chartID, _window // ); } // // Deconstructor ... ~XCPositionDrawer() { Destroy(); } // // Tools ... /** * Initialize Class Instance ... * * @param _trader: XCTrade, reference Pointer to Trader Instance Class ... * @param _chartID: ulong, Specified Chart ID ... * @param _window: int, Specified Chart Window ID ... */ void Init( XCTrade *_trader, ulong _chartID = 0, int _window = 0 // ) { // // Validate ... bool has = _window >= 0 && _chartID >= 0 && _trader != NULL; if (!has) { return; } // trader = _trader; window = _window; chartID = _chartID; // // Prepare Default Styles ... // // Risk Style ... riskStyle.width = 1; riskStyle.fill = false; riskStyle.clr = clrRed; riskStyle.style = STYLE_DASH; // // Reward Style ... rewardStyle.width = 1; rewardStyle.fill = false; rewardStyle.clr = clrLime; rewardStyle.style = STYLE_DASH; // // Price Style ... priceStyle = STYLE_SOLID; inProfitColor = clrAqua; // ApplyAlpha(clrAqua, 100); inDrawdownColor = clrMagenta; // ApplyAlpha(clrMagenta, 100); } /** * Destroy Instance ... */ void Destroy() { // riskStyle.Clean(); rewardStyle.Clean(); // positionObjects // finalizedObjects } /** * Validate Instance ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = trader != NULL; // return result; } /** * Update Positions ... * * @param barIndex: int, Specified Bar Index ... */ void Update(int barIndex = 0) { // // Normalize ... barIndex = NormalizeInt(barIndex, 0); // // Validate ... bool has = IsValid(); if (!has) { return; } // // Update Exists Positions ... XPosition positions[]; int positionsCount = trader.GetPositions(positions); has = IsValidSize(positionsCount); if (has) { // int drawingsCount = positionObjects.Total(); has = IsValidSize(drawingsCount); if (has) { // for (int i = 0; i < positionsCount; i++) { // for (int j = 0; j < drawingsCount; j++) { // // Check Object is Belong to Position ... has = ((XCPositionObject *)positionObjects.At(j)).IsBelong(positions[i]); if (has) { // // Update Position Object ... has = ((XCPositionObject *)positionObjects.At(j)).Update(positions[i]); } } } } } // // Update Test Positions ... positionsCount = positionObjects.Total(); has = !HasChild(positions) && IsValidSize(positionsCount); if (has) { // XPosition iPosition; for (int i = 0; i < positionsCount; i++) { // // Retrieve Position from Object ... has = ((XCPositionObject *)positionObjects.At(i)).GetPosition(iPosition); if (has) { // // Manully Update Position ... has = ((XCPositionObject *)positionObjects.At(i)).Update(barIndex); } } // iPosition.Clean(); } } // // Trade Event Handlers ... /** * Add Executed Signal ... * * @param signal: XSignal, reference to Executed Signal ... */ void AddExecutedSignal(XSignal &signal) { // // Validate ... bool has = signal.IsValid() && signal.IsExecuted(); if (!has) { return; } // XPosition iPosition; // // Check Position Exists ... has = trader.GetPosition( signal.positionId, iPosition // ); // // Initial by Testing Position ... if (!has) { // has = ToXPosition( signal, iPosition, trader.GetMagicNumber(), signal.positionId // ); } // // Validate result ... if (has) { // XCPositionObject *iObj = new XCPositionObject(); has = iObj.Create( chartID, window, iPosition // ); if (has) { // // Set Stylers to Position ... iObj.riskStyle = riskStyle; iObj.priceStyle = priceStyle; iObj.rewardStyle = rewardStyle; iObj.inProfitColor = inProfitColor; iObj.inDrawdownColor = inDrawdownColor; // // Add to Collection ... positionObjects.Add(iObj); } } // // Cleanup Resources ... iPosition.Clean(); } /** * Handle Stop Loss Event Triggered ... * * @param deal: XDeal instance refrence, provides Triggered Deal info ... */ void HandleStopLossTriggered(const XDeal &deal) { // Finalize(deal.positionId); } /** * Handle Take Profit Event Triggered ... * * @param deal: XDeal instance refrence, provides Triggered Deal info ... */ void HandleOnTakeProfitTriggered(const XDeal &deal) { Finalize(deal.positionId); } /** * Handle Position Force Closed Event ... * * @param ticket: ulong, triggered Positions ticket ... * @param position: XPosition instance refrence, Triggered Position ... * @param comment: string, Comment ... */ void HandleOnPositionForceClosed( const ulong ticket, const XPosition &position, const string comment // ) { Finalize(ticket); } /** * Handle Position Modified Event ... * * @param ticket: ulong, triggered Positions ticket ... * @param profit: double, Position Profit ... * @param comment: string, Comment ... */ void HandleOnPositionModified( const ulong ticket, const double profit, const string comment // ) { // // Detect Position Index ... int index = FindIndex(ticket); bool has = IsValidIndex(index); if (!has) { return; } // // Get Position of Objects ... XPosition _position; has = ((XCPositionObject *)positionObjects.At(index)).GetPosition(_position); if (has) { // // Get Position of Trader Instance ... has = trader.GetPosition( ticket, _position // ); if (has) { // // Update Position ... ((XCPositionObject *)positionObjects.At(index)).Update(_position); } } // // Cleanup Resources ... _position.Clean(); } // // Protected ... protected: // /** * Finalize Specified Position ... * Remove it From Position Objects and add it to Finalized Objects Cllection ... * * @param ticket: ulong, Specified Position Ticket ... */ void Finalize(ulong ticket) { // int index = FindIndex(ticket); bool has = IsValidIndex(index); if (!has) { return; } // // XCPositionObject *iObj = positionObjects.At(index); // positionObjects.Delete(index); // finalizedObjects.Add(iObj); } /** * Find Specified Position Index ... * * @param ticket: ulong, Specified Position Ticket ... * * @return ( int ) */ int FindIndex(ulong ticket) { // int result = -1; // // Validate ... int count = NotEmptyZero(ticket) && positionObjects.Total(); bool has = IsValidSize(count); if (!has) { return result; } // XPosition iPosition; for (int i = 0; i < count; i++) { // has = ((XCPositionObject *)positionObjects.At(i)).GetPosition(iPosition); has = has && iPosition.ticket == ticket; if (has) { // result = i; break; } } // // Cleanup Resources ... iPosition.Clean(); // return result; } // // Private ... private: // // }; //