diff --git a/Classes/x-saherelm.x121.setup.class.mq5 b/Classes/x-saherelm.x121.setup.class.mq5 index 52494d36..376ec82c 100644 --- a/Classes/x-saherelm.x121.setup.class.mq5 +++ b/Classes/x-saherelm.x121.setup.class.mq5 @@ -1898,24 +1898,32 @@ struct X121SignalGenerator } // - bool hasLong = - !_allowLong - ? false - : HasLongConditions( - conditions, - pusher, - provider // - ); + bool hasLong = false; + bool hasShort = false; // - bool hasShort = - !_allowShort - ? false - : HasShortConditions( - conditions, - pusher, - provider // - ); + if (_allowLong) + { + // + hasLong = + HasLongConditions( + conditions, + pusher, + provider // + ); + } + + // + if (_allowShort && !hasLong) + { + // + hasShort = + HasShortConditions( + conditions, + pusher, + provider // + ); + } // result = hasLong || hasShort; diff --git a/Classes/x-saherelm.x121.setup.xea.mq5 b/Classes/x-saherelm.x121.setup.xea.mq5 index 5d79a9ef..8a289ef7 100644 --- a/Classes/x-saherelm.x121.setup.xea.mq5 +++ b/Classes/x-saherelm.x121.setup.xea.mq5 @@ -253,7 +253,8 @@ struct XSignalInfo // result = // - symbol + "_" + + symbol + "\\" + + ToString(signal.type) + "\\" + provider + "_" + ToString(ticket) + "_" + ToString(period) + "_" + @@ -332,6 +333,9 @@ public: string _path = NULL // Base Path ) { + // + mAccount = new XSCAccount(); + // if (IsValid(_path)) { @@ -339,7 +343,7 @@ public: } else { - mPath = "XSignalInfo"; + mPath = "XSignalInfo" + "\\" + mAccount.GetCompany(); } } @@ -413,6 +417,9 @@ private: // string mPath; // Base Path ... + // + XSCAccount *mAccount; + // string GetFilePath(XSignalInfo &item) { @@ -502,16 +509,24 @@ public: ulong magicNumber, // Specify Magic Number // // XSCTrade Event Handlers ... + TOnSignal onSignal = NULL, // On Signal Recieved Event Handler + TOnModify onModifyPosition = NULL, // On Modify Position Event Handler TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler + TOnForceClose onForceClosePosition = NULL, // On Force Close Position Event Handler + TOnPartialClose onPartialClosePosition = NULL, // On Partial Close Position Event Handler TOnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler TOnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler TOnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler TOnTradeStateChanged onTradeStateChangedHandler = NULL // On Trade State Changed Event Handler ) : XSCBaseEA(slippage, magicNumber, + onSignal, + onModifyPosition, onStopLossTriggered, onTakeProfitTriggered, + onForceClosePosition, + onPartialClosePosition, onDealsChangedHandler, onOrdersChangedHandler, onPositionsChangedHandler, @@ -527,6 +542,25 @@ public: // Deconstructor ... ~XSCX121SetupEA() { + // + int count = CountSignalInfos(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + mSignalCollector.Save(mSignalInfos[i]); + } + + // + Clean(mSignalInfos); + } + + // + delete mSignalCollector; + + // + Clean(mSetups); } // @@ -660,6 +694,18 @@ public: mIgnoreSL = value; } + // + bool CloseOnOpposit() + { + return mCloseOnOpposit; + } + + // + void CloseOnOpposit(bool value) + { + mCloseOnOpposit = value; + } + // int ReuiredSignalVerifications() { @@ -1118,7 +1164,7 @@ public: // // Current Signals ... - if (cPusher > mReuiredSignalVerifications && cSignal.IsValid()) + if (cPusher >= mReuiredSignalVerifications && cSignal.IsValid()) { // AddRef( @@ -1138,7 +1184,7 @@ public: // // Short Signals ... - if (sPusher > mReuiredSignalVerifications && sSignal.IsValid()) + if (sPusher >= mReuiredSignalVerifications && sSignal.IsValid()) { // AddRef( @@ -1158,7 +1204,7 @@ public: // // Medium Signals ... - if (mPusher > mReuiredSignalVerifications && mSignal.IsValid()) + if (mPusher >= mReuiredSignalVerifications && mSignal.IsValid()) { // AddRef( @@ -1178,7 +1224,7 @@ public: // // Long Signals ... - if (lPusher > mReuiredSignalVerifications && lSignal.IsValid()) + if (lPusher >= mReuiredSignalVerifications && lSignal.IsValid()) { // AddRef( @@ -1198,7 +1244,7 @@ public: // // Hind Signals ... - if (hPusher > mReuiredSignalVerifications && hSignal.IsValid()) + if (hPusher >= mReuiredSignalVerifications && hSignal.IsValid()) { // AddRef( @@ -1273,6 +1319,46 @@ public: // XSignal iSignal = tmpSignals[i]; + // + // Handle Close All Positions when Opposit Signal Recieved ... + if (mCloseOnOpposit) + { + // + // Select Signal Opposit Positions ... + ENUM_X_POSITION_TYPE iOpposit = GetOppositXPositionType(iSignal.type); + + // + XPosition iPositions[]; + int iPositionsCount = mTrader.GetPositions( + iPositions, + iSignal.symbol, + NULL, // All Providers ... + NULL, // All Periods ... + iOpposit // Opposit Positions ... + ); + + // + if (IsValidSize(iPositionsCount)) + { + // + string comment = "Close due Opposit ..."; + + // + int closeds = Close( + iPositions, + comment // + ); + if (IsValidSize(closeds)) + { + // + string message = XEQMSupportToken + " Closed " + ToString(iPositionsCount) + " due Opposit Signal ..."; + + // + Alert(message); + } + } + } + // AddRef( iSignal, @@ -1356,6 +1442,17 @@ public: } } + // + void OnPositionClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) override + { + // + UpdateSignalState(ticket, position, comment); + } + // void OnGoingToProfit(XProfitTrack &track) override { @@ -1388,6 +1485,7 @@ private: double mSLPoint; // SL Point bool mIgnoreTP; // Ignore Calculated TP bool mIgnoreSL; // Ignore Calculated SL + bool mCloseOnOpposit; // Close all Positions on Opposit int mReuiredSignalVerifications; // Required Verifications for Validate Signals // @@ -1598,6 +1696,38 @@ private: } } } + void UpdateSignalState( + const ulong ticket, + const XPosition &position, + const string message // + ) + { + // + int infoIDX = FindSignalInfoIndex(ticket); + if (!IsValidIndex(infoIDX)) + { + return; + } + + // + mSignalInfos[infoIDX].message = message; + mSignalInfos[infoIDX].swap = position.swap; + mSignalInfos[infoIDX].endTime = TimeCurrent(); + mSignalInfos[infoIDX].profit = position.profit; + + // + // Now we can Save Signal Info and Remove it from mSignal Infos ... + bool isSaved = mSignalCollector.Save(mSignalInfos[infoIDX]); + if (isSaved) + { + // + ArrayRemove( + mSignalInfos, + infoIDX, + 1 // + ); + } + } // double mBullishScore; diff --git a/Classes/x-saherelm.xea.class.mq5 b/Classes/x-saherelm.xea.class.mq5 index c1227520..89eba490 100644 --- a/Classes/x-saherelm.xea.class.mq5 +++ b/Classes/x-saherelm.xea.class.mq5 @@ -27,7 +27,7 @@ // // Define On Signal Event Handler Type ... -typedef void (*TOnSignal)(XSignal &signals[]); +typedef void (*TOnSignal)(XSignal &signal); // // Tokens ... @@ -1703,8 +1703,12 @@ public: ulong magicNumber, // Specify Magic Number // // Event Handlers ... + TOnSignal onSignal = NULL, // On Signal Recieved Event Handler + TOnModify onModifyPosition = NULL, // On Modify Position Event Handler TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler + TOnForceClose onForceClosePosition = NULL, // On Force Close Position Event Handler + TOnPartialClose onPartialClosePosition = NULL, // On Partial Close Position Event Handler TOnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler TOnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler TOnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler @@ -1723,15 +1727,42 @@ public: // // Set Event Handlers ... + mOnSignal = onSignal; + mOnModifyPosition = onModifyPosition; mOnStopLossTriggered = onStopLossTriggered; + mOnForceClosePosition = onForceClosePosition; mOnTakeProfitTriggered = onTakeProfitTriggered; mOnDealsChangedHandler = onDealsChangedHandler; + mOnPartialClosePosition = onPartialClosePosition; mOnOrdersChangedHandler = onOrdersChangedHandler; mOnPositionsChangedHandler = onPositionsChangedHandler; mOnTradeStateChangedHandler = onTradeStateChangedHandler; // - // Add Event Listeners to XTrade Class if they Provided ... + if (mOnSignal != NULL) + { + AddOnSignalEventHandler(mOnSignal); + } + + // + if (mOnModifyPosition != NULL) + { + mTrader.AddOnModifyPositionEventHandler(mOnModifyPosition); + } + + // + if (mOnForceClosePosition != NULL) + { + mTrader.AddOnForceClosePositionEventHandler(mOnForceClosePosition); + } + + // + if (mOnPartialClosePosition != NULL) + { + mTrader.AddOnPartialClosePositionEventHandler(mOnPartialClosePosition); + } + + // if (mOnStopLossTriggered != NULL) { mTrader.AddOnStopLossEventHandler(mOnStopLossTriggered); @@ -1793,6 +1824,16 @@ public: return mTrader.GetMagicNumber(); } + // + void AddOnSignalEventHandler(TOnSignal handler) + { + // + Add( + handler, + mOnSignalEventHandlers // + ); + } + // // Overrides ... @@ -1874,6 +1915,36 @@ public: HandleSignalsExecution(signals); } + // + // Calls when a Position Modified ... + virtual void OnPositionModified( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + // + // Calls when a Position Closed ... + virtual void OnPositionClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + } + + // + // Calls when a Position Partially Closed ... + virtual void OnPositionPartialyClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + // // Handle StopLoss Event ... virtual void OnStopLossTriggered(const XDeal &deal) {} @@ -2065,6 +2136,14 @@ public: return; } + // + // Notify Signal Event Handlers for Reciving New Signal ... + for (int i = 0; i < managedSignalsCount; i++) + { + // + NotifyOnSignalEventHandlers(signals[i]); + } + // // Try to Execute Signals ... XSignal notExecuteds[]; @@ -2154,9 +2233,233 @@ protected: // // Tools ... + // + // Since we need to Calls Some Event Handlers on + // - Modified; + // - Closed; + // - Partial Closed; + // events ... + // we have to implement thouse Methods here and use them ... + + // + // Modify ... + bool Modify( + ulong ticket, // position ticket + double sl = 0, // stop loss price + double tp = 0, // take profit + string comment = NULL // comment + ) + { + // + bool result = false; + + // + result = mTrader.Modify( + ticket, + sl, + tp, + comment // + ); + + // + if (result) + { + // + XPosition position; + result = mTrader.GetPosition( + ticket, + position // + ); + if (result) + { + // + OnPositionModified( + ticket, + position.profit, + comment // + ); + + // + string message = "Position " + ToString(ticket) + " Modified Successfully ..."; + + // + Alert(message); + } + } + + // + return result; + } + + // + // Close ... + bool Close( + ulong ticket, + string comment // + ) + { + // + bool result = false; + + // + XPosition position; + result = mTrader.GetPosition( + ticket, + position // + ); + + // + result = mTrader.Close( + ticket, + comment // + ); + + // + if (result) + { + // + OnPositionClosed( + ticket, + position, + comment // + ); + + // + string message = "Position " + ToString(ticket) + " Closed Successfully ..."; + + // + Alert(message); + } + + // + return result; + } + + // + // Close ... + int Close( + XPosition &positions[], + string comment // + ) + { + // + int result = 0; + + // + int count = ArraySize(positions); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isClosed = Close( + positions[i].ticket, + comment // + ); + + // + if (isClosed) + { + result++; + } + } + + // + return result; + } + + // + // Partial Close ... + bool PartialClose( + ulong ticket, + double volume, + string comment // + ) + { + // + bool result = false; + + // + XPosition position; + result = mTrader.GetPosition( + ticket, + position // + ); + if (!result) + { + return result; + } + + // + result = mTrader.ClosePartial( + ticket, + volume, + comment // + ); + + // + if (result) + { + // + OnPositionPartialyClosed( + ticket, + position.profit, + comment // + ); + } + + // + return result; + } + + // + // Partial Close ... + int PartialClose( + XPosition &positions[], + double volume, + string comment // + ) + { + // + int result = 0; + + // + int count = ArraySize(positions); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isClosed = PartialClose( + positions[i].ticket, + volume, + comment // + ); + + // + if (isClosed) + { + result++; + } + } + + // + return result; + } + // // Signal Event Listeners ... - void NotifyOnSignalEventHandlers(XSignal &signals[]) + + // + void NotifyOnSignalEventHandlers(XSignal &signal) { // int listenersCount = ArraySize(mOnSignalEventHandlers); @@ -2172,7 +2475,7 @@ protected: TOnSignal iListener = mOnSignalEventHandlers[i]; // - iListener(signals); + iListener(signal); } } @@ -3126,9 +3429,13 @@ private: // // Event Handlers ... + TOnSignal mOnSignal; + TOnModify mOnModifyPosition; TOnStopLoss mOnStopLossTriggered; TOnTakeProfit mOnTakeProfitTriggered; + TOnForceClose mOnForceClosePosition; TOnDealsChanged mOnDealsChangedHandler; + TOnPartialClose mOnPartialClosePosition; TOnOrdersChanged mOnOrdersChangedHandler; TOnPositionsChanged mOnPositionsChangedHandler; TOnTradeStateChanged mOnTradeStateChangedHandler; diff --git a/Classes/x-saherelm.xtrade.class.mq5 b/Classes/x-saherelm.xtrade.class.mq5 index cf701772..b2032b82 100644 --- a/Classes/x-saherelm.xtrade.class.mq5 +++ b/Classes/x-saherelm.xtrade.class.mq5 @@ -632,6 +632,39 @@ public: // // Add Event Listeners ... + // + void AddOnModifyPositionEventHandler(TOnModify handler) + { + // + Add( + handler, + mOnModifyEventHandlers + // + ); + } + + // + void AddOnForceClosePositionEventHandler(TOnForceClose handler) + { + // + Add( + handler, + mOnForceCloseEventHandlers + // + ); + } + + // + void AddOnPartialClosePositionEventHandler(TOnPartialClose handler) + { + // + Add( + handler, + mOnPartialCloseEventHandlers + // + ); + } + // // Add New Deals Changed Event Handler ... void AddOnTradeStateChangedEventHandler(TOnTradeStateChanged handler) @@ -1742,8 +1775,12 @@ public: // // Validate Args ... + XPosition position; result = - IsOpen(ticket) && + GetPosition( + ticket, + position // + ) && (tp >= 0 || sl >= 0); if (!result) { @@ -1768,6 +1805,15 @@ public: comment // ); + if (result) + { + // + NotifyModifyEvent( + ticket, + position.profit, + comment // + ); + } // return result; @@ -1785,7 +1831,11 @@ public: // // Check Position Open ... - result = IsOpen(ticket); + XPosition position; + result = GetPosition( + ticket, + position // + ); if (!result) { return result; @@ -1806,6 +1856,15 @@ public: comment // ); + if (result) + { + // + NotifyForceCloseEvent( + ticket, + position, + comment // + ); + } // return result; @@ -1912,7 +1971,11 @@ public: bool result = false; // - result = IsOpen(ticket); + XPosition position; + result = GetPosition( + ticket, + position // + ); if (!result) { return result; @@ -1934,6 +1997,15 @@ public: comment // ); + if (result) + { + // + NotifyPartialCloseEvent( + ticket, + position.profit, + comment // + ); + } // return result; @@ -3384,6 +3456,87 @@ protected: } } + // + void NotifyModifyEvent( + ulong ticket, + double profit, + string comment // + ) + { + // + int count = ArraySize(mOnModifyEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnModify iHandler = mOnModifyEventHandlers[i]; + iHandler( + ticket, + profit, + comment // + ); + } + } + + // + void NotifyForceCloseEvent( + ulong ticket, + XPosition &position, + string comment // + ) + { + // + int count = ArraySize(mOnForceCloseEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnForceClose iHandler = mOnForceCloseEventHandlers[i]; + iHandler( + ticket, + position, + comment // + ); + } + } + + // + void NotifyPartialCloseEvent( + ulong ticket, + double profit, + string comment // + ) + { + // + int count = ArraySize(mOnPartialCloseEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnModify iHandler = mOnPartialCloseEventHandlers[i]; + iHandler( + ticket, + profit, + comment // + ); + } + } + // // Tools ... @@ -3579,6 +3732,11 @@ private: // Trade State Changed Event Handlers ... TOnTradeStateChanged mTradeStateChangedEventHandlers[]; + // + TOnModify mOnModifyEventHandlers[]; + TOnForceClose mOnForceCloseEventHandlers[]; + TOnPartialClose mOnPartialCloseEventHandlers[]; + // // TPSL ... TOnStopLoss mStopLossEventHandlers[]; diff --git a/Experts/x-saherelm.x121.ea.mq5 b/Experts/x-saherelm.x121.ea.mq5 index cefdebbc..0f0f0210 100644 --- a/Experts/x-saherelm.x121.ea.mq5 +++ b/Experts/x-saherelm.x121.ea.mq5 @@ -36,21 +36,23 @@ int x121EASlippage = 10; // Slippgae // // Trading Symbols ... -string x121EASymbols = "EURUSDb,GBPUSDb,XAUUSDb,USDCHFb"; // Symbols +string x121EASymbols = "EURUSDb"; // Symbols +// EURUSDb,GBPUSDb,XAUUSDb,USDCHFb,USDJPYb // // Signals ... bool x121EAAllowLong = true; // Allow Long Trades bool x121EAAllowShort = true; // Allow Short Trades -int x121EAReuiredSignalVerifications = 2; // Required Verifications for Signals +int x121EAReuiredSignalVerifications = 4; // Required Verifications for Signals // // Risk Management ... -double x121EAVolume = 0.01; // Static Volume -double x121EATPPoint = 30; // TP Point -double x121EASLPoint = 300; // SL Point -bool x121EAIgnoreSL = true; // Ignore Calculated SL -bool x121EAIgnoreTP = false; // Ignore Calculated TP +double x121EAVolume = 0.01; // Static Volume +double x121EATPPoint = 30; // TP Point +double x121EASLPoint = 300; // SL Point +bool x121EAIgnoreSL = false; // Ignore Calculated SL +bool x121EAIgnoreTP = false; // Ignore Calculated TP +bool x121EACloseOnOpposit = false; // Close all Positions on Opposit // // Alert ... @@ -164,6 +166,7 @@ bool InitialEA() x121EA.IgnoreTP(x121EAIgnoreTP); x121EA.AllowLong(x121EAAllowLong); x121EA.AllowShort(x121EAAllowShort); + x121EA.CloseOnOpposit(x121EACloseOnOpposit); x121EA.ReuiredSignalVerifications(x121EAReuiredSignalVerifications); // diff --git a/Libraries/x-saherelm.xtrade.lib.mq5 b/Libraries/x-saherelm.xtrade.lib.mq5 index 9f645f74..c2bc8b45 100644 --- a/Libraries/x-saherelm.xtrade.lib.mq5 +++ b/Libraries/x-saherelm.xtrade.lib.mq5 @@ -153,6 +153,7 @@ enum ENUM_X_POSITION_TYPE X_POSITION_TYPE_SHORT = 3, }; +// bool ToPositinType( ENUM_POSITION_TYPE &dest, ENUM_X_POSITION_TYPE source // @@ -179,6 +180,31 @@ bool ToPositinType( return result; } +// +ENUM_X_POSITION_TYPE GetOppositXPositionType(ENUM_POSITION_TYPE type) +{ + // + ENUM_X_POSITION_TYPE result = X_POSITION_TYPE_NONE; + + // + bool isLong = IsLong(type); + bool isShort = IsShort(type); + + // + result = + // + isLong + ? X_POSITION_TYPE_SHORT + : isShort + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_NONE + // + ; + + // + return result; +} + // // Structs ... @@ -2710,6 +2736,27 @@ typedef void (*TOnTakeProfit)(const XDeal &deal); // typedef void (*TOnTradeStateChanged)(const XOnTradeHandlerState &state); +// +typedef void (*TOnForceClose)( + const ulong ticket, + const XPosition &position, + const string comment // +); + +// +typedef void (*TOnPartialClose)( + const ulong ticket, + const double profit, + const string comment // +); + +// +typedef void (*TOnModify)( + const ulong ticket, + const double profit, + const string comment // +); + // // Classes ...