From f15e58fbc45902fc3145a793646da5c5168d935d Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Mon, 6 Oct 2025 17:57:37 +0330 Subject: [PATCH] refactor whole projects compiling issues ... --- Classes/x-saherelm.x-cobject.class.mq5 | 729 +++++++++++++++++- .../x-saherelm.x-position.drawer.class.mq5 | 182 +++++ XCATBEA/Classes/xcatbea.signaller.class.mq5 | 8 +- 3 files changed, 913 insertions(+), 6 deletions(-) create mode 100644 Classes/x-saherelm.x-position.drawer.class.mq5 diff --git a/Classes/x-saherelm.x-cobject.class.mq5 b/Classes/x-saherelm.x-cobject.class.mq5 index a2aff813..4bc8ef4c 100644 --- a/Classes/x-saherelm.x-cobject.class.mq5 +++ b/Classes/x-saherelm.x-cobject.class.mq5 @@ -46,6 +46,7 @@ enum ENUM_XCHARTOBJECTS X_OHCL_OBJ = 8863, // XBar X_RR_OBJ = 8864, // XRR X_PIVOT_OBJ = 8865, // XPivot + X_POSITION_OBJ = 8866, // XPosition // // 9860 Custom Object ... }; @@ -140,7 +141,7 @@ struct XPOIStyle * * @return ( bool ) */ -bool ToSignal( +bool ToXSignal( XBoxZone &box, XSignal &signal, double &rewardRatios[], @@ -344,6 +345,177 @@ bool ToSignal( return result; } +/** + * Converts a Signal to Position ... + * + * @param signal: XSignal, reference to Specified Signal ... + * @param position: XPosition, reference to Generated Position ... + * @param magic: ulong, Specified Magic Number ... + * @param ticket: ulong, Specified Position Ticket ... + * + * @return ( bool ) + */ +bool ToXPosition( + XSignal &signal, + XPosition &position, + ulong magic = 0, + ulong ticket = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + position.Clean(); + + // + // Validate ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + // Normalize ... + + // + if (ticket <= 0) + { + // + if (signal.positionId > 0) + { + ticket = signal.positionId; + } + else + { + // + ticket = MathRand(); + signal.positionId = ticket; + } + } + signal.positionId = ticket; + + // + if (magic <= 0) + { + magic = MathRand(); + } + + // + // Filling Position ... + position.swap = 0; + position.profit = 0; + position.magic = magic; + position.commission = 0; + position.tp = signal.tp; + position.sl = signal.sl; + position.ticket = ticket; + position.type = signal.type; + position.price = signal.entry; + position.entry = signal.entry; + position.openAt = signal.time; + position.volume = signal.volume; + position.symbol = signal.symbol; + position.period = signal.period; + position.comment = signal.comment; + position.provider = signal.provider; + + // + result = position.IsValid(); + + // + // Cleanup Resources ... + if (!result) + { + position.Clean(); + } + + // + return result; +} + +/** + * Update Specified Position by Bar ... + * + * @param position: XPosition, reference to Specified Position ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool XUpdatePosition( + XPosition &position, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = position.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init( + position.symbol, + position.period, + barIndex // + ); + if (!result) + { + return result; + } + + // + double entryDiff = MathAbs(position.entry - position.price); + bool isLong = IsLong(position.type); + bool isInProfit = isLong + ? position.price > position.entry + : position.price < position.entry; + bool isTargeted = + isLong + ? position.price >= position.tp + : position.price <= position.tp; + bool isStoped = + isLong + ? position.price <= position.sl + : position.price >= position.sl; + result = !isTargeted && !isStoped; + if (!result) + { + return result; + } + + // + double spread = GetSpread(position.symbol); + position.price = bar.close + + (isLong + ? spread + : (-1 * spread)); + entryDiff = MathAbs(position.entry - position.price); + isInProfit = isLong + ? position.price > position.entry + : position.price < position.entry; + result = position.IsValid(); + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; +} + // // Implementation ... @@ -1008,7 +1180,7 @@ class XCRRObject : public XCSignalObject // XSignal signal; - result = ToSignal( + result = ToXSignal( box, signal, rewardRatios // @@ -1614,6 +1786,559 @@ class XCBoxObject : public XCBaseObject CChartObjectRectangle mRect; }; +class XCPositionObject : public XCBaseObject +{ + // + // Public ... + public: + // + + // + // Creators ... + + bool Create( + long chart_id, + int window, + XSignal &signal, + ulong magic = 0, + ulong ticket = 0 // + ) + { + // + bool result = false; + + // + // Converts Signal to Test Position ... + XPosition _position; + result = ToXPosition( + signal, + _position, + magic, + ticket // + ); + + // + // Validate ... + result = chart_id >= 0 && + window >= 0 && + _position.IsValid(); + if (!result) + { + return result; + } + + // + result = Create( + chart_id, + window, + _position // + ); + + // + return result; + } + + /** + * Create a Position Object ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param position: XPosition, reference to Specified Position ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XPosition &position // + ) + { + // + bool result = false; + + // + // Validate ... + result = chart_id >= 0 && + window >= 0 && + position.IsValid(); + if (!result) + { + return result; + } + + // + result = Update(position); + if (!result) + { + // + Destroy(); + return result; + } + + // + return result; + } + + /** + * Update Position if Belongs to ... + * + * @param position: XPosition, reference to Specified Position ... + * + * @return ( bool ) + */ + bool Update(XPosition &position) + { + // + bool result = false; + + // + // Validate ... + result = + mChartID >= 0 && + mWindowID >= 0 && + position.IsValid() && + (!HasPosition() + ? true + : IsBelong(position)); + if (!result) + { + return result; + } + + // + // Validate Chart Info ... + result = XUpdatePosition(position); + + // + return result; + } + + bool Update(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = HasPosition(); + if (!result) + { + return result; + } + + // + // Update mPosition ... + result = XUpdatePosition(mPosition, barIndex); + if (!result) + { + return result; + } + + // + result = Update(mPosition); + + // + return result; + } + + // + // Checkers ... + + /** + * Check Object is Belongs to Specified Position or not ... + * + * @param position: XPosition, reference to Specified Position ... + * + * @return ( bool ) + */ + bool IsBelong(XPosition &position) + { + // + bool result = false; + + // + // Validate ... + result = + HasPosition() && + position.IsValid(); + + // + // Check ... + result = + result && + mPosition.ticket == position.ticket; + + // + return result; + } + + // + // Overrides ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + string TypeString() override + { + return ToXString(X_POSITION_OBJ); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + int Type(void) const override + { + return ((int)X_POSITION_OBJ); + } + + /** + * Destroy Object ... + **/ + void Destroy() override + { + // + ObjName(NULL); + + // + mRiskBox.Clean(); + mPosition.Clean(); + mPriceBox.Clean(); + mRewardBox.Clean(); + + // + mRiskBoxObj.Detach(); + mRiskBoxObj.Delete(); + + // + mPriceBoxObj.Detach(); + mPriceBoxObj.Delete(); + + // + mRewardBoxObj.Detach(); + mRewardBoxObj.Delete(); + } + + // + // Stylers ... + + // + void ApplyStyle( + XPOIStyle &bullishStyle, + XPOIStyle &bearishStyle // + ) + { + // + // Validate ... + if (!HasPosition()) + { + return; + } + + // + // Risk Box ... + if (mRiskBox.IsValid()) + { + // + mRiskBoxObj.BoxColor(bearishStyle.clr); + mRiskBoxObj.BoxFill(bearishStyle.fill); + mRiskBoxObj.BoxStyle(bearishStyle.style); + mRiskBoxObj.BoxWidth(bearishStyle.width); + } + + // + // Reward Box ... + if (mRewardBox.IsValid()) + { + // + mRewardBoxObj.BoxColor(bullishStyle.clr); + mRewardBoxObj.BoxFill(bullishStyle.fill); + mRewardBoxObj.BoxStyle(bullishStyle.style); + mRewardBoxObj.BoxWidth(bullishStyle.width); + } + + // + // Price Box ... + if (mPriceBox.IsValid()) + { + // + XPOIStyle priceStyle; + if (mPriceBox.IsBullish()) + { + priceStyle = bullishStyle; + } + else + { + priceStyle = bearishStyle; + } + + // + mPriceBoxObj.BoxColor(priceStyle.clr); + mPriceBoxObj.BoxFill(priceStyle.fill); + mPriceBoxObj.BoxStyle(priceStyle.style); + mPriceBoxObj.BoxWidth(priceStyle.width); + + // + priceStyle.Clean(); + } + } + + // + // Protected ... + protected: + // + + // + bool HasPosition() + { + return mPosition.IsValid(); + } + + // + bool UpdatePosition(XPosition &_position) + { + // + bool result = false; + + // + // Validate ... + result = _position.IsValid() && + (!HasPosition() + ? true + : _position.ticket == mPosition.ticket // + ); + if (!result) + { + return result; + } + + // + mPosition = _position; + result = UpdateZones(); + + // + return result; + } + + // + bool UpdateZones() + { + // + bool result = false; + + // + // Validate ... + result = HasPosition(); + if (!result) + { + return result; + } + + // + string iSymbol = mPosition.symbol; + ENUM_TIMEFRAMES iPeriod = mPosition.period; + + // + datetime iAt = mPosition.openAt; + datetime iFrom = mPosition.openAt; + datetime iTo = iFrom + (PeriodSeconds(iPeriod) * 3); + + // + double iTP = mPosition.tp; + double iSL = mPosition.sl; + double iEntry = mPosition.entry; + double iPrice = mPosition.price; + + // + bool isLong = IsLong(mPosition.type); + ENUM_X_DIRECTION iRiskDir = isLong + ? X_DIRECTION_BEARISH + : X_DIRECTION_BULLISH; + ENUM_X_DIRECTION iRewardDir = isLong + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + bool isInProfit = mPosition.profit > 0; + ENUM_X_DIRECTION iPriceDir = isInProfit + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Try to Update Zones ... + string iSuffix = ToXString(mPosition.type) + "_" + ToXString(mPosition.ticket); + string iPrefix = ToXString(TimeToSeconds(mPosition.openAt)); + string iName = iSuffix + "_" + iPrefix; + string iRiskName = iSuffix + "_" + "RISK" + "_" + iPrefix; + string iPriceName = iSuffix + "_" + "PRICE" + "_" + iPrefix; + string iRewardName = iSuffix + "_" + "REWARD" + "_" + iPrefix; + + // + // Risk Box ... + mRiskBox.to = iTo; + mRiskBox.at = iAt; + mRiskBox.lower = + isLong + ? iSL + : iEntry; + mRiskBox.upper = + isLong + ? iEntry + : iSL; + mRiskBox.from = iFrom; + mRiskBox.symbol = iSymbol; + mRiskBox.period = iPeriod; + mRiskBox.type = iRiskName; + mRiskBox.dir = X_DIRECTION_BEARISH; + + // + // Reward Box ... + mRewardBox.to = iTo; + mRewardBox.at = iAt; + mRewardBox.lower = + isLong + ? iEntry + : iTP; + mRewardBox.upper = + isLong + ? iTP + : iEntry; + mRewardBox.from = iFrom; + mRewardBox.symbol = iSymbol; + mRewardBox.period = iPeriod; + mRewardBox.type = iRewardName; + mRewardBox.dir = X_DIRECTION_BULLISH; + + // + // Price Box ... + mPriceBox.to = iTo; + mPriceBox.at = iAt; + mPriceBox.lower = + isLong + ? isInProfit + ? iEntry + : iPrice + : isInProfit + ? iPrice + : iEntry; + mPriceBox.upper = + isLong + ? isInProfit + ? iPrice + : iEntry + : isInProfit + ? iEntry + : iPrice; + mPriceBox.from = iFrom; + mPriceBox.symbol = iSymbol; + mPriceBox.period = iPeriod; + mPriceBox.type = iPriceName; + mPriceBox.dir = isInProfit + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = mRiskBox.IsValid() && + mPriceBox.IsValid() && + mRewardBox.IsValid(); + if (!result) + { + return result; + } + + // + mRiskBoxObj.Detach(); + mRiskBoxObj.Delete(); + bool isRiskCreated = + mRiskBoxObj.Create( + mChartID, + mWindowID, + mRiskBox.type, + mRiskBox.upper, + mRiskBox.lower, + mRiskBox.from, + mRiskBox.to, + NULL, // At ... + NULL // Prefix ... + ); + + // + mRewardBoxObj.Detach(); + mRewardBoxObj.Delete(); + bool isRewardCreated = + mRewardBoxObj.Create( + mChartID, + mWindowID, + mRewardBox.type, + mRewardBox.upper, + mRewardBox.lower, + mRewardBox.from, + mRewardBox.to, + NULL, // At ... + NULL // Prefix ... + ); + + // + mPriceBoxObj.Detach(); + mPriceBoxObj.Delete(); + bool isPriceCreated = + mPriceBoxObj.Create( + mChartID, + mWindowID, + mPriceBox.type, + mPriceBox.upper, + mPriceBox.lower, + mPriceBox.from, + mPriceBox.to, + NULL, // At ... + NULL // Prefix ... + ); + + // + result = + isRiskCreated && + isPriceCreated && + isRewardCreated; + if (!result) + { + ObjName(iName); + } + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + int mWindowID; + long mChartID; + + // + XBoxZone mRiskBox; + XBoxZone mPriceBox; + XPosition mPosition; + XBoxZone mRewardBox; + + // + XCBoxObject mRiskBoxObj; + XCBoxObject mPriceBoxObj; + XCBoxObject mRewardBoxObj; + + // +}; + /** * XPivotAnalysis Chart Object ... **/ diff --git a/Classes/x-saherelm.x-position.drawer.class.mq5 b/Classes/x-saherelm.x-position.drawer.class.mq5 new file mode 100644 index 00000000..bc955418 --- /dev/null +++ b/Classes/x-saherelm.x-position.drawer.class.mq5 @@ -0,0 +1,182 @@ +/////////////////////////////////////////////////////// +// +// 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 ... + XCTrade *trader; + CArrayObj positionObjects; + + // + // Constructor ... + XCPositionDrawer( + XCTrade *_trader // + ) : XCBase() + { + // + Init( + _trader // + ); + } + + // + // Deconstructor ... + ~XCPositionDrawer() + { + Destroy(); + } + + // + // Tools ... + + void Init( + XCTrade *_trader // + ) + { + // + // Validate ... + bool has = _trader != NULL; + if (!has) + { + return; + } + + // + trader = _trader; + } + + void Destroy() + { + } + + bool IsValid() + { + // + bool result = false; + + // + result = + trader != NULL; + + // + return result; + } + + void Update(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + bool has = IsValid(); + if (!has) { + return; + } + + // + + } + + // + // Trade Event Handlers ... + + /** + * Add Executed Signal ... + * + * @param signal: XSignal, reference to Executed Signal ... + */ + void AddExecutedSignal(XSignal &signal) + { + // + // Validate ... + if (!signal.IsValid() || !signal.IsExecuted()) + { + return; + } + } + + /** + * Handle Stop Loss Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) + { + } + + /** + * Handle Take Profit Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) + { + } + + /** + * 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 // + ) + { + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + + // +}; + +// \ No newline at end of file diff --git a/XCATBEA/Classes/xcatbea.signaller.class.mq5 b/XCATBEA/Classes/xcatbea.signaller.class.mq5 index 779fc1e5..1ba538b7 100644 --- a/XCATBEA/Classes/xcatbea.signaller.class.mq5 +++ b/XCATBEA/Classes/xcatbea.signaller.class.mq5 @@ -794,7 +794,7 @@ class XCXCATBEASignaller : XCBase // // Preparing Signal ... XSignal iSignal; - result = ToSignal( + result = ToXSignal( mConditions.pivotZone, iSignal, targets, @@ -896,7 +896,7 @@ class XCXCATBEASignaller : XCBase // // Preparing Signal ... - result = ToSignal( + result = ToXSignal( mConditions.triggerBlock.trigger, mConditions.triggerBlock.signal, targets, @@ -1359,7 +1359,7 @@ class XCXCATBEASignaller : XCBase // // Preparing Signal ... - result = ToSignal( + result = ToXSignal( mConditions.triggerBlock.trigger, mConditions.triggerBlock.signal, targets, @@ -1368,7 +1368,7 @@ class XCXCATBEASignaller : XCBase XSignal insideTBSignal; result = result && - ToSignal( + ToXSignal( cInsideTriggerBlock.trigger, insideTBSignal, targets,