diff --git a/Classes/x-saherelm.x-expert.class.mq5 b/Classes/x-saherelm.x-expert.class.mq5 index db538a7d..824931e3 100644 --- a/Classes/x-saherelm.x-expert.class.mq5 +++ b/Classes/x-saherelm.x-expert.class.mq5 @@ -724,6 +724,33 @@ class XCBaseExpert : public XCBaseAlert { } + /** + * Handle Deals Changed ... + * + * @param count: Integer, Number of Changes ... + */ + virtual void HandleOnDealsChanged(int count) + { + } + + /** + * Handle Orders Changed ... + * + * @param count: Integer, Number of Changes ... + */ + virtual void HandleOnOrdersChanged(int count) + { + } + + /** + * Handle Positions Changed ... + * + * @param count: Integer, Number of Changes ... + */ + virtual void HandleOnPositionsChanged(int count) + { + } + /** * Do All Signalling Processing Here ... */ diff --git a/Classes/x-saherelm.x-trade.class.mq5 b/Classes/x-saherelm.x-trade.class.mq5 index badfc219..1cdf0caf 100644 --- a/Classes/x-saherelm.x-trade.class.mq5 +++ b/Classes/x-saherelm.x-trade.class.mq5 @@ -1083,7 +1083,7 @@ class XCTrade : public XCBase { // // Retrieve Signal Spread ... - double spread = mSignal.GetSpread(); + double spread = GetSpread(mSignal.symbol); result = spread <= mMaxAllowedSpread; } @@ -2145,8 +2145,11 @@ class XCTrade : public XCBase ) { // - return result - .ByIndex(index); + bool isInited = result + .ByIndex(index); + + // + return isInited; } // @@ -2157,8 +2160,11 @@ class XCTrade : public XCBase ) { // - return result - .ByTicket(ticket); + bool isInited = result + .ByTicket(ticket); + + // + return isInited; } // diff --git a/Experts/x-saherelm.x-121.smc.ea.mq5 b/Experts/x-saherelm.x-121.smc.ea.mq5 index 05d12efc..e0f9a0f3 100644 --- a/Experts/x-saherelm.x-121.smc.ea.mq5 +++ b/Experts/x-saherelm.x-121.smc.ea.mq5 @@ -44,7 +44,7 @@ input string eaSymbols = "EURUSDb,GBPUSDb,USDJPYb,USDCHFb"; // Trading Symbols // // Volume ... input group "Volume"; -input double eaR2R = 3.0; // Risk to Reward Ratio +input double eaR2R = 3.0; // Risk to Reward Ratio input bool eaUseDynamicVolume = false; // Use Dynamic Volume input double eaDynamicVolumeStep = 0.01; // Increase Volume Step input double eaDynamicVolumeBalanceFactor = 200; // Balance Factor for Generate Dynamic Volume @@ -109,8 +109,11 @@ int OnInit() // eaExpert.OnSignalEventListener = OnSignalRecieved; + eaExpert.OnDealsChangedEventListener = OnDealsChanged; + eaExpert.OnOrdersChangedEventListener = OnOrdersChanged; eaExpert.OnPositionSLEventListener = OnStopLossTriggered; eaExpert.OnPositionTPEventListener = OnTakeProfitTriggered; + eaExpert.OnPositionsChangedEventListener = OnPositionsChanged; eaExpert.OnPositionForceCloseEventListener = OnPositionForceClosed; // @@ -278,6 +281,36 @@ void OnPositionForceClosed( ); } +/** + * Handle Deals Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnDealsChanged(int count) +{ + eaExpert.HandleOnDealsChanged(count); +} + +/** + * Handle Orders Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnOrdersChanged(int count) +{ + eaExpert.HandleOnOrdersChanged(count); +} + +/** + * Handle Positions Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnPositionsChanged(int count) +{ + eaExpert.HandleOnPositionsChanged(count); +} + // // Custom Functions ... diff --git a/Libraries/x-saherelm.x-trade.lib.mq5 b/Libraries/x-saherelm.x-trade.lib.mq5 index eedbdecc..28e2d13e 100644 --- a/Libraries/x-saherelm.x-trade.lib.mq5 +++ b/Libraries/x-saherelm.x-trade.lib.mq5 @@ -677,6 +677,91 @@ struct XPosition return result; } + // + // Calculate TP Levels ... + int CalculateTPLevels(double &tps[]) + { + + // + int result = 0; + + // + Clean(tps); + + // + bool isValid = IsValid(); + if (!isValid) + { + return result; + } + + // + double risk = GetRisk(); + int r2r = (int)GetRiskRewardRatio(); + bool isLong = IsLong(type); + for (int i = 0; i < r2r; i++) + { + // + double iValue = + isLong + ? entry + risk + (i * risk) + : entry - risk - (i * risk); + // + Add( + iValue, + tps // + ); + } + + // + result = ArraySize(tps); + + // + return result; + } + + // + // Calculate Reached TP Levels ... + void CalculateReahedTP( + double &reachedLevel, + double &reachedPrice // + ) + { + // + reachedLevel = -1; + reachedPrice = 0; + double tps[]; + bool isLong = IsLong(type); + double exitPrice = GetExit(); + int tpLevels = CalculateTPLevels(tps); + if (!IsValidSize(tpLevels) || exitPrice <= 0) + { + return; + } + + // + for (int i = 0; i < tpLevels - 1; i++) + { + // + double cTP = tps[i]; + double nTP = tps[i + 1]; + + // + bool isReached = + isLong + ? exitPrice > cTP && + exitPrice < nTP + : exitPrice < cTP && + exitPrice > nTP; + if (isReached) + { + // + reachedLevel = i + 1; + reachedPrice = cTP; + } + } + } + // // Calculate Age ... int GetAge( @@ -830,6 +915,25 @@ struct XSignal int pushers; // Signal Pushers ... string conditions; // Signal Conditions ... + // + // Additional ... + + // + // TP ... + double fullTPLevel; // Full TP ... + double partialCloseMultiplier; // Amount of Partial Close ... + double partialCloseOnTPLevel; // Do Partial Close on TP Level ... + + // + // RF ... + double tpLevelForBreakEven; // TP Level for Break Even ... + bool riskFreeOnBreakEven; // Risk Free Signal On Break Even ... + + // + // SL Trail ... + bool trailSL; // Do SL Trail ... + double trailSLStartOnReachTPLevel; // Start SL Trail After Reached TP Level ... + // // Constructor ... XSignal() @@ -906,6 +1010,141 @@ struct XSignal return result; } + // + bool PrepareComplex( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_POSITION_TYPE mType, // Long (Buy) or Short (Sell) + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + // + // TP ... + double mFullTPLevel = 0, // Full TP Level + double mPartialCloseOnTPLevel = 0, // Partial Close On TP Level + double mPartialCloseMultiplier = 0, // Partial Close Multiplier + // + // RF ... + bool mRiskFreeOnBreakEven = false, // Risk Free Signal On Break Even ... + double mTpLevelForBreakEven = 0, // TP Level for Break Even ... + // + // SL Trail ... + bool mTrailSL = false, // Trail SL + double mTrailSLStartOnReachTPLevel = 0 // Trail SL Starts after Reached TP Level + ) + { + // + bool result = false; + + // + // Validate Args ... + result = + // + // Common ... + mSL > 0 && + mEntry > 0 && + mVolume > 0 && + IsValid(mSymbol) && + IsValid(mPeriod) && + IsValid(mProvider) && + mMode != X_ORDER_MODE_NOTHING + // + && + // + // TP ... + mFullTPLevel > 0 + // + ; + if (!result) + { + return result; + } + + // + // Prepare Regular Signal Values ... + double _risk = MathAbs(mEntry - mSL); + double _reward = _risk * mFullTPLevel; + + // + bool isLong = IsLong(mType); + + // + sl = mSL; + type = mType; + mode = mMode; + entry = mEntry; + symbol = mSymbol; + period = mPeriod; + volume = mVolume; + provider = mProvider; + fullTPLevel = mFullTPLevel; + tp = isLong + ? mEntry + _reward + : mEntry - _reward; + + // + result = Normalize(); + if (!result) + { + return result; + } + + // + // Calculate Other Conditions ... + + // + bool canPartialClose = + // + mPartialCloseOnTPLevel > 0 && + mPartialCloseMultiplier > 0 && + mPartialCloseOnTPLevel < mFullTPLevel + // + ; + if (canPartialClose) + { + // + partialCloseOnTPLevel = mPartialCloseOnTPLevel; + partialCloseMultiplier = mPartialCloseMultiplier; + } + + // + bool canRFOnBEP = + // + mRiskFreeOnBreakEven && + mTpLevelForBreakEven > 0 + // + ; + if (canRFOnBEP) + { + // + riskFreeOnBreakEven = mRiskFreeOnBreakEven; + tpLevelForBreakEven = mTpLevelForBreakEven; + } + + // + bool canTrailSL = + // + mTrailSL && + mTrailSLStartOnReachTPLevel > 0 && + mTrailSLStartOnReachTPLevel < mFullTPLevel + // + ; + if (canTrailSL) + { + // + trailSL = mTrailSL; + trailSLStartOnReachTPLevel = mTrailSLStartOnReachTPLevel; + } + + // + result = IsValid(); + + // + return result; + } + // bool PrepareLong( string mSymbol, // Trading Symbol @@ -1247,6 +1486,17 @@ struct XSignal provider = NULL; conditions = NULL; + // + trailSL = false; + riskFreeOnBreakEven = false; + + // + fullTPLevel = 0; + tpLevelForBreakEven = 0; + partialCloseOnTPLevel = 0; + partialCloseMultiplier = 0; + trailSLStartOnReachTPLevel = 0; + // Clean(supports); } @@ -1368,74 +1618,6 @@ struct XSignal ); } - // - // Retrieve Entry Price ... - double GetEntry() - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = GetEntry( - symbol, - type - // - ); - - // - return result; - } - - // - // Retrieve Exit ... - double GetExit() - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = GetExit( - symbol, - type - // - ); - - // - return result; - } - - // - // Get Spread by Point ... - double GetSpread() - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = PriceToPoint(GetSpread(symbol)); - - // - return result; - } - // // Find Risk ... double GetRisk() @@ -1496,6 +1678,61 @@ struct XSignal return result; } + // + // Check Can Partial Close on Specified TP Level ... + bool CanPartialClose() + { + // + bool result = false; + + // + result = + IsValid() && + fullTPLevel > 0 && + partialCloseOnTPLevel > 0 && + partialCloseMultiplier > 0 && + partialCloseOnTPLevel < fullTPLevel; + + // + return result; + } + + // + // Check Can Risk Free On Break Even Point ... + bool CanRiskFreeOnBreakEvenPoint() + { + // + bool result = false; + + // + result = + IsValid() && + riskFreeOnBreakEven && + tpLevelForBreakEven > 0; + + // + return result; + } + + // + // Check Can Trail SL ... + bool CanTrailSL() + { + // + bool result = false; + + // + result = + IsValid() && + trailSL && + fullTPLevel > 0 && + trailSLStartOnReachTPLevel > 0 && + trailSLStartOnReachTPLevel < fullTPLevel; + + // + return result; + } + // string GetTag() { @@ -3341,21 +3578,24 @@ struct XSymbolPositions }; // -struct XSymbolLastPosition { +struct XSymbolLastPosition +{ // string symbol; string provider; datetime time; // - XSymbolLastPosition() { + XSymbolLastPosition() + { Clean(); } // // Tools ... - - void Clean() { + + void Clean() + { // time = NULL; symbol = NULL; diff --git a/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 b/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 index 03f323e2..22e9d3ac 100644 --- a/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 +++ b/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 @@ -35,44 +35,34 @@ struct X121SMCTradeData { // - datetime time; // Issue Time (Open Position) - string symbol; // Trading Symbol - double entry; // Entry Price - double volume; // Volume - string provider; // Signaller - ENUM_TIMEFRAMES period; // Trading Timeframe - ENUM_X_POSITION_TYPES type; // Position Type - - // + double ask; // Ask Price on Start Time + double bid; // bid Price on Start Time ulong ticket; // Position Ticket double swap; // Swap double profit; // Profit on Close - double commission; // Commission - double maxDrawdown; // Max Position Drawdown - string message; // Close Reason + XSignal signal; // Signal Object + string message; // Message datetime endTime; // End Time - - // - XSignal signal; // Signal Object - int pushers; // Signal Pushers - string conditions; // Signal Conditions - - // - bool forceTrail; // Force Trail - int trailStep; // Trail Step - bool partiallyClosed; // Partially Closed or not - datetime lastProtectedOn; // Last Protected On + datetime startTime; // Start Time + double commission; // Commission + string conditions; // Signal Conditions + double maxDrawdown; // Max Position Drawdown // // Constructor ... - void X121SMCTradeData() + X121SMCTradeData() { Clean(); } - // - // Filling Trade Handler ... - bool Fill(XSignal &_signal) + /** + * Initialize Item ... + * + * @param _signal: XSignal instance Reference, Provides Source For Initializaion ... + * + * @return ( bool ) + */ + bool Init(XSignal &_signal) { // bool result = false; @@ -81,7 +71,6 @@ struct X121SMCTradeData Clean(); // - // Check Signal Validation ... result = _signal.IsValid(); if (!result) { @@ -90,85 +79,9 @@ struct X121SMCTradeData // signal = _signal; - time = _signal.time; - entry = _signal.entry; - symbol = _signal.symbol; - volume = _signal.volume; - period = _signal.period; - pushers = _signal.pushers; - provider = _signal.provider; - conditions = _signal.conditions; - type = ToPositionType(_signal.type); // - if (_signal.IsExecuted()) - { - ticket = _signal.positionId; - } - - // - return result; - } - - // - // Filling Trade Handler ... - bool Fill(XPosition &_position) - { - // - bool result = false; - - // - Clean(); - - // - // Check Signal Validation ... - result = _position.IsValid(); - if (!result) - { - return result; - } - - // - time = _position.openAt; - symbol = _position.symbol; - entry = _position.entry; - volume = _position.volume; - provider = _position.provider; - period = _position.period; - type = ToPositionType(_position.type); - - // - ticket = _position.ticket; - - // - return result; - } - - // - // Update Data ... - bool Update(XPosition &_position) - { - // - bool result = false; - - // - result = _position.IsValid(); - if (!result) - { - return result; - } - - // - profit = _position.profit; - swap = _position.swap; - - // - if (profit < 0 && - (maxDrawdown == 0 || - MathAbs(profit) > MathAbs(maxDrawdown))) - { - maxDrawdown = profit; - } + result = IsValid(); // return result; @@ -177,40 +90,35 @@ struct X121SMCTradeData // // Tools ... - // - // Cleanup ... + /** + * Cleaning Up Model ... + */ void Clean() { // - time = NULL; - type = NULL; - symbol = NULL; - period = NULL; - endTime = NULL; - message = NULL; - provider = NULL; - - // + ask = 0; + bid = 0; swap = 0; - entry = 0; - ticket = 0; profit = 0; - volume = 0; + ticket = 0; commission = 0; maxDrawdown = 0; // - trailStep = 0; - forceTrail = false; - lastProtectedOn = NULL; - partiallyClosed = false; + endTime = NULL; + message = NULL; + startTime = NULL; + conditions = NULL; // signal.Clean(); } - // - // Validation ... + /** + * Validate Model ... + * + * @return ( bool ) + */ bool IsValid() { // @@ -219,10 +127,7 @@ struct X121SMCTradeData // result = // - ticket > 0 && - IsValid(time) && - IsValid(symbol) && - IsValid(period) + signal.IsValid() // ; @@ -230,35 +135,38 @@ struct X121SMCTradeData return result; } - // - // Retrieve Trade Data Age ... + /** + * Calculate Model Age ... + * + * @return ( int ) + */ int GetAge() { // int result = -1; // - if (!IsValid(symbol) || - !IsValid(time) || - !IsValid(endTime) || - !IsValid(period)) + if (!IsValid()) { return result; } // int startIndex = iBarShift( - symbol, - period, - time, + GetSymbol(), + GetPeriod(), + startTime, false // ); // + datetime mEndTime = IsValid(endTime) + ? endTime + : TimeCurrent(); int endIndex = iBarShift( - symbol, - period, - endTime, + GetSymbol(), + GetPeriod(), + mEndTime, false // ); @@ -270,8 +178,15 @@ struct X121SMCTradeData } // - // Check Own of Trade Data ... - // based on Ticket ... + // Owner Functions ... + + /** + * Check a Ticket is Own to Model or not ... + * + * @param _ticket: ULONG, Position Ticket ... + * + * @return ( bool ) + */ bool IsOwn( ulong _ticket // ) @@ -280,15 +195,23 @@ struct X121SMCTradeData bool result = false; // - result = _ticket == ticket; + result = IsValid() && + _ticket == ticket; // return result; } - // - // Check Own of Trade Data ... - // based on Symbol/Provider and Period ... + /** + * Check Specified Conditions is Own to Model or not ... + * + * @param _symbol: String, Specified Symbol ... + * @param _provider: String, Specified Provider ... + * @param _period: ENUM_TIMEFRAMES member, Specified Signal Period ... + * @param _type: ENUM_X_POSITION_TYPES member, Specified Signal Type ... + * + * @return ( bool ) + */ bool IsOwn( string _symbol, string _provider, @@ -304,14 +227,13 @@ struct X121SMCTradeData // IsValid(_symbol) && IsValid(_period) && + XType() == _type && IsValid(_provider) && - type != X_POSITION_TYPE_ALL && - type != X_POSITION_TYPE_NONE && - // - type == _type && - period == _period && - symbol == _symbol && - provider == _provider + GetPeriod() == _period && + GetSymbol() == _symbol && + Provider() == _provider && + XType() != X_POSITION_TYPE_ALL && + XType() != X_POSITION_TYPE_NONE // ; @@ -319,11 +241,435 @@ struct X121SMCTradeData return result; } - // - // Data Collector ... + /** + * Check Specified Signal is Own to Model or not ... + * + * @param _signal: XSignal instance Reference ... + * + * @return ( bool ) + */ + bool IsOwn(XSignal &_signal) + { + // + bool result = false; + + // + result = + // + IsValid() && + _signal.IsValid() && + IsOwn( + _signal.symbol, + _signal.provider, + _signal.period, + ToPositionType(_signal.type)) + // + ; + + // + return result; + } + + /** + * Check Specified Position is Own to Model or not ... + * + * @param _position: XPosition instance Reference ... + * + * @return ( bool ) + */ + bool IsOwn(XPosition &_position) + { + // + bool result = false; + + // + result = + // + IsValid() && + _position.IsValid() && + IsOwn( + _position.symbol, + _position.provider, + _position.period, + ToPositionType(_position.type)) + // + ; + + // + return result; + } + + /** + * Update Model Data by Providing Specified Signal ... + * + * @param _signal: XSignal instance Reference ... + * + * @return ( bool ) + */ + bool Update(XSignal &_signal) + { + // + bool result = false; + + // + result = + // + IsValid() && + _signal.IsValid() && + IsOwn(_signal) + // + ; + if (!result) + { + return result; + } + + // + signal = _signal; + + // + return result; + } + + /** + * Update Model Data by Providing Specified Position ... + * + * @param _position: XPosition instance Reference ... + * + * @return ( bool ) + */ + bool Update(XPosition &_position) + { + // + bool result = false; + + // + result = + // + IsValid() && + _position.IsValid() && + IsOwn(_position) + // + ; + if (!result) + { + return result; + } + + // + swap = _position.swap; + ticket = _position.ticket; + profit = _position.profit; + message = _position.comment; + startTime = _position.openAt; + + // + // Set Once ... + if (commission == 0 && + _position.commission != 0) + { + commission = _position.commission; + } + + // + // Set Once ... + if (ask == 0) + { + ask = GetAsk(_position.symbol); + } + + // + // Set Once ... + if (bid == 0) + { + bid = GetBid(_position.symbol); + } + + // + if (profit < 0 && profit < maxDrawdown) + { + maxDrawdown = profit; + } + + // + return result; + } // - // Get Data File Name ... + // Tools Extensions ... + + /** + * Get Model Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + return signal.symbol; + } + + /** + * Get Model Period ... + * + * @return ( ENUM_TIMEFRAMES ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + return signal.period; + } + + /** + * Get Model Provider ... + * + * @return ( string ) + */ + string Provider() + { + return signal.provider; + } + + /** + * Get Model Entry ... + * + * @return ( double ) + */ + double Entry() + { + return signal.entry; + } + + /** + * Get Model Stop Loss ... + * + * @return ( double ) + */ + double SL() + { + return signal.sl; + } + + /** + * Get Model Take Profit ... + * + * @return ( double ) + */ + double TP() + { + return signal.tp; + } + + /** + * Get Position Spread on Open Time ... + * + * @return ( double ) + */ + double Spread() + { + return MathAbs(ask - bid); + } + + /** + * Get Model Volume ... + * + * @return ( double ) + */ + double Volume() + { + return signal.volume; + } + + /** + * Get Model Point Value ... + * + * @return ( double ) + */ + double Points() + { + return GetPoints(GetSymbol()); + } + + /** + * Get Model Type ... + * + * @return ( ENUM_POSITION_TYPE ) + */ + ENUM_POSITION_TYPE Type() + { + return signal.type; + } + + /** + * Get Model Type ... + * + * @return ( ENUM_X_POSITION_TYPES ) + */ + ENUM_X_POSITION_TYPES XType() + { + // + ENUM_X_POSITION_TYPES result = X_POSITION_TYPE_NONE; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsLong(Type()) + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + return result; + } + + /** + * Get Model Signal Mode ... + * + * @return ( ENUM_X_ORDER_MODES ) + */ + ENUM_X_ORDER_MODES Mode() + { + return signal.mode; + } + + // + // Additional Helpers Extensions ... + + /** + * Get Signal Full TP Level ... + * + * @return ( double ) + */ + double FullTPLevel() + { + return signal.fullTPLevel; + } + + /** + * Check Can Partial Close Position or not ... + * + * @return ( bool ) + */ + bool CanPartialClose() + { + return signal.CanPartialClose(); + } + + /** + * Retrieve Partial Close Volume Multiplier ... + * + * @return ( double ) + */ + double PartialCloseMultiplier() + { + return signal.partialCloseMultiplier; + } + + /** + * Get Partial Close On TP Level ... + * + * @return ( double ) + */ + double PartialCloseOnTPLevel() + { + return signal.partialCloseOnTPLevel; + } + + /** + * Check Can Risk Free Position on Break Even Point or not ... + * + * @return ( bool ) + */ + bool CanRiskFreeOnBreakEvenPoint() + { + return signal.CanRiskFreeOnBreakEvenPoint(); + } + + /** + * Get Minimum Required Profit after Break Even Point for Risk Free ... + * + * @return ( double ) + */ + double TPLevelForBreakEven() + { + return signal.tpLevelForBreakEven; + } + + /** + * Calculate Break Even Point ... + * + * @return ( double ) + */ + double CalculateBreakEvenPoint() + { + // + double result = 0; + + // + bool isValid = + // + ask > 0 && + bid > 0 && + IsValid() && + ticket > 0 && + signal.IsValid() + // + ; + if (!isValid) + { + return result; + } + + // + // Calculate Spread ... + double spread = Spread(); + if (spread <= 0) + { + return result; + } + + // + // Calculate BEP ... + result = + // + spread + (-1 * swap) + MathAbs(commission) + // + ; + + // + return result; + } + + /** + * Check Can Trail Position Stop Loss or not ... + * + * @return ( bool ) + */ + bool CanTrailSL() + { + return signal.CanTrailSL(); + } + + /** + * Get Start Position SL Trailling on TP Level ... + * + * @return ( double ) + */ + double TrailSLStartOnReachTPLevel() + { + return signal.trailSLStartOnReachTPLevel; + } + + // + // Data Collector Extensions ... + + /** + * Get Data Collection File Name ... + * + * @return ( string ) + */ string GetFileName() { // @@ -338,12 +684,12 @@ struct X121SMCTradeData // result = // - symbol + "\\" + - ToString(type) + "\\" + + GetSymbol() + "\\" + + ToString(XType()) + "\\" + (profit >= 0 ? "Profit" : "Loss") + "\\" + ToString(ticket) + "_" + - ToString(period) + "_" + - ToFormatString(time) + ToString(GetPeriod()) + "_" + + ToFormatString(startTime) // ; @@ -351,8 +697,11 @@ struct X121SMCTradeData return result; } - // - // Get Signal File Name ... + /** + * Get Signal Collectiong File Name ... + * + * @return ( string ) + */ string GetSignalFileName() { // @@ -361,10 +710,10 @@ struct X121SMCTradeData // result = // - symbol + "\\" + - ToString(type) + "\\" + - provider + "_" + - ToFormatString(time) + GetSymbol() + "\\" + + ToString(XType()) + "\\" + + Provider() + "_" + + ToFormatString(startTime) // ; @@ -372,8 +721,13 @@ struct X121SMCTradeData return result; } - // - // Convert(s) To String Representation(s) ... + /** + * Converts Model to String Representation ... + * + * @param onlySignals: Boolean, Specified Represent Only Signal or not ... + * + * @return ( string ) + */ string ToString( bool onlySignals = false // ) @@ -388,18 +742,18 @@ struct X121SMCTradeData result = // (onlySignals ? "" : ToString("Ticket", ticket)) + - ToString("Symbol", symbol) + - ToString("Period", period) + - ToString("Entry", entry) + - ToString("Provider", provider) + - ToString("Type", ToString(type)) + - ToString("Time", time) + + ToString("Symbol", GetSymbol()) + + ToString("Period", GetPeriod()) + + ToString("Entry", Entry()) + + ToString("Provider", Provider()) + + ToString("Type", ToString(XType())) + + ToString("Time", startTime) + // // Attach Trade Info ... (onlySignals ? "" : // "-------------" + "\n" + - ToString("Volume", volume) + + ToString("Volume", Volume()) + ToString("Profit", profit) + ToString("Commission", commission) + ToString("Swap", swap) + @@ -415,7 +769,7 @@ struct X121SMCTradeData (!onlySignals ? "" : // "-------------" + "\n" + - ToString("Pushers", pushers) + + ToString("Pushers", signal.pushers) + "Conditions:" + "\n" + "-------------" + "\n" + conditions + @@ -432,72 +786,11 @@ struct X121SMCTradeData } // + // End Of X121SMCTradeData Model ... }; // -// Model a Position and it's Protected Positions ... -struct X121SMCProtectedPosition -{ - // - XPosition main; // Main Position ... - X121SMCTradeData data; // Trade Handler Data ... - - // - XPosition supports[]; // Support Positions ... - - /** - * Count Supported Positions - */ - int CountSupports() - { - return ArraySize(supports); - } - - /** - * Extract All Positions into Specified Array - * of Positions ... - */ - int ExtractPositions( - XPosition &positions[] // - ) - { - // - int result = 0; - - // - Clean(positions); - - // - if (main.IsValid()) - { - // - AddRef( - main, - positions // - ); - } - - // - int supportsCount = CountSupports(); - if (IsValidSize(supportsCount)) - { - // - Copy( - supports, - positions, - false // - ); - } - - // - result = ArraySize(positions); - - // - return result; - } -}; - -// +// Model Specified Symbol's Positions States ... struct X121SMCSymbolPositionInfo { // @@ -518,7 +811,8 @@ struct X121SMCSymbolPositionInfo int countedSLs; // - void X121SMCSymbolPositionInfo() + // Constructor ... + X121SMCSymbolPositionInfo() { Clean(); } @@ -680,6 +974,7 @@ struct X121SMCSymbolPositionInfo } // + // End of X121SMCSymbolPositionInfo Model ... }; // @@ -697,7 +992,7 @@ class X121SMCTradeCollector // // Constructor(s) ... - void X121SMCTradeCollector( + X121SMCTradeCollector( string _path = NULL // Base Path ) { @@ -717,11 +1012,17 @@ class X121SMCTradeCollector // // Deconstructor ... - void ~X121SMCTradeCollector() + ~X121SMCTradeCollector() { } - // + /** + * Check Specified Model is Exists or not ... + * + * @param item: X121SMCTradeData instance Reference, Provides Source Model ... + * + * @return ( bool ) + */ bool IsExists(X121SMCTradeData &item) { // @@ -736,7 +1037,13 @@ class X121SMCTradeCollector return result; } - // + /** + * Save Specified Model as Data ... + * + * @param item: X121SMCTradeData instance Reference, Provides Source Model ... + * + * @return ( bool ) + */ bool Save(X121SMCTradeData &item) { // @@ -778,7 +1085,13 @@ class X121SMCTradeCollector return result; } - // + /** + * Save Specified Model as Signal ... + * + * @param item: X121SMCTradeData instance Reference, Provides Source Model ... + * + * @return ( bool ) + */ bool SaveSignal(X121SMCTradeData &item) { // @@ -809,10 +1122,16 @@ class X121SMCTradeCollector return result; } - // - // Conditions only save for Loss Signals ... - // this means the profit must be Lower than Zero ... - // ans also message Contains SL ... + /** + * Save Specified Model Conditions ... + * Conditions only save for Loss Signals ... + * this means the profit must be Lower than Zero ... + * ans also message Contains SL ... + * + * @param item: X121SMCTradeData instance Reference, Provides Source Model ... + * + * @return ( bool ) + */ bool SaveConditions(X121SMCTradeData &item) { // @@ -926,11 +1245,11 @@ class X121SMCTradeCollector string GetConditionsFilePath(X121SMCTradeData &item) { // - bool isLong = IsLong(item.type); + bool isLong = IsLong(item.Type()); // string fileName = - item.symbol + "\\" + + item.GetSymbol() + "\\" + (isLong ? "Longs" : "Shorts"); // @@ -1083,10 +1402,14 @@ class X121SMCTradeCollector // return result; } + + // + // End of X121SMCTradeCollector Class ... }; // // Trade Handler Class ... +// a Class For Handling All Trade Requirements ... class XC121SMCTradeHandler : public XCBaseAlert { // @@ -1096,7 +1419,7 @@ class XC121SMCTradeHandler : public XCBaseAlert // // Constructor(s) ... - void XC121SMCTradeHandler(XCTrade *trader) + XC121SMCTradeHandler(XCTrade *trader) { // mTrader = trader; @@ -1106,7 +1429,7 @@ class XC121SMCTradeHandler : public XCBaseAlert // // Deconstructor ... - void ~XC121SMCTradeHandler() + ~XC121SMCTradeHandler() { // delete mTrader; @@ -1114,75 +1437,174 @@ class XC121SMCTradeHandler : public XCBaseAlert } // - // Getter(s) / Setter(s) ... + // ReadOnly Props ... + + /** + * Get Max Same Time Trades ... + * + * @return ( double ) + */ + double GetMaxSameTimeTrades() + { + return maxSameTimeTrades; + } + + /** + * Get Max Drawdown Happens ... + * + * @return ( double ) + */ + double GetMaxDrawdown() + { + return maxDrawdown; + } + + /** + * Get Currently Drawdown of Account ... + * + * @return ( double ) + */ + double GetCurrentDrawdown() + { + return currentDrawdown; + } + + /** + * Get Account Current Drawdown Percent ... + * + * @return ( double ) + */ + double GetDrawdownPercent() + { + return drawdownPercent; + } // + // Properties Getter(s) / Setter(s) ... + + // + // Saving Properties ... + + /** + * Get Save Signals State ... + * + * @return ( bool ) + */ bool SaveSignals() { return mSaveSignals; } - // + /** + * Set Save Signals State ... + * + * @param value: Boolean ... + */ void SaveSignals(bool value) { mSaveSignals = value; } - // + /** + * Get Save Trades State ... + * + * @return ( bool ) + */ bool SaveTrades() { return mSaveTrades; } - // + /** + * Set Save Trades State ... + * + * @param value: Boolean ... + */ void SaveTrades(bool value) { mSaveTrades = value; } - // + /** + * Get Save Conditions State ... + * + * @return ( bool ) + */ bool SaveConditions() { return mSaveConditions; } - // + /** + * Set Save Conditions State ... + * + * @param value: Boolean ... + */ void SaveConditions(bool value) { mSaveConditions = value; } // + // Signalling Properties ... + + /** + * Get Allow Long Signals State ... + * + * @return ( bool ) + */ bool AllowLong() { return mAllowLong; } - // + /** + * Set Allow Long Signals State ... + * + * @param value: Boolean ... + */ void AllowLong(bool value) { mAllowLong = value; } - // + /** + * Get Allow Short Signals State ... + * + * @return ( bool ) + */ bool AllowShort() { return mAllowShort; } - // + /** + * Set Allow Short Signals State ... + * + * @param value: Boolean ... + */ void AllowShort(bool value) { mAllowShort = value; } - // + /** + * Get Max Allowed Long Signals ... + * = 0 => Unlimited ... + * + * @return ( int ) + */ int MaxAllowedLongs() { return mMaxAllowedLongs; } - // + /** + * Set Max Allowed Long Signals ... + * = 0 => Unlimited ... + * + * @param value: Integer ... + */ void MaxAllowedLongs(int value) { // @@ -1195,13 +1617,23 @@ class XC121SMCTradeHandler : public XCBaseAlert mMaxAllowedLongs = value; } - // + /** + * Get Max Allowed Short Signals ... + * = 0 => Unlimited ... + * + * @return ( int ) + */ int MaxAllowedShorts() { return mMaxAllowedShorts; } - // + /** + * Set Max Allowed Short Signals ... + * = 0 => Unlimited ... + * + * @param value: Integer ... + */ void MaxAllowedShorts(int value) { // @@ -1214,26 +1646,43 @@ class XC121SMCTradeHandler : public XCBaseAlert mMaxAllowedShorts = value; } - // + /** + * Get Use Max Allowed Signals Per Symbol or at All State ... + * + * @return ( bool ) + */ bool UseMaxAllowedTradesPerSymbol() { return mUseMaxAllowedTradesPerSymbol; } - // + /** + * Set Use Max Allowed Signals Per Symbol or at All State ... + * + * @param value: Boolean ... + */ void UseMaxAllowedTradesPerSymbol(bool value) { mUseMaxAllowedTradesPerSymbol = value; } - // - double MaxDrawdownPercentForOpenTrades() + /** + * Get Additional Signal Volume ... + * + * @return ( double ) + */ + double AdditionalVolume() { - return mMaxDrawdownPercentForOpenTrades; + return mAdditionalVolume; } - // - void MaxDrawdownPercentForOpenTrades(double value) + /** + * Set Additional Signal Volume ... + * + * @param value: Double ... + * min = 0.01 + */ + void AdditionalVolume(double value) { // if (value < 0) @@ -1242,31 +1691,32 @@ class XC121SMCTradeHandler : public XCBaseAlert } // - mMaxDrawdownPercentForOpenTrades = value; + if (value > 0 && value < 0.01) + { + value = 0.01; + } + + // + mAdditionalVolume = value; } - // - // Protector Start ... - - // - bool UseForceMomentumsInProtection() - { - return mUseForceMomentumsInProtection; - } - - // - void UseForceMomentumsInProtection(bool value) - { - mUseForceMomentumsInProtection = value; - } - - // + /** + * Get How Many Bars Must Passed after a Signal for Accept Next ... + * 0 => Unlimited ... + * + * @return ( int ) + */ int DelayBarBetweenTwoSignal() { return mDelayBarBetweenTwoSignal; } - // + /** + * Set How Many Bars Must Passed after a Signal for Accept Next ... + * + * @param value: Integer ... + * 0 => Unlimited ... + */ void DelayBarBetweenTwoSignal(int value) { // @@ -1279,14 +1729,24 @@ class XC121SMCTradeHandler : public XCBaseAlert mDelayBarBetweenTwoSignal = value; } - // - int MaxAllowedSLToPause() + /** + * Get Max Allowed Drawdown Percent for Open New Positions ... + * 0 => Unlimited ... + * + * @return ( double ) + */ + double MaxDrawdownPercentForOpenTrades() { - return mMaxAllowedSLToPause; + return mMaxDrawdownPercentForOpenTrades; } - // - void MaxAllowedSLToPause(int value) + /** + * Set Max Allowed Drawdown Percent for Open New Positions ... + * + * @param value: Double ... + * 0 => Unlimited ... + */ + void MaxDrawdownPercentForOpenTrades(double value) { // if (value < 0) @@ -1295,35 +1755,26 @@ class XC121SMCTradeHandler : public XCBaseAlert } // - mMaxAllowedSLToPause = value; + mMaxDrawdownPercentForOpenTrades = value; } - // - int MaxAllowedSLReachedPauseDelay() - { - return mMaxAllowedSLReachedPauseDelay; - } - - // - void MaxAllowedSLReachedPauseDelay(int value) - { - // - if (value < 0) - { - value = 0; - } - - // - mMaxAllowedSLReachedPauseDelay = value; - } - - // + /** + * Get Accept Next Same Type Signal only When last Issued Signal is InProfit by Points ... + * + * @return ( double ) + * 0 => Accept All ... + */ double AcceptNextSameTypeSignalWhenLastInProfit() { return mAcceptNextSameTypeSignalWhenLastInProfit; } - // + /** + * Set Accept Next Same Type Signal only When last Issued Signal is InProfit by Points ... + * + * @param value: Double ... + * 0 => Accept All ... + */ void AcceptNextSameTypeSignalWhenLastInProfit(double value) { // @@ -1337,31 +1788,26 @@ class XC121SMCTradeHandler : public XCBaseAlert } // - // In Profit Position Protecting ... + // Protecting Properties ... - // - // Trail ... - - // - bool AllowTrail() + /** + * Get Max Allower SL Per Symbol before Pausing ... + * 0 => Unlimited ... + * + * @return ( int ) + */ + int MaxAllowedSLToPause() { - return mAllowTrail; + return mMaxAllowedSLToPause; } - // - void AllowTrail(bool value) - { - mAllowTrail = value; - } - - // - double TrailStartDistance() - { - return mTrailStartDistance; - } - - // - void TrailStartDistance(double value) + /** + * Set Max Allower SL Per Symbol before Pausing ... + * + * @param value: Integer ... + * 0 => Unlimited ... + */ + void MaxAllowedSLToPause(int value) { // if (value < 0) @@ -1370,17 +1816,27 @@ class XC121SMCTradeHandler : public XCBaseAlert } // - mTrailStartDistance = value; + mMaxAllowedSLToPause = value; } - // - double TrailStep() + /** + * Get Specified Delay For Pause Symbol Trade if Reached Max Allowed SL in Seconds ... + * 0 => Ignored ... + * + * @return ( int ) + */ + int MaxAllowedSLReachedPauseDelay() { - return mTrailStep; + return mMaxAllowedSLReachedPauseDelay; } - // - void TrailStep(double value) + /** + * Set Specified Delay For Pause Symbol Trade if Reached Max Allowed SL in Seconds ... + * + * @param value: Integer ... + * 0 => Ignored ... + */ + void MaxAllowedSLReachedPauseDelay(int value) { // if (value < 0) @@ -1389,286 +1845,69 @@ class XC121SMCTradeHandler : public XCBaseAlert } // - mTrailStep = value; - } - - // - int RemoveTPAfterTrailedLevel() - { - return mRemoveTPAfterTrailedLevel; - } - - // - void RemoveTPAfterTrailedLevel(int value) - { - // - if (value < 0) - { - value = 0; - } - - // - mRemoveTPAfterTrailedLevel = value; - } - - // - bool OnlyTrailUnprotected() - { - return mOnlyTrailUnprotected; - } - - // - void OnlyTrailUnprotected(bool value) - { - mOnlyTrailUnprotected = value; - } - - // - // Partial Close (In Profit) ... - - // - double PartialCloseInProfitDistance() - { - return mPartialCloseInProfitDistance; - } - - // - void PartialCloseInProfitDistance(double value) - { - // - if (value < 0) - { - value = 0; - } - - // - mPartialCloseInProfitDistance = value; - } - - // - double PartialCloseInProfitVolume() - { - return mPartialCloseInProfitVolume; - } - - // - void PartialCloseInProfitVolume(double value) - { - // - if (value < 0) - { - value = 0; - } - - // - mPartialCloseInProfitVolume = value; - } - - // - // In Drawdown Positions Protecting ... - - // - // Protect ... - - // - bool AllowProtect() - { - return mAllowProtect; - } - - // - void AllowProtect(bool value) - { - mAllowProtect = value; - } - - // - double ProtectionStartDistance() - { - return mProtectionStartDistance; - } - - // - void ProtectionStartDistance(double value) - { - // - if (value < 0) - { - value = 0; - } - - // - mProtectionStartDistance = value; - } - - // - int ProtectionDelay() - { - return mProtectionDelay; - } - - // - void ProtectionDelay(int value) - { - // - if (value < 0) - { - value = 0; - } - - // - mProtectionDelay = value; - } - - // - double ProtectionVolumeMultiplier() - { - return mProtectionVolumeMultiplier; - } - - // - void ProtectionVolumeMultiplier(double value) - { - // - if (value < 1) - { - value = 1; - } - - // - mProtectionVolumeMultiplier = value; - } - - // - int MaxAllowedProtection() - { - return mMaxAllowedProtection; - } - - // - void MaxAllowedProtection(int value) - { - // - if (value < 0) - { - value = 0; - } - - // - mMaxAllowedProtection = value; - } - - // - bool UseEntryAsProtectionSL() - { - return mUseEntryAsProtectionSL; - } - - // - void UseEntryAsProtectionSL(bool value) - { - mUseEntryAsProtectionSL = value; - } - - // - bool ProtectOnConditions() - { - return mProtectOnConditions; - } - - // - void ProtectOnConditions(bool value) - { - mProtectOnConditions = value; - } - - // - bool AllowDirectionProtct() - { - return mAllowDirectionProtct; - } - - // - void AllowDirectionProtct(bool value) - { - mAllowDirectionProtct = value; - } - - // - // Partial Close (In Drawdown) ... - - // - double PartialCloseInDrawdownDistance() - { - return mPartialCloseInDrawdownDistance; - } - - // - void PartialCloseInDrawdownDistance(double value) - { - // - if (value < 0) - { - value = 0; - } - - // - mPartialCloseInDrawdownDistance = value; - } - - // - double PartialCloseInDrawdownVolume() - { - return mPartialCloseInDrawdownVolume; - } - - // - void PartialCloseInDrawdownVolume(double value) - { - // - if (value < 0) - { - value = 0; - } - - // - mPartialCloseInDrawdownVolume = value; + mMaxAllowedSLReachedPauseDelay = value; } // // Hedge Props ... - // + /** + * Get Allow Hedge Position State ... + * + * @return ( bool ) + */ bool AllowHedge() { return mAllowHedge; } - // + /** + * Set Allow Hedge Position State ... + * + * @param value: Boolean ... + */ void AllowHedge(bool value) { mAllowHedge = value; } - // + /** + * Get Minimum Volume Steps for Hedge Requirement Calculation ... + * 0 => Ignore Hedging ... + * min => 0.01 ... + * max => 0.1 ... + * + * @return ( double ) + */ double HedgeMinVolumeStep() { return mHedgeMinVolumeStep; } - // - // Min: 0.01 - // Max 0.1 + /** + * Set Minimum Volume Steps for Hedge Requirement Calculation ... + * + * @param value: Double ... + * 0 => Ignore Hedging ... + * min => 0.01 ... + * max => 0.1 ... + */ void HedgeMinVolumeStep(double value) { // - if (value < 0.01) + if (value < 0) + { + value = 0; + } + + // + if (value > 0 && value < 0.01) { value = 0.01; } // - if (value > 0.1) + if (value > 0 && value > 0.1) { value = 0.1; } @@ -1677,14 +1916,24 @@ class XC121SMCTradeHandler : public XCBaseAlert mHedgeMinVolumeStep = value; } - // - int MinimumOpenPositionsForHEHedge() + /** + * Get Minimum Requirement Open Positions for Hedging ... + * 0 => Ignore Hedging ... + * + * @return ( int ) + */ + int MinimumOpenPositionsForHedge() { - return mMinimumOpenPositionsForHEHedge; + return mMinimumOpenPositionsForHedge; } - // - void MinimumOpenPositionsForHEHedge(int value) + /** + * Set Minimum Requirement Open Positions for Hedging ... + * + * @param value: Integer ... + * 0 => Ignore Hedging ... + */ + void MinimumOpenPositionsForHedge(int value) { // if (value < 0) @@ -1693,325 +1942,206 @@ class XC121SMCTradeHandler : public XCBaseAlert } // - mMinimumOpenPositionsForHEHedge = value; + mMinimumOpenPositionsForHedge = value; } - // - double HedgeHEMinProfitPerVolumeStep() - { - return mHedgeHEMinProfitPerVolumeStep; - } - - // - // Min: 0.01 - void HedgeHEMinProfitPerVolumeStep(double value) - { - // - if (value < 0.01) - { - value = 0.01; - } - - // - mHedgeHEMinProfitPerVolumeStep = value; - } - - // - double HedgeBEMinProfitPerVolumeStep() - { - return mHedgeBEMinProfitPerVolumeStep; - } - - // - // Min: 0.01 - void HedgeBEMinProfitPerVolumeStep(double value) - { - // - if (value < 0.01) - { - value = 0.01; - } - - // - mHedgeBEMinProfitPerVolumeStep = value; - } - - // - // Read Only Props ... - - // - int MaxSameTimeTrades() - { - return maxSameTimeTrades; - } - - // - // Calculate Max Drawdown and it's Percent ... - double GetMaxDrawdown() - { - // - XPosition positions[]; - int positionsCount = mTrader.GetPositions(positions); - if (IsValidSize(positionsCount)) - { - double mEquity = mTrader.mAccount.GetEquity(); - if (mEquity > maxDrawdown) - { - maxDrawdown = mEquity; - } - - // - drawdownPercent = (maxDrawdown - mEquity) / (staticBalanceForCalculateDrawdown > 0 ? staticBalanceForCalculateDrawdown : maxDrawdown) * 100; - drawdownPercent = NormalizeDouble(drawdownPercent, 3); - } - else - { - // - maxDrawdown = 0.0; - drawdownPercent = 0.0; - } - - // - return drawdownPercent; - } - - // - double AdditionalVolume() - { - return mAdditionalVolume; - } - - // - // Position Retrievers ... - /** - * Retrieve Positions as XProtetedPosition structure - * @param positions: Argument 1 - * @return ( int ) + * Get Minimum Required Profit Per Volume Step for Hedging ... + * 0 => Ignore Hedging ... + * + * @return ( double ) */ - int GetPositions( - X121SMCProtectedPosition &positions[] // - ) + double HedgeMinProfitPerVolumeStep() + { + return mHedgeMinProfitPerVolumeStep; + } + + /** + * Set Minimum Required Profit Per Volume Step for Hedging ... + * + * @param value: Double ... + * 0 => Ignore Hedging ... + * min => 0.01 ... + */ + void HedgeMinProfitPerVolumeStep(double value) { // - int result = 0; - - // - Clean(positions); - - // - // Retrieve Positions from Trader Class ... - XPosition allPositions[]; - int allPositionsCount = mTrader.GetPositions( - allPositions, - NULL, // All Symbols ... - NULL, // All Providers ... - NULL, // All Periods ... - X_POSITION_TYPE_ALL, // Long and Short ... - false, // Filter By Magic ... - true // Force Clean ... - ); - if (!IsValidSize(allPositionsCount)) + if (value < 0) { - return result; + value = 0; } // - // Filter Support Positions ... - XPosition mainPositions[]; - XPosition supportPositions[]; - for (int i = 0; i < allPositionsCount; i++) + if (value > 0 && value < 0.01) { - // - XPosition iPosition = allPositions[i]; - - // - // Check Validation ... - if (!iPosition.IsValid()) - { - continue; - } - - // - // Check Position Support or not ... - bool isSupport = IsSupport(iPosition.comment); - if (isSupport) - { - // - AddRef( - iPosition, - supportPositions // - ); - continue; - } - - // - AddRef( - iPosition, - mainPositions // - ); + value = 0.01; } // - // Check Main Positions Count ... - int mainPositionsCount = ArraySize(mainPositions); - if (!IsValidSize(mainPositionsCount)) - { - return result; - } - - // - int supportPositionsCount = ArraySize(supportPositions); - - // - for (int i = 0; i < mainPositionsCount; i++) - { - // - XPosition iPosition = mainPositions[i]; - - // - X121SMCProtectedPosition iProtected; - iProtected.main = iPosition; - Clean(iProtected.supports); - - // - // Loop Through Support Positions To Find iPositions Support ... - if (IsValidSize(supportPositionsCount)) - { - // - for (int j = 0; j < supportPositionsCount; j++) - { - // - XPosition jSupport = supportPositions[j]; - - // - ulong supportParentTicket = ExtractSupportedTicket(jSupport.comment); - bool isSupport = supportParentTicket > 0; - if (isSupport && - supportParentTicket == iPosition.ticket) - { - // - AddRef( - jSupport, - iProtected.supports // - ); - } - - // - ulong eqmSupportParentTicket = ExtractEQMSupportedTicket(jSupport.comment); - bool isEQMSupport = eqmSupportParentTicket > 0; - if (isEQMSupport && - eqmSupportParentTicket == iPosition.ticket) - { - // - AddRef( - jSupport, - iProtected.supports // - ); - } - } - } - - // - // Findout X121SMCTradeData ... - int iIDX = -1; - bool hasItem = HasItem( - iPosition.ticket, - iIDX // - ); - if (hasItem && IsValidIndex(iIDX)) - { - iProtected.data = mData[iIDX]; - } - - // - AddRef( - iProtected, - positions // - ); - } - - // - Clean(allPositions); - Clean(mainPositions); - Clean(supportPositions); - - // - result = ArraySize(positions); - - // - return result; + mHedgeMinProfitPerVolumeStep = value; } // - // Trade Handling Functions ... + // Actions ... // - // First Step of Trade Handling ... - // Since Must Call when a Signal Executed ... - void AddData( - XSignal &signal, // Executed Signal - double commission = 0, // Commission - // - // Force Protections ... - bool forceTrail = false // Force Trail Stops ... - ) + // Data Collection Actions ... + + /** + * Add Executed Signal Data Model to Trade Datas ... + * + * @param signal: XSignal instance Reference, Issued Signal ... + */ + void Add(XSignal &signal) { // - // Check Signal Valid ... + // Check Signal is Valid and also not Exists + // in Datas ... + int idx = -1; + bool hasItem = HasItem( + signal, + idx // + ); + if (hasItem) + { + return; + } + + // + // Initialize Data Item and Add it to Collection of Datas + // if Everythings OK ... + X121SMCTradeData data; + bool isInited = data.Init(signal); + if (isInited) + { + // + Add(data); + SaveSignal(data); + } + } + + /** + * Update a Registered Data Model by Providing Specified Signal ... + * usually used When a signal Modified after Executed for Conditionally Signals ... + * + * @param signal: XSignal instance Reference, Issued Signal ... + */ + void Update(XSignal &signal) + { + // + // Validate Signal ... if (!signal.IsValid()) { return; } // - // Check Signal Support or Recovery ... - bool isSupport = IsSupport(signal.comment); - bool isRecovery = ExtractRecoveredTicket(signal.comment) > 0; + // Check Signal Registered Before ... + int idx = -1; + bool hasItem = HasItem( + signal, + idx // + ); + bool isUpdated = false; + if (!hasItem) + { + // + // Add New Item if not Exists ... + Add(signal); + isUpdated = true; + } + else + { + // + // Update Data Model in Datas Collection ... + isUpdated = mData[idx].Update(signal); + } // - X121SMCTradeData item; - bool isFilled = item.Fill(signal); - if (!isFilled) + if (isUpdated) + { + SaveSignal(mData[idx]); + } + } + + /** + * Update a Registered Data Model by Providing Specified Position ... + * used for Updating Positions Data or When a Conditional Order Executed as Position ... + * + * @param position: XPosition instance Referece ... + */ + void Update(XPosition &position) + { + // + // Validate Position ... + if (!position.IsValid()) { return; } // - item.commission = commission; - - // - // Checking Trailling Configs ... - double trailStep = TrailStep(); - double trailStartDistance = TrailStartDistance(); - bool enableTrail = - trailStep > 0 && - trailStartDistance > 0; - - // - bool onlyTrailUnprotecteds = OnlyTrailUnprotected(); - bool canCheck = - (onlyTrailUnprotecteds - ? !isSupport && - !isRecovery - : true) && - enableTrail; - if (canCheck) + // Check Position Registered Before ... + int idx = -1; + bool hasItem = HasItem( + position, + idx // + ); + if (!hasItem) { - item.forceTrail = forceTrail; + return; } // - Add(item); - - // - SaveSignal(item); + // Update Data Model in Datas Collection ... + mData[idx].Update(position); } - // + /** + * Remove Specified Registered Signal from Data Collection ... + * + * @param signal: XSignal instance Reference ... + */ + void Remove(XSignal &signal) + { + // + // Validate Signal ... + if (!signal.IsValid()) + { + return; + } + + // + // Check Signal is Registered or not ... + int idx = -1; + bool hasItem = HasItem( + signal, + idx // + ); + if (!hasItem) + { + return; + } + + // + // Remove Data From Collection ... + ArrayRemove( + mData, + idx, + 1 // + ); + } + + /** + * Handle Position Execution Finished by Providing a Deal ... + * usually used when a Position TP/SL Triggered ... + * + * @param deal: XDeal instance Reference ... + */ void Finish(const XDeal &deal) { // + // Validate Deal ... + // Check Specified Data Registered or not ... int idx = -1; bool hasItem = HasItem( deal.positionId, @@ -2023,16 +2153,18 @@ class XC121SMCTradeHandler : public XCBaseAlert } // - // Update Item Info ... + // Update Data Info ... mData[idx].swap = deal.swap; mData[idx].endTime = deal.time; mData[idx].profit = deal.profit; // + // Check Deal Reason ... bool isTP = deal.reason == DEAL_REASON_TP; bool isSL = deal.reason == DEAL_REASON_SL; // + // Prepare Specified Message Based on Deal Reason ... mData[idx].message = isTP ? "TP" @@ -2041,22 +2173,25 @@ class XC121SMCTradeHandler : public XCBaseAlert : ""; // + // Handle Symbol Positions TP or SL Actions ... if (isTP || isSL) { // + // Check Symbol Position Info Model Exists ... int symbolIDX = -1; bool hasInfo = HasSymbol( - mData[idx].symbol, + mData[idx].GetSymbol(), symbolIDX // ); // + // Try to Update or Add Symbol Position Info ... X121SMCSymbolPositionInfo info; if (!hasInfo) { // // Add New One ... - info.symbol = mData[idx].symbol; + info.symbol = mData[idx].GetSymbol(); } else { @@ -2074,9 +2209,12 @@ class XC121SMCTradeHandler : public XCBaseAlert } // - ENUM_POSITION_TYPE xType = IsLong(mData[idx].type) + ENUM_POSITION_TYPE xType = IsLong(mData[idx].Type()) ? POSITION_TYPE_BUY : POSITION_TYPE_SELL; + + // + // Call Propper TP / SL Handlers on Symbol Position Info Model ... if (isTP) { info.HandleTP(xType); @@ -2087,20 +2225,30 @@ class XC121SMCTradeHandler : public XCBaseAlert } // + // Add Model to Symbol Positions Collection ... AddRef( info, mSymbolInfos // ); // - HandlePauseSymbol(mData[idx].symbol); + // Try to Check Symbol Positions Info Collection for Pause Specified Symbol ... + HandlePauseSymbol(mData[idx].GetSymbol()); } // + // Save Collector Calss Data Model ... Save(idx); } - // + /** + * Handle Position Execution Finished by Providing some Data ... + * usually used when a Position Force Closed Triggered ... + * + * @param ticket: ULong, Position ticket ... + * @param position: XPosition instance Reference ... + * @param comment: String, Force Closing Comment ... + */ void Finish( const ulong ticket, const XPosition &position, @@ -2108,6 +2256,7 @@ class XC121SMCTradeHandler : public XCBaseAlert ) { // + // Validate and Check Data Registered or not ... int idx = -1; bool hasItem = HasItem( ticket, @@ -2119,7 +2268,7 @@ class XC121SMCTradeHandler : public XCBaseAlert } // - // Update Item Info ... + // Update Data Info ... mData[idx].swap = position.swap; mData[idx].endTime = TimeCurrent(); mData[idx].profit = position.profit; @@ -2128,10 +2277,13 @@ class XC121SMCTradeHandler : public XCBaseAlert mData[idx].message = comment; // + // Handle Force Closes as TP/SL for Updating + // Symbol Info Positions ... bool handleForceClose = true; if (handleForceClose) { // + // Simulate TP/SL based on Closing Profit ... bool isTP = position.profit > 0; bool isSL = position.profit < 0; @@ -2139,19 +2291,21 @@ class XC121SMCTradeHandler : public XCBaseAlert if (isTP || isSL) { // + // Check Symbol Position Info Model Exists ... int symbolIDX = -1; bool hasInfo = HasSymbol( - mData[idx].symbol, + mData[idx].GetSymbol(), symbolIDX // ); // + // Try to Update or Add Symbol Position Info ... X121SMCSymbolPositionInfo info; if (!hasInfo) { // // Add New One ... - info.symbol = mData[idx].symbol; + info.symbol = mData[idx].GetSymbol(); } else { @@ -2169,9 +2323,12 @@ class XC121SMCTradeHandler : public XCBaseAlert } // - ENUM_POSITION_TYPE xType = IsLong(mData[idx].type) + ENUM_POSITION_TYPE xType = IsLong(mData[idx].Type()) ? POSITION_TYPE_BUY : POSITION_TYPE_SELL; + + // + // Call Propper TP / SL Handlers on Symbol Position Info Model ... if (isTP) { info.HandleTP(xType); @@ -2182,176 +2339,60 @@ class XC121SMCTradeHandler : public XCBaseAlert } // + // Add Model to Symbol Positions Collection ... AddRef( info, mSymbolInfos // ); // - HandlePauseSymbol(mData[idx].symbol); + // Try to Check Symbol Positions Info Collection for Pause Specified Symbol ... + HandlePauseSymbol(mData[idx].GetSymbol()); } // + // Save Collector Calss Data Model ... Save(idx); } } - // - // this Method call's by a Timer, - // or in OnTick for Update Positions, - // Data ... - void UpdateData() + /** + * Update New Open Positions Data on Collection ... + */ + void HandleNewPosition() { // - XPosition positions[]; - int count = mTrader.GetPositions(positions); - if (!IsValidSize(count)) + // Retrieve Last Open Position ... + ulong lastOpenPositionTicket = mTrader.GetLastOpenPositionTicket(); + if (lastOpenPositionTicket == 0) { return; } // - for (int i = 0; i < count; i++) - { - // - XPosition iPosition = positions[i]; - - // - int idx = -1; - bool isExists = HasItem( - iPosition.ticket, - idx // - ); - if (!isExists) - { - // - // Add New Data ... - - // - // Find Executed Signal Deal History ... - XDeal deals[]; - double commission = 0; - int dealsCount = mTrader.GetDeals( - deals, - iPosition.symbol, - iPosition.provider, - iPosition.period, - NULL, - DEAL_ENTRY_IN // - ); - if (IsValidSize(dealsCount)) - { - // - for (int i = 0; i < dealsCount; i++) - { - // - XDeal iDeal = deals[i]; - if (iDeal.positionId == iPosition.ticket) - { - // - commission = iDeal.commission; - break; - } - } - } - - // - X121SMCTradeData iData; - iData.Fill( - iPosition // - ); - - // - iData.ticket = iPosition.ticket; - - // - Add(iData); - } - else - { - // - // Update Exists ... - mData[idx].Update(iPosition); - } - } - - // - count = Count(); - if (count > maxSameTimeTrades) - { - maxSameTimeTrades = count; - } - - // - GetMaxDrawdown(); - } - - // - void UpdateSignal(XSignal &signal) - { - // - if (!signal.IsValid()) - { - return; - } - - // - int count = Count(); - if (!IsValidSize(count)) - { - return; - } - - // - for (int i = 0; i < count; i++) - { - // - bool isOwn = mData[i].IsOwn( - signal.symbol, - signal.provider, - signal.period, - ToPositionType(signal.type) // - ); - if (isOwn) - { - mData[i].Fill(signal); - } - } - } - - // - void RemoveSignal(XSignal &signal) - { - // - if (!signal.IsValid()) - { - return; - } - - // - int signalIDX = -1; - ENUM_X_POSITION_TYPES xType = ToPositionType(signal.type); - bool hasSignal = HasItem( - signal.symbol, - signal.provider, - signal.period, - xType, - signalIDX // + XPosition position; + bool hasPosition = mTrader.GetPosition( + lastOpenPositionTicket, + position // ); - if (!hasSignal || !IsValidIndex(signalIDX)) + if (!hasPosition) { return; } // - // Remove Item From List ... - ArrayRemove( - mData, - signalIDX, - 1 // - ); + // Calculate Position Commission ... + double commission = mTrader.GetPositionCommission(position.ticket); + position.commission = commission; + + // + // Apply Updates on Data Collection ... + Update(position); } + // + // Symbol Position Info Actions ... + /** * Retrieve Specified Symbols Info ... * @@ -2389,1376 +2430,6 @@ class XC121SMCTradeHandler : public XCBaseAlert return result; } - /** - * Reset Specified Symbol Info ... - * - * @param symbol: String ... - */ - void ResetSymbolInfo(string symbol) - { - // - if (!IsValid(symbol)) - { - return; - } - - // - int symbolIDX = -1; - bool hasSymbol = HasSymbol( - symbol, - symbolIDX // - ); - if (!hasSymbol) - { - return; - } - - // - mSymbolInfos[symbolIDX].Reset(); - } - - // - // Position Execute and Sync Functions ... - - /** - * Validate Signal For Execution ... - */ - bool CanExecute(XSignal &signal) - { - // - bool result = false; - - // - // Validate Signal ... - result = signal.IsValid(); - if (!result) - { - return result; - } - - // - int symbolIDX = -1; - bool hasSymbolInfo = HasSymbol( - signal.symbol, - symbolIDX // - ); - - // - // Check rading Not Paused ... - result = - !hasSymbolInfo || - mSymbolInfos[symbolIDX].IsEnable(); - if (!result) - { - return result; - } - - // - bool isLong = IsLong(signal.type); - - // - // Chekc Signalling Enable or not ... - result = - isLong - ? mAllowLong - : mAllowShort; - if (!result) - { - return result; - } - - // - // Check Signal is Support or not ... - bool isSupport = IsSupport(signal.comment); - result = !isSupport; - if (!result) - { - return result; - } - - // - ENUM_X_POSITION_TYPES pType = ToPositionType(signal.type); - double requiredProfitForAcceptNext = AcceptNextSameTypeSignalWhenLastInProfit(); - - // - // Implement Same Signal Conditions ... - XPosition smaeSymbolPositions[]; - int sameSymbolPositionsCount = mTrader.GetPositions( - smaeSymbolPositions, - signal.symbol, - signal.provider, - signal.period, - pType, - true, // Filter By Magic ... - true // Force Clean ... - ); - XPosition youngestSame; - int youngestSameAge = GetYoungest( - youngestSame, - smaeSymbolPositions // - ); - - // - double youngestSameProfitInPoint = youngestSame.GetProfitInPoint(); - - // - result = - sameSymbolPositionsCount == 0 || - (sameSymbolPositionsCount <= 0 - ? true - : requiredProfitForAcceptNext <= 0 - ? true - : youngestSameAge >= 0 && - youngestSameProfitInPoint >= requiredProfitForAcceptNext); - - // - return result; - } - - /** - * Execute Specific Signal using Trade Handler ... - */ - bool ExecuteSignal( - XSignal &signal, // Signal for Execution - ENUM_X_SIGNAL_EXECUTION_RESULT &state, // Execution State - bool ignorePolicies = false, // Ignore Execution Policies - // - // Force Protections ... - bool forceTrail = false // Force Trail Position - ) - { - // - bool result = false; - - // - // Check Signal Validation ... - result = signal.IsValid(); - if (!result) - { - return result; - } - - // - // Check Policies ... - if (!ignorePolicies) - { - // - // Filter Signals if Necessary ... - result = CanExecute(signal); - if (!result) - { - // - state = X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS; - return result; - } - - // - bool isLong = IsLong(signal.type); - - // - // Check Allow Trade Type ... - result = - isLong - ? mAllowLong - : mAllowShort; - if (!result) - { - // - state = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; - return result; - } - - // - XPosition longs[]; - XPosition shorts[]; - - // - // Counting Positions ... - if (mUseMaxAllowedTradesPerSymbol) - { - // - mTrader.GetPositions( - longs, - shorts, - signal.symbol // - ); - } - else - { - // - mTrader.GetPositions( - longs, - shorts, - NULL // All Symbols ... - ); - } - - // - int longsCount = ArraySize(longs); - int shortsCount = ArraySize(shorts); - - // - // Check Trades Count ... - if (mMaxAllowedLongs > 0 || mMaxAllowedShorts > 0) - { - // - result = - // - // Long ... - isLong - ? mMaxAllowedLongs <= 0 - ? true - : longsCount < mMaxAllowedLongs - // - // Short ... - : mMaxAllowedShorts <= 0 - ? true - : shortsCount < mMaxAllowedShorts - // - ; - if (!result) - { - // - state = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; - return result; - } - } - - // - // Check Position Delays ... - if (result && mDelayBarBetweenTwoSignal > 0) - { - // - int youngestAge = 0; - XPosition youngestPosition; - - // - // Long Positions when there are Longs ... - if (isLong && longsCount > 0) - { - // - youngestAge = GetYoungest( - youngestPosition, - longs // - ); - } - // - // Short Positions when there are Shorts ... - else if (!isLong && shortsCount > 0) - { - // - youngestAge = GetYoungest( - youngestPosition, - shorts // - ); - } - - // - // Only Check when there is must to check and conditions happens ... - if (youngestAge > 0 && youngestPosition.IsValid()) - { - // - result = youngestAge >= mDelayBarBetweenTwoSignal; - if (!result) - { - // - state = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; - return result; - } - } - - // - if (!youngestPosition.IsValid()) - { - // - int symbolIDX = FindLastExecutedSignalItem(signal); - if (IsValidIndex(symbolIDX)) - { - // - datetime cTime = TimeCurrent(); - int signalPeriodSeconds = PeriodSeconds(signal.period); - datetime lastExecutedTime = mLastExecutedSignals[symbolIDX].time; - datetime passedTime = ((datetime)lastExecutedTime + - ((mDelayBarBetweenTwoSignal * signalPeriodSeconds))); - - // - result = cTime >= passedTime; - if (!result) - { - return result; - } - } - } - } - - // - // Check Drawdown ... - if (mMaxDrawdownPercentForOpenTrades > 0) - { - // - drawdownPercent = GetMaxDrawdown(); - - // - result = - drawdownPercent <= 0 - ? true - : drawdownPercent < mMaxDrawdownPercentForOpenTrades; - if (!result) - { - // - state = X_SIGNAL_EXECUTION_FAILED_NO_EQUITY; - return result; - } - } - } - - // - // Add Additional Volume to Signal ... - signal.volume += mAdditionalVolume; - - // - // Execute Signal ... - result = mTrader.ExecuteSignal( - signal, - state // - ); - if (result) - { - // - double commission = mTrader.GetPositionCommission(signal.positionId); - - // - // Add Signal to Trade Handler ... - AddData( - signal, - commission, - forceTrail // - ); - - // - HandleSignalExecuted(signal); - - // - string msg = (signal.type == POSITION_TYPE_BUY ? "Long" : "Short") + - " Signal Provided by: " + signal.provider + - (signal.pushers > 1 ? " Pushers: " + ToString(signal.pushers) : "") + - " on: " + signal.symbol + - " in: " + ToString(signal.period) + - " Executed Successfully ..."; - Alert(msg); - } - - // - return result; - } - - // - // Protection Functions ... - - /** - * Handle Positiona Protections - */ - void HandleProtection() - { - // - // Retrieve Positions ... - X121SMCProtectedPosition pPositions[]; - int pPositionsCount = GetPositions( - pPositions // - ); - - // - // Validate Count ... - if (!IsValidSize(pPositionsCount)) - { - return; - } - - // - bool isHedged = HandleHedge(pPositions); - if (isHedged) - { - // - // Renew Data ... - Clean(pPositions); - int pPositionsCount = GetPositions( - pPositions // - ); - - // - // Validate Count ... - if (!IsValidSize(pPositionsCount)) - { - return; - } - - // - return; - } - - // - int protectedPositions = 0; - for (int i = 0; i < pPositionsCount; i++) - { - // - // Check Position is Protectable or not ... - X121SMCProtectedPosition iProtected = pPositions[i]; - XPosition iPosition = iProtected.main; - - // - bool isProtected = HandlePositionProtecting( - iPosition, - iProtected.supports, - pPositions // - ); - if (isProtected) - { - protectedPositions++; - } - } - - // - if (protectedPositions > 0) - { - // - // Renew Data ... - Clean(pPositions); - int pPositionsCount = GetPositions( - pPositions // - ); - - // - // Validate Count ... - if (!IsValidSize(pPositionsCount)) - { - return; - } - } - } - - /** - * Reset All Paused Symbols ... - */ - void ResumePausedSymbols() - { - // - int count = ArraySize(mSymbolInfos); - if (!IsValidSize(count)) - { - return; - } - - // - for (int i = 0; i < count; i++) - { - // - mSymbolInfos[i].Reset(); - } - - // - string message = "Force Resume Paused Symbols ..."; - Alert(message); - } - - // - // Protected ... - protected: - // - XCTrade *mTrader; // Instance of Trader Class - X121SMCTradeCollector *mCollector; // Instance of Trade Collector Class - - // - X121SMCTradeData mData[]; // Hold Trade Data - - // - // Hedge Related Functions ... - - /** - * Handle Hedging On Positions ... - */ - bool HandleHedge(X121SMCProtectedPosition &positions[]) - { - // - bool result = false; - - // - // Check Hedging is Enabled Or Not ... - result = AllowHedge(); - if (!result) - { - return result; - } - - // - // Check Minimum Volume Step is Provided or not ... - double minVolumeStep = HedgeMinVolumeStep(); - result = minVolumeStep > 0; - if (!result) - { - return result; - } - - // - // Check Positions ... - int positionsCount = ArraySize(positions); - result = IsValidSize(positionsCount); - if (!result) - { - return result; - } - - // - // Calculate Required Info ... - double swaps = 0; // Summary of Positions Swaps ... - double profits = 0; // Summary of Positions and Supports Profits ... - double volumes = 0; // Summary of Positions and Supports Volumes ... - int supportsCount = 0; // Number of Protecting Positions ... - double commissions = 0; // Summary of Positions and Supports Commissions ... - XPosition flatPositions[]; // Flat Positions ... - for (int i = 0; i < positionsCount; i++) - { - // - X121SMCProtectedPosition iProtected = positions[i]; - - // - XPosition iPositions[]; - int iPositionsCount = iProtected.ExtractPositions(iPositions); - if (IsValidSize(iPositionsCount)) - { - // - Copy( - iPositions, - flatPositions, - false // - ); - } - - // - // Collect Main Positions Data ... - swaps += iProtected.main.swap; - profits += iProtected.main.profit; - volumes += iProtected.main.volume; - commissions += mTrader.GetPositionCommission(iProtected.main.ticket); - - // - int iSupportsCount = iProtected.CountSupports(); - supportsCount += iSupportsCount; - - // - if (IsValidSize(iSupportsCount)) - { - // - // Collectiong Supports Positions Data ... - for (int j = 0; j < iSupportsCount; j++) - { - // - XPosition jSupport = iProtected.supports[j]; - - // - swaps += jSupport.swap; - profits += jSupport.profit; - volumes += jSupport.volume; - - // - commissions += mTrader.GetPositionCommission(jSupport.ticket); - } - } - } - - // - // First Step is Handle HE Hedge ... - - // - int minOpenPositions = MinimumOpenPositionsForHEHedge(); - double heMinProfitPerVolumeStep = HedgeHEMinProfitPerVolumeStep(); - double beMinProfitPerVolumeStep = HedgeBEMinProfitPerVolumeStep(); - - // - // Check HE Hedge Conditions ... - bool allowHEHedge = minOpenPositions > 0 && heMinProfitPerVolumeStep > 0; - if (allowHEHedge) - { - // - // Implement HE Hedge ... - - // - // Check Main Positions Count and also not Support Positions ... - result = supportsCount == 0 && - positionsCount >= minOpenPositions; - if (result) - { - // - // Check Profits ... - result = profits > 0; - if (result) - { - // - // Calculate Required Profit ... - double volumeSteps = volumes / minVolumeStep; - double minRequiredProfit = (volumeSteps * heMinProfitPerVolumeStep) + - commissions + (-1 * swaps); - - // - // Check Profits Satisfied Required Profit's For Hedge or not ... - result = profits >= minRequiredProfit; - if (result) - { - // - int flatPositionsCount = ArraySize(flatPositions); - result = IsValidSize(flatPositionsCount); - if (result) - { - // - string comment = "EQM HE Hedge ..."; - int closed = mTrader.Close( - flatPositions, - comment // - ); - - // - result = closed > 0; - if (result) - { - // - string message = "EQM HE Hedge Close (" + ToString(flatPositionsCount) + ") Positions by: " + ToString(profits); - Alert(message); - - // - return result; - } - } - } - } - } - } - - // - // Check BE Hedge Conditions ... - bool allowBEHedge = positionsCount >= 1 && - supportsCount >= 1 && - beMinProfitPerVolumeStep > 0; - if (allowBEHedge) - { - // - // Implement BE Hedge ... - - // - // Check Profits ... - result = profits > 0; - if (result) - { - // - // Calculate Required Profit ... - double volumeSteps = volumes / minVolumeStep; - double minRequiredProfit = (volumeSteps * beMinProfitPerVolumeStep) + - commissions + (-1 * swaps); - - // - // Check Profits Satisfied Required Profit's For Hedge or not ... - result = profits >= minRequiredProfit; - if (result) - { - // - int flatPositionsCount = ArraySize(flatPositions); - result = IsValidSize(flatPositionsCount); - if (result) - { - // - string comment = "EQM BE Hedge ..."; - int closed = mTrader.Close( - flatPositions, - comment // - ); - - // - result = closed > 0; - if (result) - { - // - string message = "EQM BE Hedge Close (" + ToString(flatPositionsCount) + ") Positions by: " + ToString(profits); - Alert(message); - - // - return result; - } - } - } - } - - // - return result; - } - - // - return result; - } - - /** - * Handle Protecting Position ... - */ - bool HandlePositionProtecting( - XPosition &position, // Main Position - XPosition &supports[], // Supports - X121SMCProtectedPosition &positions[] // All Positions - ) - { - // - bool result = false; - - // - // Find Position's Item Data ... - int iDX = -1; - result = HasItem( - position.ticket, - iDX // - ); - if (!result) - { - return result; - } - - // - int supportsCount = ArraySize(supports); - - // - // Handle Protection Of Protection Signals ... - if (supportsCount > 0) - { - HandleProtectionOfProtectors(supports); - } - - // - // Here we Make Sure this Position has reached Proper distance ... - - // - bool isLong = IsLong(position.type); - bool isInProfit = position.profit > 0; - datetime currentTime = TimeCurrent(); - - // - double profitInPoint = position.GetProfitInPoint(); - double pointValue = position.GetPointsValue(); - - // - // Determines there is a Freezed Position or not ... - bool hasFreezed = false; - int positionsCount = ArraySize(positions); - if (IsValidSize(positionsCount)) - { - // - for (int i = 0; i < positionsCount; i++) - { - // - int iSupportsCount = ArraySize(positions[i].supports); - - // - hasFreezed = iSupportsCount == 1 && - positions[i].main.tp == 0 && - positions[i].main.sl == 0 && - positions[i].supports[0].tp == 0 && - positions[i].supports[0].sl == 0 && - positions[i].main.volume == positions[i].supports[0].volume; - if (hasFreezed) - { - break; - } - } - } - - // - // Reading Requirements for Trailling Stops ... - bool allowTrail = AllowTrail() || mData[iDX].forceTrail; - double trailStep = TrailStep(); - double trailStartDistance = TrailStartDistance(); - bool allowOnlyUnprotecteds = OnlyTrailUnprotected(); - int removeTPAfterTrailedLevel = RemoveTPAfterTrailedLevel(); - bool disableTrailWhenFreezedPosition = false; // DisableTrailWhenFreezedPosition(); - bool canTrail = isInProfit && - allowTrail && - trailStep > 0 && - profitInPoint > 0 && - trailStartDistance > 0 && - (!allowOnlyUnprotecteds - ? true - : supportsCount <= 0) && - profitInPoint >= trailStartDistance && - (!disableTrailWhenFreezedPosition - ? true - : !hasFreezed); - - // - // Reading Requirements for Partial Close ... - // In Profit ... - double partialCloseInProfitDistance = PartialCloseInProfitDistance(); - double partialCloseInProfitVolume = PartialCloseInProfitVolume(); - bool canPartialCloseInProfit = isInProfit && - profitInPoint > 0 && - !mData[iDX].partiallyClosed && - partialCloseInProfitVolume > 0 && - profitInPoint >= partialCloseInProfitDistance; - - // - // In Drawdown ... - double partialCloseInDrawdownDistance = PartialCloseInProfitDistance(); - double partialCloseInDrawdownVolume = PartialCloseInProfitVolume(); - bool canPartialCloseInDrawdown = !isInProfit && - profitInPoint < 0 && - !mData[iDX].partiallyClosed && - partialCloseInDrawdownVolume > 0 && - MathAbs(profitInPoint) >= partialCloseInDrawdownDistance; - - // - double partialCloseVolume = canPartialCloseInProfit - ? partialCloseInProfitVolume - : canPartialCloseInDrawdown - ? partialCloseInDrawdownVolume - : 0; - - // - bool canPartialClose = partialCloseVolume > 0 && - (canPartialCloseInProfit || - canPartialCloseInDrawdown); - - // - // Reading Requirement for Freezing Positions ... - - // - // Protect ... - bool allowProtect = AllowProtect(); - int protectionDelay = ProtectionDelay(); - bool protectOnConditions = ProtectOnConditions(); - int maxAllowedProtection = MaxAllowedProtection(); - bool useEntryAsProtectionSL = UseEntryAsProtectionSL(); - double protectDistance = ProtectionStartDistance(); - bool allowDirectionProtect = AllowDirectionProtct(); - double protectVolumeMultiplier = ProtectionVolumeMultiplier(); - bool canProtect = - !isInProfit && - allowProtect && - protectDistance > 0 && - protectionDelay >= 0 && - protectVolumeMultiplier >= 1 && - (maxAllowedProtection <= 0 - ? true - : supportsCount < maxAllowedProtection) && - MathAbs(profitInPoint) >= MathAbs(protectDistance); - - // - result = - canTrail || - canProtect || - canPartialClose; - if (!result) - { - return result; - } - - // - int zIndex = 0; - int cIndex = zIndex + 1; - int pIndex = cIndex + 1; - int ppIndex = pIndex + 1; - - // - // Last Bar ... - XOHCL cBar; - result = cBar.Init( - position.symbol, - position.period, - cIndex // - ); - if (!result) - { - return result; - } - - // - // Previous Bar of Last Bar ... - XOHCL pBar; - result = cBar.GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - // Last Swing Low Bar ... - XOHCL lastSwingLow; - result = cBar.FindLastSwingLow(lastSwingLow); - if (!result) - { - return result; - } - - // - // Last Swing High Bar ... - XOHCL lastSwingHigh; - result = cBar.FindLastSwingHigh(lastSwingHigh); - if (!result) - { - return result; - } - - // - // Common Conditions For Bullish and Bearish Powers ... - - // - // Detect Bullish/Bearish Patterns and Trends ... - - // - // Bullish ... - bool hasBullishPower = cBar.HasBullishPower(); - bool hasBullishPattern = mBarAnalyser.HasBullishPattern(cBar); - bool hasBullishPressure = cBar.HasBullishPressure(); - bool hasBullishTrend = mBarAnalyser.HasBullishTrend(cBar, true); - - // - // Bearish ... - bool hasBearishPower = cBar.HasBearishPower(); - bool hasBearishPattern = mBarAnalyser.HasBearishPattern(cBar); - bool hasBearishPressure = cBar.HasBearishPressure(); - bool hasBearishTrend = mBarAnalyser.HasBearishTrend(cBar, true); - - // - // Define Conditions ... - MqlTick ticks[]; - int ticksCount = CopyTicks( - position.symbol, - ticks, - COPY_TICKS_ALL, - 0, - 5 // - ); - - // - bool isTicksBullishForLong = - // - GetTickEntry(ticks[0], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[1], POSITION_TYPE_BUY, position.symbol) && - GetTickEntry(ticks[1], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[2], POSITION_TYPE_BUY, position.symbol) && - GetTickEntry(ticks[2], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[3], POSITION_TYPE_BUY, position.symbol) - // - ; - - // - bool isTicksBearishForLong = - // - GetTickEntry(ticks[0], POSITION_TYPE_BUY, position.symbol) < GetTickEntry(ticks[1], POSITION_TYPE_BUY, position.symbol) && - GetTickEntry(ticks[1], POSITION_TYPE_BUY, position.symbol) < GetTickEntry(ticks[2], POSITION_TYPE_BUY, position.symbol) && - GetTickEntry(ticks[2], POSITION_TYPE_BUY, position.symbol) < GetTickEntry(ticks[3], POSITION_TYPE_BUY, position.symbol) - // - ; - - // - bool isTicksBullishForShort = - // - GetTickEntry(ticks[0], POSITION_TYPE_SELL, position.symbol) > GetTickEntry(ticks[1], POSITION_TYPE_SELL, position.symbol) && - GetTickEntry(ticks[1], POSITION_TYPE_SELL, position.symbol) > GetTickEntry(ticks[2], POSITION_TYPE_SELL, position.symbol) && - GetTickEntry(ticks[2], POSITION_TYPE_SELL, position.symbol) > GetTickEntry(ticks[3], POSITION_TYPE_SELL, position.symbol) - // - ; - - // - bool isTicksBearishForShort = - // - GetTickEntry(ticks[0], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[1], POSITION_TYPE_SELL, position.symbol) && - GetTickEntry(ticks[1], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[2], POSITION_TYPE_SELL, position.symbol) && - GetTickEntry(ticks[2], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[3], POSITION_TYPE_SELL, position.symbol) - // - ; - - // - // News Momentum Change ... - - // - double hh5 = cBar.FindHighest( - 5, - MODE_HIGH // - ); - - // - double ll5 = cBar.FindLowest( - 5, - MODE_LOW // - ); - - // - bool isForecBullishMomentum = false; - bool isForceBearishMomentum = false; - bool useForceMomentum = UseForceMomentumsInProtection(); - if (ticksCount == 5 && useForceMomentum) - { - // - isForecBullishMomentum = - // - GetTickEntry(ticks[0], POSITION_TYPE_BUY, position.symbol) >= hh5 - // - && - // - ( - // - GetTickEntry(ticks[0], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[1], POSITION_TYPE_BUY, position.symbol) && - GetTickEntry(ticks[1], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[2], POSITION_TYPE_BUY, position.symbol) && - GetTickEntry(ticks[2], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[3], POSITION_TYPE_BUY, position.symbol) && - GetTickEntry(ticks[3], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[4], POSITION_TYPE_BUY, position.symbol) - // - ) - // - ; - - // - isForceBearishMomentum = - // - GetTickEntry(ticks[0], POSITION_TYPE_SELL, position.symbol) <= ll5 - // - && - // - ( - // - GetTickEntry(ticks[0], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[1], POSITION_TYPE_SELL, position.symbol) && - GetTickEntry(ticks[1], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[2], POSITION_TYPE_SELL, position.symbol) && - GetTickEntry(ticks[2], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[3], POSITION_TYPE_SELL, position.symbol) && - GetTickEntry(ticks[3], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[4], POSITION_TYPE_SELL, position.symbol) - // - ) - // - ; - } - - // - bool hasBullishDecision = - // - cBar.IsBullishDecision() - // - ; - - // - bool hasBearishDecision = - // - cBar.IsBearishDecision() - // - ; - - // - bool hasBullishConditions = - // - ( - // - hasBullishTrend && - hasBullishDecision && - (hasBullishPower || - hasBullishPattern || - hasBullishPressure) - // - ) - // - ; - - // - bool hasBearishConditions = - // - ( - // - hasBearishTrend && - hasBearishDecision && - (hasBearishPower || - hasBearishPattern || - hasBearishPressure) - // - ) - // - ; - - // - // Do Trail ... - bool isTrailed = false; - if (canTrail) - { - // - bool hasTrailConditions = - isLong - ? (isForecBullishMomentum || - (isTicksBullishForLong && - hasBullishConditions)) - : (isForceBearishMomentum || - (isTicksBearishForShort && - hasBearishConditions)); - if (hasTrailConditions) - { - // - double entry = position.entry; - int lastTrailedStep = mData[iDX].trailStep; - - // - double requiredProfit = - lastTrailedStep == 0 - ? trailStartDistance - : trailStartDistance + (lastTrailedStep * trailStep); - - // - bool isProfitsPassed = profitInPoint > requiredProfit; - if (isProfitsPassed) - { - // - double delta = (requiredProfit * pointValue); - - // - double sl = - isLong - ? entry + delta - : entry - delta; - - // - string comment = "EQM Trail Stop ..."; - - // - bool canRemoveTP = - position.tp != 0 && - removeTPAfterTrailedLevel > 0 && - mData[iDX].trailStep == removeTPAfterTrailedLevel; - double tp = - canRemoveTP - ? 0 - : position.tp; - - // - // Try to Modify Position ... - isTrailed = mTrader.Modify( - position.ticket, - sl, - tp, - comment // - ); - if (isTrailed) - { - // - mData[iDX].trailStep++; - - // - string message = "EQM Trail (" + ToString(position.ticket) + ") Stop in Level: " + ToString(mData[iDX].trailStep) + " ..."; - Alert(message); - } - } - } - // - // Force Trail When passed half way ... - else - { - // - // Handle Force Trail ... - double requiredProfit = position.GetRewardInPoint(); - if (position.sl > 0 && - position.sl < position.entry && - profitInPoint >= requiredProfit) - { - // - double delta = requiredProfit - (requiredProfit / 3); - double sl = - isLong - ? position.entry + (delta * pointValue) - : position.entry - (delta * pointValue); - - // - string comment = "EQM Force Trail Stop ..."; - - // - // Try to Modify Position ... - isTrailed = mTrader.Modify( - position.ticket, - sl, - position.tp, - comment // - ); - if (isTrailed) - { - // - mData[iDX].trailStep++; - - // - string message = "EQM Force Trail (" + ToString(position.ticket) + ") Stop ..."; - Alert(message); - } - } - } - } - - // - // Do Partial Close ... - bool isPartialClosed = false; - if (canPartialClose) - { - // - string comment = "EQM Partial Close ..."; - - // - // Do Partial Closing ... - isPartialClosed = mTrader.ClosePartial( - position.ticket, - partialCloseVolume, - comment // - ); - if (isPartialClosed) - { - // - mData[iDX].partiallyClosed = true; - - // - string message = "EQM Partially Closed " + ToString(partialCloseVolume) + " of (" + ToString(position.ticket) + ") ..."; - Alert(message); - } - } - - // - // Protect ... - bool isProtected = false; - if (canProtect) - { - // - // Protection Conditions ... - bool hasLongProtectConditions = isForecBullishMomentum || - (isTicksBullishForLong && - hasBullishConditions); - bool hasShortProtectConditions = isForceBearishMomentum || - (isTicksBearishForShort && - hasBearishConditions); - - // - // Check Protection Delay ... - datetime currentTime = TimeCurrent(); - datetime lastProtectedOn = mData[iDX].lastProtectedOn; - bool isProtectionDelayPassed = - protectionDelay <= 0 - ? true - : !IsValid(lastProtectedOn) - ? true - : (TimeToSeconds(currentTime) - TimeToSeconds(lastProtectedOn)) > (ulong)protectionDelay; - - // - // Checking Protection Conditions ... - bool hasProtectConditions = - isProtectionDelayPassed && - (!protectOnConditions - ? true - : allowDirectionProtect - ? (hasLongProtectConditions || - hasShortProtectConditions) - : isLong - ? hasShortProtectConditions - : hasLongProtectConditions); - - // - // Check Protection Conditions Happens ... - if (hasProtectConditions) - { - // - bool isInDirectProtection = - !protectOnConditions - ? true - : isLong - ? hasShortProtectConditions - : hasLongProtectConditions; - - // - double sl = - !isInDirectProtection - ? position.sl - : useEntryAsProtectionSL - ? position.entry - : position.tp; - double tp = - !isInDirectProtection - ? position.tp - : position.sl; - double volume = protectVolumeMultiplier * position.volume; - ENUM_POSITION_TYPE type = - !isInDirectProtection - ? position.type - : GetOpposit(position.type); - double entry = GetEntry( - position.symbol, - type // - ); - ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET; - - // - // Prepare Signal ... - XSignal signal; - bool isPrepared = signal.Prepare( - position.symbol, - position.provider, - position.period, - type, - mode, - entry, - volume, - sl, - tp // - ); - - // - if (isPrepared) - { - // - // Generate Comment for Recover and Support ... - string comment = GenerateSupportTag(position.ticket); - - // - signal.comment = comment; - - // - ENUM_X_SIGNAL_EXECUTION_RESULT state; - isProtected = ExecuteSignal( - signal, - state, - true // Support Signal need to Ignore Policies ... - ); - if (isProtected) - { - // - // Update Last Protected On Data Handler ... - mData[iDX].lastProtectedOn = currentTime; - - // - // Alert ... - string message = "EQM Open " + (IsLong(type) ? "Long" : "Short") + " Protect Position for (" + ToString(position.ticket) + ") ..."; - Alert(message); - } - } - } - } - - // - result = - isTrailed || - isProtected || - isPartialClosed; - - // - return result; - } - - /** - * Handle Protection of Support(s) ... - * - * @param supports: Supports Array ... - */ - void HandleProtectionOfProtectors(XPosition &supports[]) - { - // - int supportsCount = ArraySize(supports); - - // - if (!IsValidSize(supportsCount)) - { - return; - } - - // - // TODO: Implement Supports Protection ... - - // - // Trailling ... - } - /** * Pause Specified Symbol Trading ... * @@ -3810,18 +2481,635 @@ class XC121SMCTradeHandler : public XCBaseAlert // } + /** + * Reset Specified Symbol Info ... + * + * @param symbol: String ... + */ + void ResetSymbolInfo(string symbol) + { + // + if (!IsValid(symbol)) + { + return; + } + + // + int symbolIDX = -1; + bool hasSymbol = HasSymbol( + symbol, + symbolIDX // + ); + if (!hasSymbol) + { + return; + } + + // + mSymbolInfos[symbolIDX].Reset(); + + // + string message = "Reset " + symbol + ", Pause State ..."; + Alert(message); + } + + /** + * Reset All Paused Symbols ... + */ + void ResumePausedSymbols() + { + // + int count = ArraySize(mSymbolInfos); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + mSymbolInfos[i].Reset(); + } + + // + string message = "Force Resume Paused Symbols ..."; + Alert(message); + } + + // + // Signal Execution Actions ... + + /** + * Validate Signal For Execution ... + * + * @param signal: XSignal instance Reference ... + * @param state: ENUM_X_SIGNAL_EXECUTION_RESULT Reference for olding Signal Execution Result Reason ... + * + * @return ( bool ) + */ + bool CanExecute( + XSignal &signal, + ENUM_X_SIGNAL_EXECUTION_RESULT &state // Execution State + ) + { + // + bool result = false; + + // + state = X_SIGNAL_EXECUTION_UNKNOWN; + + // + // Validate Signal ... + result = signal.IsValid(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS; + return result; + } + + // + int symbolIDX = -1; + bool hasSymbolInfo = HasSymbol( + signal.symbol, + symbolIDX // + ); + + // + // Check rading Not Paused ... + result = + !hasSymbolInfo || + mSymbolInfos[symbolIDX].IsEnable(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + return result; + } + + // + bool isLong = IsLong(signal.type); + + // + // Chekc Signalling Enable or not ... + result = + isLong + ? mAllowLong + : mAllowShort; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + return result; + } + + // + // Check Signal is Support or not ... + bool isSupport = IsSupport(signal.comment); + result = !isSupport; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + return result; + } + + // + ENUM_X_POSITION_TYPES pType = ToPositionType(signal.type); + double requiredProfitForAcceptNext = AcceptNextSameTypeSignalWhenLastInProfit(); + + // + // Implement Same Signal Conditions ... + XPosition smaeSymbolPositions[]; + int sameSymbolPositionsCount = mTrader.GetPositions( + smaeSymbolPositions, + signal.symbol, + signal.provider, + signal.period, + pType, + true, // Filter By Magic ... + true // Force Clean ... + ); + XPosition youngestSame; + int youngestSameAge = GetYoungest( + youngestSame, + smaeSymbolPositions // + ); + + // + double youngestSameProfitInPoint = youngestSame.GetProfitInPoint(); + + // + result = + sameSymbolPositionsCount == 0 || + (sameSymbolPositionsCount <= 0 + ? true + : requiredProfitForAcceptNext <= 0 + ? true + : youngestSameAge >= 0 && + youngestSameProfitInPoint >= requiredProfitForAcceptNext); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR; + return result; + } + + // + // Retrieve Longs and Shorts ... + XPosition longs[]; + XPosition shorts[]; + bool useMaxAllowedPositionsPerSymbol = UseMaxAllowedTradesPerSymbol(); + + // + // Retrieve Positions ... + if (useMaxAllowedPositionsPerSymbol) + { + // + mTrader.GetPositions( + longs, + shorts, + signal.symbol // + ); + } + else + { + // + mTrader.GetPositions( + longs, + shorts, + NULL // All Symbols ... + ); + } + + // + // Counting ... + int longsCount = ArraySize(longs); + int shortsCount = ArraySize(shorts); + + // + int maxAllowedLongs = MaxAllowedLongs(); + int maxAllowedShorts = MaxAllowedShorts(); + + // + // Check Max Allowed Positions ... + if (maxAllowedLongs > 0 || + maxAllowedShorts > 0) + { + // + if (isLong && maxAllowedLongs > 0 && longsCount > 0) + { + result = longsCount < maxAllowedLongs; + } + else if (!isLong && maxAllowedShorts > 0 && shortsCount > 0) + { + result = shortsCount < maxAllowedShorts; + } + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + return result; + } + } + + // + // Check Delays Bar if Provided ... + int delaysBarBetweenTwoSignal = DelayBarBetweenTwoSignal(); + if (delaysBarBetweenTwoSignal > 0) + { + // + // Try To Detect Youngest Position ... + int youngestAge = 0; + XPosition youngestPosition; + + // + // Long Positions when there are Longs ... + if (isLong && longsCount > 0) + { + // + youngestAge = GetYoungest( + youngestPosition, + longs // + ); + } + // + // Short Positions when there are Shorts ... + else if (!isLong && shortsCount > 0) + { + // + youngestAge = GetYoungest( + youngestPosition, + shorts // + ); + } + + // + // Check Delays When Youngest Position Exists ... + if (youngestAge > 0 && youngestPosition.IsValid()) + { + // + result = youngestAge >= delaysBarBetweenTwoSignal; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED; + return result; + } + } + + // + // Check Delays When Youngest Position is not Exists ... + if (!youngestPosition.IsValid()) + { + // + // Try to Detect Last Issued Signal in Model Collections ... + int symbolIDX = FindLastExecutedSignalItem(signal); + if (IsValidIndex(symbolIDX)) + { + // + // Calculate Requirements ... + datetime cTime = TimeCurrent(); + int signalPeriodSeconds = PeriodSeconds(signal.period); + datetime lastExecutedTime = mLastExecutedSignals[symbolIDX].time; + datetime passedTime = ((datetime)lastExecutedTime + + ((delaysBarBetweenTwoSignal * signalPeriodSeconds))); + + // + // Check Conditions ... + result = cTime >= passedTime; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED; + return result; + } + } + } + } + + // + // Check Max Drawdown Percent for Open Trades ... + double maxAllowedDrawdownPercent = MaxDrawdownPercentForOpenTrades(); + if (maxAllowedDrawdownPercent > 0) + { + // + // Calculate and Update Drawdown Percent ... + double cdPercent = CalculateMaxDrawdownPercent(); + + // + result = cdPercent < maxAllowedDrawdownPercent; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NO_EQUITY; + return result; + } + } + + // + return result; + } + + /** + * Execute Specific Signal using Trade Handler ... + * + * @param signal: XSignal instance Reference ... + * @param state: ENUM_X_SIGNAL_EXECUTION_RESULT Reference for olding Signal Execution Result Reason ... + * @param ignorePolicies: Boolean ... + * + * @return ( bool ) + */ + bool ExecuteSignal( + XSignal &signal, // Signal for Execution + ENUM_X_SIGNAL_EXECUTION_RESULT &state, // Execution State + bool ignorePolicies = false // Ignore Execution Policies + ) + { + // + bool result = false; + + // + // Check Signal Validation ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + // Check Policies ... + if (!ignorePolicies) + { + // + // Filter Signals if Necessary ... + result = CanExecute( + signal, + state // + ); + if (!result) + { + return result; + } + } + + // + // Apply Additional Volume to Signal if Provided ... + double additionalVolume = AdditionalVolume(); + if (additionalVolume > 0) + { + signal.volume += mAdditionalVolume; + } + + // + // Execute Signal ... + result = mTrader.ExecuteSignal( + signal, + state // + ); + if (result) + { + // + // Add XTradeHandler Data ... + Add(signal); + + // + // Handle Last Executed Signal ... + HandleSignalExecuted(signal); + + // + // Alert Executed Signal ... + string msg = (signal.type == POSITION_TYPE_BUY ? "Long" : "Short") + + " Signal Provided by: " + signal.provider + + (signal.pushers > 1 ? " Pushers: " + ToString(signal.pushers) : "") + + " on: " + signal.symbol + + " in: " + ToString(signal.period) + + " Executed Successfully ..."; + Alert(msg); + } + + // + if (!result) + { + + // + // Alert Signal Execution Failed ... + string msg = "Failed To Execute " + + (signal.type == POSITION_TYPE_BUY ? "Long" : "Short") + + " Signal Provided by: " + signal.provider + + (signal.pushers > 1 ? " Pushers: " + ToString(signal.pushers) : "") + + " on: " + signal.symbol + + " in: " + ToString(signal.period) + + " due Reason: " + ToString(state) + " ..."; + Alert(msg); + } + + // + return result; + } + + // + // Timing Actions ... + + /** + * Update Currently Open Positions Info on Data Collection ... + */ + void UpdateData() + { + // + // Retrieve Positions ... + XPosition positions[]; + int count = mTrader.GetPositions(positions); + if (!IsValidSize(count)) + { + return; + } + + // + // Loop Through Positions ... + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = positions[i]; + + // + // Check Position Registered as Data or not ... + int idx = -1; + bool isExists = HasItem( + iPosition.ticket, + idx // + ); + if (isExists) + { + // + // Update Position Data ... + mData[idx].Update(iPosition); + } + } + } + + /** + * Handle Positiona Protections + */ + void HandleProtection() + { + // + // Implement Protection Senario Here ... + int count = Count(); + if (!IsValidSize(count)) + { + // + currentDrawdown = 0; + return; + } + + // + // Calculate Max Same Time Trades ... + maxSameTimeTrades = + maxSameTimeTrades == 0 || + maxSameTimeTrades < count + ? count + : maxSameTimeTrades; + + // + double profitSummary = 0; + + // + for (int i = 0; i < count; i++) + { + // + X121SMCTradeData iData = mData[i]; + + // + // Profit Sum ... + profitSummary += iData.profit; + + // + XPosition iPosition; + bool hasPosition = mTrader.GetPosition( + iData.ticket, + iPosition // + ); + if (!hasPosition) + { + continue; + } + + // + // Calculate Break Even Point ... + double entry = iPosition.entry; + double points = iData.Points(); + double volume = iPosition.volume; + bool isLong = IsLong(iData.Type()); + double spread = GetSpread(iData.GetSymbol()); + double bep = iData.CalculateBreakEvenPoint(); + double exitPrice = GetExit( + iPosition.symbol, + iPosition.type // + ); + + // + double tps[]; + double reachedTPLevel = -1; + double reachedTPPrice = 0; + int tpLevelsCount = iPosition.CalculateTPLevels(tps); + iPosition.CalculateReahedTP( + reachedTPLevel, + reachedTPPrice // + ); + + // + // All Protections Done for InProfit Positions ... + if (iData.profit > 0) + { + // + // Check Break Even ... + bool canRFOnBEP = iData.CanRiskFreeOnBreakEvenPoint(); + if (canRFOnBEP && reachedTPLevel > 0) + { + // + double tpLevel = iData.TPLevelForBreakEven(); + int tpIDX = (int)tpLevel - 1; + double rfTPPrice = tps[tpIDX]; + bool isSLReady = isLong + ? iPosition.sl < rfTPPrice + : iPosition.sl > rfTPPrice; + if (isSLReady && tpLevel == reachedTPLevel - 1) + { + // + double sl = rfTPPrice; + double tp = iPosition.tp; + string comment = "RF on BEP ..."; + bool isModified = mTrader.Modify( + iData.ticket, + sl, + tp, + comment // + ); + if (isModified) + { + // + string message = ToString(iData.Type()) + + " Position: " + + ToString(iData.ticket) + + " RF On BEP Successfully ..."; + Alert(message); + } + } + } + } + } + + // + // Calculate Max Draw Down ... + maxDrawdown = + profitSummary < 0 && + (maxDrawdown == 0 || + maxDrawdown < profitSummary) + ? profitSummary + : maxDrawdown; + + // + // Calculate Current Drawdown ... + currentDrawdown = + profitSummary < 0 + ? profitSummary + : 0; + + // + // TODO: Here Implement Collection Based Protections ... + + // + Print("Protection"); + } + + // + // Protected ... + protected: + // + XCTrade *mTrader; // Instance of Trader Class + X121SMCTradeCollector *mCollector; // Instance of Trade Collector Class + + // + X121SMCTradeData mData[]; // Hold Trade Data + X121SMCSymbolPositionInfo mSymbolInfos[]; // Symbol Positions Info + XSymbolLastPosition mLastExecutedSignals[]; // Last Executed Signals + + // + // Hedge Related Functions ... + // // Private ... private: // // Props ... - double mAdditionalVolume; // Volume Additional - XSymbolLastPosition mLastExecutedSignals[]; // Last Executed Signals // // Read Only ... - int maxSameTimeTrades; // Max Same Time Trades + int maxSameTimeTrades; // Holds Max Same Time Trades double maxDrawdown; // Max Drawdown + double currentDrawdown; // Current Drawdown double drawdownPercent; // Drawdown Percent double staticBalanceForCalculateDrawdown; // Static Balance for Max Drawdown Calculation @@ -3831,124 +3119,29 @@ class XC121SMCTradeHandler : public XCBaseAlert bool mSaveConditions; // Save SL Conditions // - bool mAllowLong; // Allow Long/Buy Trade Type - bool mAllowShort; // Allow Short/Sell Trade Type - int mMaxAllowedLongs; // Max Allowe Long/Buy Trades - int mMaxAllowedShorts; // Max Allowe Short/Sell Trades - bool mUseMaxAllowedTradesPerSymbol; // Use Max Allowed Trades Per Symbol - double mMaxDrawdownPercentForOpenTrades; // Max Drawdown Percent for Open Trades - - // - // Protector ... - - // + bool mAllowLong; // Allow Long/Buy Trade Type + bool mAllowShort; // Allow Short/Sell Trade Type + int mMaxAllowedLongs; // Max Allowe Long/Buy Trades + int mMaxAllowedShorts; // Max Allowe Short/Sell Trades + double mAdditionalVolume; // Volume Additional int mDelayBarBetweenTwoSignal; // Delay Bars Between Two Signal - int mMaxAllowedSLToPause; // Max Allowed SL Per Symbol - int mMaxAllowedSLReachedPauseDelay; // Pause Symbol Trading After Mx Allowed SL Reached - bool mUseForceMomentumsInProtection; // Use Force Momentums In Protection + bool mUseMaxAllowedTradesPerSymbol; // Use Max Allowed Trades Per Symbol + double mMaxDrawdownPercentForOpenTrades; // Max Drawdown Percent for Open Trades double mAcceptNextSameTypeSignalWhenLastInProfit; // Accept Next Same Type Signal When Last in Profit in Point // - // In Profit Positions Protecting ... - - // - // Trail ... - bool mAllowTrail; // Allow Trail Stop for Positions - double mTrailStartDistance; // Specify Trail Start in Point - double mTrailStep; // Trail Step in Point - int mRemoveTPAfterTrailedLevel; // Remove Trailed Position TP after Level - bool mOnlyTrailUnprotected; // Only Trail Unprotected Positionss - - // - // Partial Close (In Profit) ... - double mPartialCloseInProfitDistance; // Specify Partial Close Profit in Point - double mPartialCloseInProfitVolume; // Specify Partial Close in Profit Volume - - // - // In Drawdown Positions Protecting ... - - // - // Protect ... - bool mAllowProtect; // Allow Proptecting - double mProtectionStartDistance; // Protection Start Drawdown in Profit - double mProtectionVolumeMultiplier; // Protection Volume Multiplier - int mMaxAllowedProtection; // Max Allowed Protection - bool mUseEntryAsProtectionSL; // Use Position Entry For SL of Protect - bool mAllowDirectionProtct; // Allow also Directional Protect - bool mProtectOnConditions; // Do Protection only when Conditions happens - int mProtectionDelay; // Delay Between two Protection in Secconds - - // - // Partial Close (In Drawdown) ... - double mPartialCloseInDrawdownDistance; // Specify Partial Close Drawdown in Point - double mPartialCloseInDrawdownVolume; // Specify Partial Close in Drawdown Volume + int mMaxAllowedSLToPause; // Max Allowed SL Per Symbol + int mMaxAllowedSLReachedPauseDelay; // Pause Symbol Trading After Max Allowed SL Reached // // Hedging Properties ... - bool mAllowHedge; // Allow Protector to Hedge Positions - double mHedgeMinVolumeStep; // Minimum Volume Step For Hedge - int mMinimumOpenPositionsForHEHedge; // Minimum Open Positions For HE Hedge - double mHedgeHEMinProfitPerVolumeStep; // Minimum Required Profit For HE Hedge Per Volume Step - double mHedgeBEMinProfitPerVolumeStep; // Minimum Required Profit For BE Hedge Per Volume Step + bool mAllowHedge; // Allow Protector to Hedge Positions + double mHedgeMinVolumeStep; // Minimum Volume Step For Hedge + int mMinimumOpenPositionsForHedge; // Minimum Open Positions For Hedge + double mHedgeMinProfitPerVolumeStep; // Minimum Required Profit For Hedge Per Volume Step // XCBarAnalyser mBarAnalyser; - X121SMCSymbolPositionInfo mSymbolInfos[]; - - /** - * Find Specific Symbo Indo Item index ... - * - * @param symbol: String ... - * @param index: Integer ... - * - * @return ( bool ) - */ - bool HasSymbol( - string symbol, - int &index // - ) - { - // - bool result = false; - - // - index = -1; - - // - result = IsValid(symbol); - if (!result) - { - return result; - } - - // - int count = ArraySize(mSymbolInfos); - result = IsValidSize(count); - if (!result) - { - return result; - } - - // - for (int i = 0; i < count; i++) - { - // - bool isOwn = mSymbolInfos[i] - .IsOwn(symbol); - if (isOwn) - { - // - index = i; - break; - } - } - - // - result = IsValidIndex(index); - - // - return result; - } // // Common Functions ... @@ -3988,10 +3181,10 @@ class XC121SMCTradeHandler : public XCBaseAlert { // result = !HasItem( - item.symbol, - item.provider, - item.period, - item.type, + item.GetSymbol(), + item.Provider(), + item.GetPeriod(), + item.XType(), index // ); } @@ -4050,6 +3243,50 @@ class XC121SMCTradeHandler : public XCBaseAlert return result; } + // + bool HasItem( + XSignal &signal, + int &index // + ) + { + // + bool result = + // + signal.IsValid() && + HasItem(signal.symbol, + signal.provider, + signal.period, + ToPositionType(signal.type), + index) + // + ; + + // + return result; + } + + // + bool HasItem( + XPosition &position, + int &index // + ) + { + // + bool result = + // + position.IsValid() && + HasItem(position.symbol, + position.provider, + position.period, + ToPositionType(position.type), + index) + // + ; + + // + return result; + } + // // Find Item Index ... bool HasItem( @@ -4112,6 +3349,61 @@ class XC121SMCTradeHandler : public XCBaseAlert return result; } + /** + * Find Specific Symbo Indo Item index ... + * + * @param symbol: String ... + * @param index: Integer ... + * + * @return ( bool ) + */ + bool HasSymbol( + string symbol, + int &index // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = IsValid(symbol); + if (!result) + { + return result; + } + + // + int count = ArraySize(mSymbolInfos); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isOwn = mSymbolInfos[i] + .IsOwn(symbol); + if (isOwn) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + // void Save(int index) { @@ -4159,6 +3451,7 @@ class XC121SMCTradeHandler : public XCBaseAlert } // + // Find Last Signal Execution ... int FindLastExecutedSignalItem(XSignal &signal) { // @@ -4196,6 +3489,7 @@ class XC121SMCTradeHandler : public XCBaseAlert } // + // Handle Last Signal Execution ... void HandleSignalExecuted(XSignal &signal) { // @@ -4231,6 +3525,41 @@ class XC121SMCTradeHandler : public XCBaseAlert } // + double CalculateMaxDrawdownPercent() + { + // + double result = 0; + + // + double mEquity = mTrader.mAccount.GetEquity(); + if (mEquity > currentDrawdown) + { + currentDrawdown = mEquity; + } + + // + if (currentDrawdown >= 0) + { + // + drawdownPercent = 0; + return result; + } + + // + drawdownPercent = (currentDrawdown - mEquity) / + (staticBalanceForCalculateDrawdown > 0 + ? staticBalanceForCalculateDrawdown + : currentDrawdown) * + 100; + drawdownPercent = NormalizeDouble(drawdownPercent, 3); + result = drawdownPercent; + + // + return result; + } + + // + // End of XC121SMCTradeHandler Class ... }; // \ No newline at end of file diff --git a/X121SMCEA/Experts/x-121.smc.expert.class.mq5 b/X121SMCEA/Experts/x-121.smc.expert.class.mq5 index b27dc41f..3364142f 100644 --- a/X121SMCEA/Experts/x-121.smc.expert.class.mq5 +++ b/X121SMCEA/Experts/x-121.smc.expert.class.mq5 @@ -47,6 +47,11 @@ class XC121SMCExpert : public XCBaseExpert TOnModify OnPositionModifiedEventListener; TOnForceClose OnPositionForceCloseEventListener; + // + TOnDealsChanged OnDealsChangedEventListener; + TOnOrdersChanged OnOrdersChangedEventListener; + TOnPositionsChanged OnPositionsChangedEventListener; + // TOnX121SMCSignal OnSignalEventListener; @@ -293,7 +298,7 @@ class XC121SMCExpert : public XCBaseExpert if (isFiltered) { // - mTradeHandler.RemoveSignal(signal); + mTradeHandler.Remove(signal); return; } @@ -313,34 +318,14 @@ class XC121SMCExpert : public XCBaseExpert // datetime currentTime = TimeCurrent(); - // - // Check Signal Protections ... - bool canTrail = false; - ENUM_X_121_SMC_PROVIDERS signalProvider = ParseProvider(signal.provider); - if (IsValid(signalProvider)) - { - // - // Complete this in Force States ... - // canTrail = true; - } - // // Execute Signal Using Trade Handler ... ENUM_X_SIGNAL_EXECUTION_RESULT state; bool isExecuted = mTradeHandler.ExecuteSignal( signal, state, - false, // ignore Policies ... - // - // Force Protections ... - canTrail // + false // ignore Policies ... ); - - // - if (isExecuted) - { - mLastSignalOn = currentTime; - } } // @@ -541,7 +526,10 @@ class XC121SMCExpert : public XCBaseExpert ); mTrader.AddOnStopLossEventHandler(OnPositionSLEventListener); mTrader.AddOnTakeProfitEventHandler(OnPositionTPEventListener); + mTrader.AddOnDealsChangedEventHandler(OnDealsChangedEventListener); + mTrader.AddOnOrdersChangedEventHandler(OnOrdersChangedEventListener); mTrader.AddOnModifyPositionEventHandler(OnPositionModifiedEventListener); + mTrader.AddOnPositionsChangedEventHandler(OnPositionsChangedEventListener); mTrader.AddOnForceClosePositionEventHandler(OnPositionForceCloseEventListener); mTrader.AddOnPartialClosePositionEventHandler(OnPositionPartialCloseEventListener); @@ -578,51 +566,12 @@ class XC121SMCExpert : public XCBaseExpert // // Configure Position Protector ... - // - mTradeHandler.UseForceMomentumsInProtection(true); - // // Configure Hedging ... mTradeHandler.AllowHedge(false); mTradeHandler.HedgeMinVolumeStep(0.01); - mTradeHandler.MinimumOpenPositionsForHEHedge(2); - mTradeHandler.HedgeHEMinProfitPerVolumeStep(0.2); - mTradeHandler.HedgeBEMinProfitPerVolumeStep(0.06); - - // - // In Profit Position Protecting ... - - // - // Trail ... - mTradeHandler.AllowTrail(false); - mTradeHandler.TrailStep(15); - mTradeHandler.TrailStartDistance(30); - mTradeHandler.OnlyTrailUnprotected(true); - mTradeHandler.RemoveTPAfterTrailedLevel(3); - - // - // Partial Close (In Profit) ... - mTradeHandler.PartialCloseInProfitDistance(0); - mTradeHandler.PartialCloseInProfitVolume(0); - - // - // In Drawdown Positions Protecting ... - - // - // Protect ... - mTradeHandler.AllowProtect(false); - mTradeHandler.ProtectionDelay(20); - mTradeHandler.MaxAllowedProtection(0); - mTradeHandler.UseEntryAsProtectionSL(true); - mTradeHandler.ProtectOnConditions(true); - mTradeHandler.AllowDirectionProtct(false); - mTradeHandler.ProtectionStartDistance(50); - mTradeHandler.ProtectionVolumeMultiplier(2); - - // - // Partial Close (In Profit) ... - mTradeHandler.PartialCloseInDrawdownDistance(0); - mTradeHandler.PartialCloseInDrawdownVolume(0); + mTradeHandler.MinimumOpenPositionsForHedge(2); + mTradeHandler.HedgeMinProfitPerVolumeStep(0.2); // // Parsers ... @@ -743,7 +692,11 @@ class XC121SMCExpert : public XCBaseExpert void HandleStrategiesOnTick() override { // - // Calling Protection Handler of TradeHandler ... + // Update Positions Data ... + mTradeHandler.UpdateData(); + + // + // Protect Positions ... mTradeHandler.HandleProtection(); // @@ -765,6 +718,38 @@ class XC121SMCExpert : public XCBaseExpert // // Event Handlers ... + /** + * Calls When a Deals Changed Triggered ... + * + * @param count: Integer, Number of Changes ... + */ + void HandleOnDealsChanged(int count) override + { + } + + /** + * Calls When a Order Changed Triggered ... + * + * @param count: Integer, Number of Changes ... + */ + void HandleOnOrdersChanged(int count) override + { + } + + /** + * Calls When a Positions Changed Triggered ... + * + * @param count: Integer, Number of Changes ... + */ + void HandleOnPositionsChanged(int count) override + { + // + if (IsValidSize(count)) + { + mTradeHandler.HandleNewPosition(); + } + } + /** * Calls When a Position's SL Triggered ... * @@ -871,9 +856,6 @@ class XC121SMCExpert : public XCBaseExpert // // Props ... - // - datetime mLastSignalOn; - // XC121SMCTradeHandler *mTradeHandler; // Trade Handler ... XCX121SMCBaseStrategy *mStrategies[]; // Registere Strategies in EA ... @@ -963,9 +945,6 @@ class XC121SMCExpert : public XCBaseExpert { signal.volume = Volume(); } - - // - mTradeHandler.UpdateSignal(signal); } /** diff --git a/X121SMCEA/Libraries/x-121.smc.lib.mq5 b/X121SMCEA/Libraries/x-121.smc.lib.mq5 index 4e2bc4b7..ba3cedac 100644 --- a/X121SMCEA/Libraries/x-121.smc.lib.mq5 +++ b/X121SMCEA/Libraries/x-121.smc.lib.mq5 @@ -2006,112 +2006,4 @@ ENUM_X_121_SMC_PROVIDERS ParseProvider(string value) return result; } -// -// Custom Providers Conditions ... -struct XSMCStrategySetupConditions -{ - // - // Props ... - - // - string symbol; - ENUM_TIMEFRAMES period; - - // - double sl; - ENUM_X_DIRECTION dir; - ENUM_X_POSITION_TYPES type; - - // - // Setup Props ... - - // - datetime setupTime; - datetime triggerTime; - - // - // Trigger Props ... - - // - // Constructor ... - XSMCStrategySetupConditions() - { - Clean(); - } - - // - // Tools ... - - /** - * Cleaning Up ... - */ - void Clean() - { - // - sl = 0; - - // - dir = X_DIRECTION_NONE; - type = X_POSITION_TYPE_NONE; - - // - symbol = NULL; - period = NULL; - setupTime = NULL; - triggerTime = NULL; - } - - /** - * Check Condition is Setting Up ... - * - * @param dir: ENUM_X_DIRECTION member, Setting Up Direction ... - * - * @return ( bool ) - */ - bool IsSetuped() - { - // - bool result = false; - - // - result = IsValid(setupTime) && - HasDirection(dir); - if (!result) - { - return result; - } - - // - return result; - } - - /** - * Detect How we Can Trigger Signal ... - * - * @return ( bool ) - */ - bool CanTrigger() - { - // - bool result = false; - - // - result = - // - sl > 0 && - IsValid(symbol) && - IsValid(period) && - IsValid(triggerTime) && - type != X_POSITION_TYPE_ALL && - type != X_POSITION_TYPE_NONE - // - ; - - // - return result; - } - - // -}; - // \ No newline at end of file diff --git a/X121SMCEA/Signals/x-121.smc.test.signal.class.mq5 b/X121SMCEA/Signals/x-121.smc.test.signal.class.mq5 index e2c06d94..ab47b9ae 100644 --- a/X121SMCEA/Signals/x-121.smc.test.signal.class.mq5 +++ b/X121SMCEA/Signals/x-121.smc.test.signal.class.mq5 @@ -1591,9 +1591,10 @@ bool DetectX121SMCTestSiganlTrigger( // // !isTriggerMarketBearish && // !isDecisionMarketBearish && - !isAnalyseMarketBearish && + // !isAnalyseMarketBearish && + isTriggerMarketBullish && !isVerificationMarketBearish && - !isConsolidationMarketBearish + !isConsolidationMarketBearish // ; @@ -1602,9 +1603,10 @@ bool DetectX121SMCTestSiganlTrigger( // // !isTriggerMarketBullish && // !isDecisionMarketBullish && - !isAnalyseMarketBullish && + // !isAnalyseMarketBullish && + isTriggerMarketBearish && !isVerificationMarketBullish && - !isConsolidationMarketBullish + !isConsolidationMarketBullish // ; @@ -1616,7 +1618,7 @@ bool DetectX121SMCTestSiganlTrigger( // isSameVale && lookupLong && isValesInsideFVG && - isMarketReadyForLong && + // isMarketReadyForLong && isSarSwitchedToBullish && triggerVale <= iFVG.Upper() && triggerVale >= iFVG.Lower(); @@ -1626,7 +1628,7 @@ bool DetectX121SMCTestSiganlTrigger( // isSamePeak && lookupShort && isPeaksInsideFVG && - isMarketReadyForShort && + // isMarketReadyForShort && isSarSwitchedToBearish && triggerPeak <= iFVG.Upper() && triggerPeak >= iFVG.Lower(); diff --git a/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 b/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 index 48f616ff..d519aecd 100644 --- a/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 +++ b/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 @@ -277,6 +277,26 @@ class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy signal.provider = provider; signal.time = TimeCurrent(); + // + if (hasTestSignal) + { + // + // Add Aditionsal Info ... + + // + signal.fullTPLevel = r2r; + signal.partialCloseOnTPLevel = 2; + signal.partialCloseMultiplier = 0.5; + + // + signal.riskFreeOnBreakEven = true; + signal.tpLevelForBreakEven = 1; + + // + signal.trailSL = true; + signal.trailSLStartOnReachTPLevel = 3; + } + // result = PrepareSignal(signal); if (result) @@ -487,23 +507,6 @@ class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy } conditions.visionConditions.state = mVisionState; - // // - // XPVPivot triggerPivot; - // mTriggerCycleHelper.GetActivePivot(triggerPivot); - // result = triggerPivot.IsValid(); - // if (!result) - // { - // return result; - // } - - // // - // ClearDraws(); - // DrawPivot( - // triggerPivot, - // true, // Draw State ... - // true // Filter By Price ... - // ); - // return result; }