From 9c6cd61f2b934b051bdbc9b28b72b321308f9962 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Sun, 19 May 2024 01:55:13 +0330 Subject: [PATCH] refactor some typos on helper classes and implement base classes for providers and start x5 provider ... --- Classes/x-saherelm.provider.class.mq5 | 0 Classes/x-saherelm.x5.provider.class.mq5 | 396 +++ Classes/x-saherelm.xaccount.class.mq5 | 398 +++ Classes/x-saherelm.xprovider.class.mq5 | 264 ++ Classes/x-saherelm.xtrade.class.mq5 | 3501 ++++++++++++++++++++++ Helpers/x-saherelm.xama.helper.mq5 | 14 +- Helpers/x-saherelm.xcc.helper.mq5 | 14 +- Helpers/x-saherelm.xchlh.helper.mq5 | 14 +- Helpers/x-saherelm.xchma.helper.mq5 | 14 +- Helpers/x-saherelm.xct.helper.mq5 | 14 +- Helpers/x-saherelm.xdon.helper.mq5 | 2 +- Helpers/x-saherelm.xfi.helper.mq5 | 14 +- Helpers/x-saherelm.xhk.helper.mq5 | 2 +- Helpers/x-saherelm.xhull.helper.mq5 | 22 +- Helpers/x-saherelm.xlh.helper.mq5 | 14 +- Helpers/x-saherelm.xmrb.helper.mq5 | 2 +- Helpers/x-saherelm.xobd.helper.mq5 | 14 +- Helpers/x-saherelm.xosc.helper.mq5 | 4 +- Helpers/x-saherelm.xpv.helper.mq5 | 14 +- Helpers/x-saherelm.xrsi.helper.mq5 | 14 +- Helpers/x-saherelm.xsslc.helper.mq5 | 2 +- Helpers/x-saherelm.xstr.helper.mq5 | 20 +- Helpers/x-saherelm.xtd.helper.mq5 | 14 +- Helpers/x-saherelm.xtm.helper.mq5 | 14 +- Helpers/x-saherelm.xts.helper.mq5 | 2 +- Helpers/x-saherelm.xzg.helper.mq5 | 2 +- Indicators/x-saherelm.xct.mq5 | 64 +- Libraries/x-saherelm.common.lib.mq5 | 79 + Libraries/x-saherelm.xtrade.lib.mq5 | 979 +++++- 29 files changed, 5672 insertions(+), 235 deletions(-) delete mode 100644 Classes/x-saherelm.provider.class.mq5 create mode 100644 Classes/x-saherelm.x5.provider.class.mq5 create mode 100644 Classes/x-saherelm.xaccount.class.mq5 create mode 100644 Classes/x-saherelm.xprovider.class.mq5 create mode 100644 Classes/x-saherelm.xtrade.class.mq5 diff --git a/Classes/x-saherelm.provider.class.mq5 b/Classes/x-saherelm.provider.class.mq5 deleted file mode 100644 index e69de29b..00000000 diff --git a/Classes/x-saherelm.x5.provider.class.mq5 b/Classes/x-saherelm.x5.provider.class.mq5 new file mode 100644 index 00000000..0c314c68 --- /dev/null +++ b/Classes/x-saherelm.x5.provider.class.mq5 @@ -0,0 +1,396 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCBaseX5Provider +// Description: provides all Base Provider +// requirements For X5 ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... + +// +#include "../Helpers/x-saherelm.xct.helper.mq5" +#include "../Helpers/x-saherelm.xcc.helper.mq5" +#include "../Helpers/x-saherelm.xtm.helper.mq5" +#include "../Helpers/x-saherelm.xama.helper.mq5" +#include "../Helpers/x-saherelm.xlh.helper.mq5" +#include "../Helpers/x-saherelm.xtd.helper.mq5" +#include "../Helpers/x-saherelm.xfi.helper.mq5" +#include "../Helpers/x-saherelm.xts.helper.mq5" +#include "../Helpers/x-saherelm.xrsi.helper.mq5" +#include "../Helpers/x-saherelm.xobd.helper.mq5" +#include "../Helpers/x-saherelm.xchlh.helper.mq5" +#include "../Helpers/x-saherelm.xchma.helper.mq5" + +// +#include "../Classes/x-saherelm.xprovider.class.mq5" + +// +// Definitions ... + +// +enum ENUM_X5_SIGNAL_PROVIDERS +{ + // + // XSP Expert Support Mechanism ... + XSP, + // + // XTD ... + XTD, + // + // XTAM ... + XTAM, + // + // XSI ... + XSI, + // + // XTSFI ... + XTSFI, + // + // XOBDLH ... + XOBDLH, + // + // XCHMACC ... + XCHMACC, + // + // XCHMACMN ... + XCHMAMN, + // + // XCHMACMX ... + XCHMAMX, +}; + +// +// X5 Provider Inputs ... +class X5ProviderInputs : public XSCBaseProviderInpts +{ + // + // Public ... +public: + // + // Props ... + XTMInputs tmInputs; + XLHInputs lhInputs; + XTDInputs tdInputs; + XFIInputs fiInputs; + XCTInputs ctInputs; + XCCInputs ccInputs; + XOBDInputs obdInputs; + XAMAInputs amaInputs; + XRSIInputs rsiInputs; + XCHLHInputs chlhInputs; + XCHMAInputs chmaInputs; + + // + // Tools ... + + // + // Validate ... + virtual bool IsValid() + { + // + bool result = false; + + // + result = ctInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = ccInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = tmInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = lhInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = tdInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = fiInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = obdInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = amaInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = rsiInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = chlhInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = chmaInputs.IsValid(); + + // + return result; + } + + // + // Cleanup ... + virtual void Clean() + { + // + ctInputs.Clean(); + ccInputs.Clean(); + tmInputs.Clean(); + lhInputs.Clean(); + tdInputs.Clean(); + fiInputs.Clean(); + obdInputs.Clean(); + amaInputs.Clean(); + rsiInputs.Clean(); + chlhInputs.Clean(); + chmaInputs.Clean(); + } + + // + // Default ... + virtual void Default() + { + // + ctInputs.Default(); + ccInputs.Default(); + tmInputs.Default(); + lhInputs.Default(); + tdInputs.Default(); + fiInputs.Default(); + obdInputs.Default(); + amaInputs.Default(); + rsiInputs.Default(); + chlhInputs.Default(); + chmaInputs.Default(); + } + + // + // Max ... + virtual int Max() + { + // + int result = 0; + + // + result = MathMax(lhInputs.Max(), tmInputs.Max()); + + // + result = MathMax(result, ctInputs.Max()); + result = MathMax(result, ccInputs.Max()); + result = MathMax(result, tdInputs.Max()); + result = MathMax(result, fiInputs.Max()); + result = MathMax(result, obdInputs.Max()); + result = MathMax(result, amaInputs.Max()); + result = MathMax(result, rsiInputs.Max()); + result = MathMax(result, chlhInputs.Max()); + result = MathMax(result, chmaInputs.Max()); + + // + return result; + } +}; + +// +// X5 Provider Market Conditions ... +class X5MarketConditions : public XSCBaseProviderMarketConditions +{ + + // + // Buffers ... + + // + // Conditions ... + + // + // Generate Score ... + virtual void GenerateScore( + double &bullishScore, // Bullish Score + double &bearishScore, // Bearish Score + const double multiplier = 1 // Score Multiplier + ) + { + } + + // + // Generate Summary ... + virtual string GenerateSummary( + const double multiplier = 1, // Score Multiplier + const bool ignoreFalseConditions = true // Ignore False Conditions + ) + { + // + string result = NULL; + + // + return result; + } +}; + +// +// Class ... + +// +// X5 Provider Class ... +class XSC5Provider : public XSCBaseProvider +{ + // + // Public ... +public: + // + // Props ... + XSCXTSHelper *tsHelper; + XSCXFIHelper *fiHelper; + XSCXTDHelper *tdHelper; + XSCXLHHelper *lhHelper; + XSCXTMHelper *tmHelper; + XSCXOBDHelper *obdHelper; + XSCXRSIHelper *rsiHelper; + XSCXAMAHelper *amaHelper; + XSCXCHMAHelper *chmaHelper; + XSCXCHLHHelper *chlhHelper; + + // + // Constructor ... + XSC5Provider( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading PEriod + ) : XSCBaseProvider(symbol, period) + { + // + } + + // + // Properties Gettr(s) / Setter(s) ... + + // + // Inheritance ... + + // + // Init all Requirements ... + virtual bool Init(X5ProviderInputs &inputs) + { + // + bool result = false; + + // + // Validate ... + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + return result; + } + + // + // DeInit all Requirements ... + virtual void DeInit() + { + } + + // + // Functions ... + + // + virtual bool GetMarketConditions( + X5MarketConditions &conditions, // Market Conditions Result + int barIndex = 0 // Specified Bar Index + ) + { + // + bool result = false; + + // + return result; + } + + // + // Check Market For Signal ... + virtual bool HasSignal( + int barIndex, + XSignal &signal, // Hold's Signal if Exists ... + X5MarketConditions &conditions // Hold's Market Conditions ... + ) + { + // + bool result = false; + + // + return result; + } + + // + // Protected ... +protected: + // + // X5MarketConditions mInputs; + + // + // Private ... +private: + // + // Props ... + + // + // Tools ... +}; diff --git a/Classes/x-saherelm.xaccount.class.mq5 b/Classes/x-saherelm.xaccount.class.mq5 new file mode 100644 index 00000000..66169f54 --- /dev/null +++ b/Classes/x-saherelm.xaccount.class.mq5 @@ -0,0 +1,398 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCAccount +// Description: provides all Account requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include +#include "../Classes/x-saherelm.base.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Manage Account ... +class XSCAccount : public XSCBase +{ + // + // Public ... +public: + // + // Constructor ... + void XSCAccount() + { + // + mAccountInfo = new CAccountInfo(); + } + + // + // Deconstructor ... + void ~XSCAccount() + { + } + + // + // START Provided Functions ... + // + + // + // User Account ... + long GetUserAccount() + { + return mAccountInfo.Login(); + } + + // + // Account Leverage ... + long GetLeverage() + { + return mAccountInfo.Leverage(); + } + + // + // Get Trade Expert State ... + bool CanExpertTrade() + { + return mAccountInfo.TradeExpert(); + } + + // + // User Account Trade Mopde (ENUM_ACCOUNT_TRADE_MODE) ... + // -------------------------- + // ACCOUNT_TRADE_MODE_DEMO + // ACCOUNT_TRADE_MODE_CONTEST + // ACCOUNT_TRADE_MODE_REAL + ENUM_ACCOUNT_TRADE_MODE GetTradeMode() + { + return mAccountInfo.TradeMode(); + } + + // + // Get Account Balance ... + double GetBalance() + { + return mAccountInfo.Balance(); + } + + // + // Get the amount of give Credit ... + double GetCredit() + { + return mAccountInfo.Credit(); + } + + // + // Get the amount of current Profit on account ... + double GetProfit() + { + return mAccountInfo.Profit(); + } + + // + // Get the amount of current Equity on account ... + double GetEquity() + { + return mAccountInfo.Equity(); + } + + // + // Get the amount of reserved Margin ... + double GetMargin() + { + return mAccountInfo.Margin(); + } + + // + // Get the amount of free Margin ... + double GetFreeMargin() + { + return mAccountInfo.FreeMargin(); + } + + // + // Get the Level of Margin ... + double GetMarginLevel() + { + return mAccountInfo.MarginLevel(); + } + + // + // Get the Level Of Margin for a Deposit ... + double GetMarginCall() + { + return mAccountInfo.MarginCall(); + } + + // + // Get the Level of Margin for Stop out ... + double GetMarginStopOut() + { + return mAccountInfo.MarginStopOut(); + } + + // + // Get the Client Name ... + string GetName() + { + return mAccountInfo.Name(); + } + + // + // Get the Trade Server Name ... + string GetServerName() + { + return mAccountInfo.Server(); + } + + // + // Get deposit Currency Name ... + string GetCurrency() + { + return mAccountInfo.Currency(); + } + + // + // Get the Company Name that serves an Account ... + string GetCompany() + { + return mAccountInfo.Company(); + } + + // + // Calculate Profits for the current account based on passed parameters ... + double CalculateTradeProfit( + const string symbol, // trading symbol + ENUM_ORDER_TYPE type, // order type + double volume, // volume + double entry, // open price + double exit // close price + ) + { + // + double result = mAccountInfo.OrderProfitCheck( + symbol, + type, + volume, + entry, + exit); + + // + return result; + } + + // + // Calculate amount of margin which required for trade operation ... + double CalculateMarging( + const string symbol, // trading symbol + ENUM_ORDER_TYPE type, // order type + double volume, // volume + double entry // open price + ) + { + // + double result = mAccountInfo.MarginCheck( + symbol, + type, + volume, + entry); + + // + return result; + } + + // + // Calculate amount of free margin left after trade operation ... + double CalculateFreeMarging( + const string symbol, // trading symbol + ENUM_ORDER_TYPE type, // order type + double volume, // volume + double entry // open price + ) + { + // + double result = mAccountInfo.FreeMarginCheck( + symbol, + type, + volume, + entry); + + // + return result; + } + + // + // Calculate the Maximum possible volume of trade operation ... + double CalculateMaxVolume( + const string symbol, // trading symbol + ENUM_ORDER_TYPE type, // order type + double entry, // open price + double percent = 100 // percent of available margin + ) + { + // + double result = mAccountInfo.MaxLotCheck( + symbol, + type, + entry, + percent); + + // + return result; + } + + // + // Calculate Point Value for Given Symbol based on Account ... + double GetPointValue( + string symbol // trading symbol + ) + { + // + double result = 0; + + // + double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE); + double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE); + double point = SymbolInfoDouble(symbol, SYMBOL_POINT); + + // + double ticksPerPoint = tickSize / point; + + // + result = tickValue / ticksPerPoint; + + // + return result; + } + + // + // Calculate Risk Amount based on account Currency by Providing: + // Points and Volume ... + double CalculateRiskAmount( + string symbol, // trading symbol + double points, // amount of Risk Points + double volume // position Volume + ) + { + // + double result = 0; + + // + double pointValue = GetPointValue(symbol); + + // + result = pointValue * volume * points; + + // + return result; + } + + // + // Calculate Risk Points based on account Currency by Providing: + // Volume and Amount ... + double CalculateRiskPoints( + string symbol, // trading symbol + double volume, // position Volume + double amount // amount of Risk based on Account Currency + ) + { + // + double result = 0; + + // + double pointValue = GetPointValue(symbol); + + // + result = amount / (pointValue * volume); + + // + return result; + } + + // + // Calculate Volume based on account Currency by Providing: + // Amount and Risk Points ... + double CalculateVolume( + string symbol, // trading symbol + double amount, // amount of Risk based on Account Currency + double points // amount of Risk Points + ) + { + // + double result = 0; + + // + points = + points <= 0 + ? 10 + : points; + + // + double pointValue = GetPointValue(symbol); + + // + result = amount / (pointValue * points); + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Account Info ... + CAccountInfo mAccountInfo; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/Classes/x-saherelm.xprovider.class.mq5 b/Classes/x-saherelm.xprovider.class.mq5 new file mode 100644 index 00000000..4753dead --- /dev/null +++ b/Classes/x-saherelm.xprovider.class.mq5 @@ -0,0 +1,264 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCBaseProvider +// Description: provides all Base Provider +// requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Includes ... +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Libraries/x-saherelm.xtrade.lib.mq5" + +// +// Definitions ... + +// +// Base Provider Inputs ... +class XSCBaseProviderInpts : public XSCBase +{ + // + // Public ... +public: + // + // Validate Input ... + virtual bool IsValid(); + + // + // Cleanup ... + virtual void Clean(); + + // + // Default ... + virtual void Default(); + + // + // Max ... + virtual int Max(); +}; + +// +// Base Market Conditions Class ... +class XSCBaseProviderMarketConditions : public XSCBase +{ + // + // Public ... +public: + // + // Props ... + XOHCL bars[]; // Number of Bars ... + + // + // Buffers ... + + // + // Conditions ... + + // + // Generate Score ... + virtual void GenerateScore( + double &bullishScore, // Bullish Score + double &bearishScore, // Bearish Score + const double multiplier = 1 // Score Multiplier + ); + + // + // Generate Summary ... + virtual string GenerateSummary( + const double multiplier = 1, // Score Multiplier + const bool ignoreFalseConditions = true // Ignore False Conditions + ); +}; + +// +// Class ... + +// +// Base Provider Class ... +class XSCBaseProvider : public XSCBase +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor ... + XSCBaseProvider( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading Period + ) + { + // + // Initialize Cycle ... + mCycle.Init( + symbol, + period, + X_MARKET_CYCLE_UNKNOWN, + X_PERIOD_NOTHING, + period, + "HOST Period" + // + ); + } + + // + // Deconstructor ... + ~XSCBaseProvider() + { + DeInit(); + } + + // + // Properties Gettr(s) / Setter(s) ... + + // + // Inheritance ... + + // + // Init all Requirements ... + virtual bool Init(XSCBaseProviderInpts &inputs) + { + // + mInputs = inputs; + + // + bool result = false; + + // + return result; + } + + // + // Get Inputs ... + virtual void GetInputs(XSCBaseProviderInpts &inputs) + { + inputs = mInputs; + } + + // + // Set Inputs and Reinitial ... + virtual bool setInputs(XSCBaseProviderInpts &inputs) + { + return Init(inputs); + } + + // + // DeInit all Requirements ... + virtual void DeInit(); + + // + virtual bool GetMarketConditions( + XSCBaseProviderMarketConditions &conditions, // Market Conditions Result + int barIndex = 0 // Specified Bar Index + ); + + // + // Check Market For Signal ... + virtual bool HasSignal( + int barIndex, + XSignal &signal, // Hold's Signal if Exists ... + XSCBaseProviderMarketConditions &conditions // Hold's Market Conditions ... + ); + + // + // Functions ... + + // + string GetSymbol() + { + return mCycle.symbol; + } + + // + ENUM_TIMEFRAMES GetPeriod() + { + return mCycle.hostPeriod; + } + + // + // Count Bars ... + int CountBars() + { + // + return mCycle + .CountBars(); + } + + // + // Check New Bar ... + bool IsNewBar() + { + // + return mCycle + .IsNewBar(); + } + + // + // Protected ... +protected: + // + // Props ... + + // + XMarketCycle mCycle; + XSCBaseProviderInpts mInputs; + + // + bool mWaitsUntilNewBar; + + // + // Can Ignore Process ... + bool CanIgnoreProcess() + { + // + bool result = false; + + // + result = + // + IsRunningOnTestMode() + ? !IsNewBar() + : !IsNewBar() && mWaitsUntilNewBar + // + ; + + // + return result; + } + + // + // Toggle Waititng Until New Candle ... + void ToggleWaitingUntilNewBar() + { + mWaitsUntilNewBar = !mWaitsUntilNewBar; + } + + // + // Private ... +private: + // + // Props ... + + // + // Tools ... +}; + +// +// Tools ... diff --git a/Classes/x-saherelm.xtrade.class.mq5 b/Classes/x-saherelm.xtrade.class.mq5 new file mode 100644 index 00000000..79793071 --- /dev/null +++ b/Classes/x-saherelm.xtrade.class.mq5 @@ -0,0 +1,3501 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCTrade +// Description: provides all Trade requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Libraries/x-saherelm.xtrade.lib.mq5" +#include "../Classes/x-saherelm.xaccount.class.mq5" + +// +// Definitions ... + +// +// Overrides ... + +// +// XCTrade Base Class ... +class XSCTradeBase : public CTrade +{ +public: + // + // Modify Specific Position, by Specific Comment ... + bool PositionModify( + const string symbol, // Symbol + const double sl, // Stop Loss + const double tp, // Take Profit + const string comment = "" // Comment For Modify + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!SelectPosition(symbol)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // setting request + m_request.action = TRADE_ACTION_SLTP; + m_request.symbol = symbol; + m_request.magic = m_magic; + m_request.sl = sl; + m_request.tp = tp; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specified Comment ... + if (StringLen(comment) > 0) + { + m_request.comment = comment; + } + + // + // action and return the result + return (OrderSend(m_request, m_result)); + } + bool PositionModify( + const ulong ticket, // Position Ticket + const double sl, // Stop Loss + const double tp, // Take Profit + const string comment = "" // Comment For Modify + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // setting request + m_request.action = TRADE_ACTION_SLTP; + m_request.position = ticket; + m_request.symbol = PositionGetString(POSITION_SYMBOL); + m_request.magic = m_magic; + m_request.sl = sl; + m_request.tp = tp; + + // + // Specified Comment ... + if (StringLen(comment) > 0) + { + m_request.comment = comment; + } + + // + // action and return the result + return (OrderSend(m_request, m_result)); + } + + // + // Close Specific Position, by Specific Comment ... + bool PositionClose( + const string symbol, // Symbol + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + bool partial_close = false; + int retry_count = 10; + uint retcode = TRADE_RETCODE_REJECT; + + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + do + { + // + // check + if (SelectPosition(symbol)) + { + // + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + } + else + { + // + // position not found + m_result.retcode = retcode; + return (false); + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.symbol = symbol; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specify Comment ... + m_request.comment = comment; + + // + // check volume + double max_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX); + if (m_request.volume > max_volume) + { + // + m_request.volume = max_volume; + partial_close = true; + } + else + { + partial_close = false; + } + + // + // hedging? just send order + if (IsHedging()) + { + return (OrderSend(m_request, m_result)); + } + + // + // order send + if (!OrderSend(m_request, m_result)) + { + // + if (--retry_count != 0) + { + continue; + } + + // + if (retcode == TRADE_RETCODE_DONE_PARTIAL) + { + m_result.retcode = retcode; + } + + // + return (false); + } + + // + //--- WARNING. If position volume exceeds the maximum volume allowed for deal, + //--- and when the asynchronous trade mode is on, for safety reasons, position is closed not completely, + //--- but partially. It is decreased by the maximum volume allowed for deal. + if (m_async_mode) + { + break; + } + + // + retcode = TRADE_RETCODE_DONE_PARTIAL; + if (partial_close) + { + Sleep(1000); + } + } while (partial_close); + + // + // succeed + return (true); + } + bool PositionClose( + const ulong ticket, // Position Ticket + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.position = ticket; + m_request.symbol = symbol; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + + // + // Specify Comment ... + m_request.comment = comment; + + // + // close position + return (OrderSend(m_request, m_result)); + } + + // + // Partial Close Specific Position, by Specific Comment ... + bool PositionClosePartial( + const string symbol, // Symbol + const double volume, // Partial Closing Volume + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + uint retcode = TRADE_RETCODE_REJECT; + + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // for hedging mode only + if (!IsHedging()) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if (SelectPosition(symbol)) + { + // + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + } + else + { + // + // position not found + m_result.retcode = retcode; + return (false); + } + + // + // check volume + double position_volume = PositionGetDouble(POSITION_VOLUME); + if (position_volume > volume) + { + position_volume = volume; + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.symbol = symbol; + m_request.volume = position_volume; + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specifieng Comment ... + m_request.comment = comment; + + // + // hedging? just send order + return (OrderSend(m_request, m_result)); + } + bool PositionClosePartial( + const ulong ticket, // Position Ticket + const double volume, // Partial Closing Volume + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // for hedging mode only + if (!IsHedging()) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // check volume + double position_volume = PositionGetDouble(POSITION_VOLUME); + if (position_volume > volume) + { + position_volume = volume; + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.position = ticket; + m_request.symbol = symbol; + m_request.volume = position_volume; + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + + // + // Specifieng Comment ... + m_request.comment = comment; + + // + // close position + return (OrderSend(m_request, m_result)); + } +}; + +// +// Implementation ... + +// a Class For Manage Trades and Handle Trading Actions ... +class XSCTrade : public XSCBase +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + void XSCTrade( + int slippage, // Specify Slippage + ulong magicNumber, // Specify Magic Number + int manageInterval, // Manager Check Intervals Seconds + double maxAllowedSpread, // Max Allowed Spred for Opening Trades + int maxAllowedPositions, // Max Allowed Positions + double maxAllowedDrawdownFactor // Max Allowed Drawdown Factor + ) + { + // + // Setting Props ... + mSlippage = slippage; + mMagicNumber = magicNumber; + + // + mManageInterval = manageInterval; + + // + mMaxAllowedSpread = maxAllowedSpread; + mMaxAllowedPositions = maxAllowedPositions; + mMaxAllowedDrawdownFactor = maxAllowedDrawdownFactor; + + // + mAccount = new XSCAccount(); + + // + // Instance Base Trader Class ... + mTrader = new XSCTradeBase(); + + // + // Configuring Base Trader Class ... + mTrader.SetAsyncMode(false); + mTrader.SetDeviationInPoints(mSlippage); + mTrader.SetExpertMagicNumber(mMagicNumber); + + // + // Setting Log Level ... + mTrader.LogLevel(LOG_LEVEL_ERRORS); + + // + // OnTrade Context ... + + // + mDaysForRead = 1; + mScanStarted = false; + + // + // Reset On Trade Counter ... + ResetOnTradeContext(); + + // + // Init On Trade Context ... + InitOnTradeContext(); + + // + // Sync Position Infos ... + SyncPositionInfos(); + } + + // + // Deconstructor ... + ~XSCTrade() + { + // + // Remove Pointer ... + delete mTrader; + delete mAccount; + } + + // + // Props ... + + // + // Retrieve Slippage ... + int GetSlippage() + { + return mSlippage; + } + + // + // Retrieve Magic Number ... + ulong GetMagicNumber() + { + return mMagicNumber; + } + + // + int GetManageInterval() + { + return mManageInterval; + } + + // + double GetMaxAllowedSpread() + { + return mMaxAllowedSpread; + } + + // + int GetMaxAllowedPositions() + { + return mMaxAllowedPositions; + } + + // + double GetMaxAllowedDrawdownFactor() + { + return mMaxAllowedDrawdownFactor; + } + + // + // Add Event Listeners ... + + // + // Add New Deals Changed Event Handler ... + void AddOnTradeStateChangedEventHandler(TOnTradeStateChanged handler) + { + // + Add( + handler, + mTradeStateChangedEventHandlers + // + ); + } + + // + // Add New Deals Changed Event Handler ... + void AddOnDealsChangedEventHandler(TOnDealsChanged handler) + { + // + Add( + handler, + mDealsChangedEventHandlers + // + ); + } + + // + // Add New Orders Changed Event Handler ... + void AddOnOrdersChangedEventHandler(TOnOrdersChanged handler) + { + // + Add( + handler, + mOrdersChangedEventHandlers + // + ); + } + + // + // Add New Positions Changed Event Handler ... + void AddOnPositionsChangedEventHandler(TOnPositionsChanged handler) + { + // + Add( + handler, + mPositionsChangedEventHandlers + // + ); + } + + // + // Add New Stop Loss Event Handler ... + void AddOnStopLossEventHandler(TOnStopLoss handler) + { + // + Add( + handler, + mStopLossEventHandlers + // + ); + } + + // + // Add New Stop Loss Event Handler ... + void AddOnTakeProfitEventHandler(TOnTakeProfit handler) + { + // + Add( + handler, + mTakeProfitEventHandlers + // + ); + } + + // + // Functions ... + + // + // Handlers ... + + // + // Process On Trade Requirement ... + // this Only Used when we Have to Proccess OnTrade Event in EA(s) ... + void HandleOnTradeEvent( + XOnTradeHandlerState &result // Hold's Result + ) + { + // + result.Clean(); + + // + if (mScanStarted) + { + // + ProcessOnTradeContext(result); + } + else + { + // + // Init Trade Context ... + InitOnTradeContext(); + + // + return; + } + + // + // Here we Can Check the Start ... + bool isValid = + // + result.IsValid() && + // + !result.hasNewDeal && + !result.hasNewOrder && + !result.hasNewPosition && + !result.hasNewHistoryOrder + // + ; + if (!isValid) + { + return; + } + + // + // State ... + + // + // Notfy Trade State Changed Event ... + NotifyTradeStateChangeEvent(result); + + // + // Deals ... + if (result.hasNewDeal) + { + // + // Notfy Deals Changed Event ... + NotifyDealsChangeEvent(result.newDeals); + + // + // Retrieve Last Deal ... + XDeal deals[]; + int dealsCount = GetDeals(deals); + if (dealsCount > 0) + { + // + XDeal lastDeal = deals[0]; + + // + if (lastDeal.reason == DEAL_REASON_TP) + { + NotifyTakeProfitEvent(lastDeal); + } + else if (lastDeal.reason == DEAL_REASON_SL) + { + NotifyStopLossEvent(lastDeal); + } + } + } + + // + // Orders ... + if (result.hasNewOrder || result.hasNewHistoryOrder) + { + // + // Notfy Orders Changed Event ... + NotifyOrdersChangeEvent(result.newOrders + result.newHistoryOrders); + } + + // + // Positions ... + if (result.hasNewPosition) + { + // + // Notfy Positions Changed Event ... + NotifyPositionsChangeEvent(result.newPositions); + } + } + + // + // This Must be Called Every time OnTrade Event Happening ... + // this Used for Implementing Custom Senarios ... + XOnTradeHandlerState HandleOnTrade() + { + // + // Handle OnTrade Event ... + XOnTradeHandlerState state; + HandleOnTradeEvent(state); + if ( + !state.hasNewDeal && + !state.hasNewOrder && + !state.hasNewPosition && + !state.hasNewHistoryOrder) + { + return state; + } + + // + // State ... + + // + // Notfy Trade State Changed Event ... + NotifyTradeStateChangeEvent(state); + + // + // DEALS ... + if (state.hasNewDeal) + { + // + // Notfy Deals Changed Event ... + NotifyDealsChangeEvent(state.newDeals); + + // + // Retrieve Last Deal ... + XDeal deals[]; + GetDeals(deals); + int dealsCount = ArraySize(deals); + if (dealsCount > 0) + { + // + XDeal lastDeal = deals[0]; + + // + if (lastDeal.reason == DEAL_REASON_TP) + { + NotifyTakeProfitEvent(lastDeal); + } + else if (lastDeal.reason == DEAL_REASON_SL) + { + NotifyStopLossEvent(lastDeal); + } + } + } + + // + // ORDERS ... + if (state.hasNewOrder || state.hasNewHistoryOrder) + { + // + // Notfy Orders Changed Event ... + NotifyOrdersChangeEvent(state.newOrders + state.newHistoryOrders); + } + + // + // POSITIONS ... + if (state.hasNewPosition) + { + // + // Notfy Positions Changed Event ... + NotifyPositionsChangeEvent(state.newPositions); + } + + // + return state; + } + + // + // Trade Actions ... + + // + // Main ... + + // + // Policies ... + + // + // Check Acocunt Balance is Allow new Trades or not ... + bool CheckEquityForTrade() + { + // + bool result = false; + + // + if (mMaxAllowedDrawdownFactor <= 0) + { + // + result = true; + return result; + } + + // + double equity = mAccount.GetEquity(); + double balance = mAccount.GetBalance(); + + // + double selectedBalance = MathMax(equity, balance) - MathMin(equity, balance); + + // + double maxAllowedBalanceDrawDown = GetMaxAllowedEquity(); + + // + result = equity > balance || + (equity <= balance && + selectedBalance <= maxAllowedBalanceDrawDown); + + // + return result; + } + + // + // Check Max Allowed Positions Policy for Trade ... + bool CheckPositionsForTrade() + { + // + bool result = false; + + // + if (mMaxAllowedPositions <= 0) + { + // + result = true; + return result; + } + + // + XPosition positions[]; + int positionsCount = GetPositions(positions); + if (positionsCount <= 0) + { + // + result = true; + return result; + } + + // + result = positionsCount < mMaxAllowedPositions; + + // + return result; + } + + // + // Check Spread is Ok for Executing Specific Signal ... + bool CheckSpreadForSignalExecution(XSignal &signal) + { + // + bool result = false; + + // + bool isSpreadCheckEnable = mMaxAllowedSpread > 0; + if (!isSpreadCheckEnable) + { + result = true; + } + else + { + // + // Retrieve Signal Spread ... + double spread = signal.GetSpread(); + result = spread <= mMaxAllowedSpread; + } + + // + return result; + } + + // + // Check Account Policy ... + bool CheckAccountPolicy( + XSignal &signal, // For Executing Signal + ENUM_X_SIGNAL_EXECUTION_RESULT &state // State Holder + ) + { + // + bool result = false; + + // + // Check Positions For Trade ... + result = CheckPositionsForTrade(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + return result; + } + + // + // Check Equity For Trade ... + result = CheckEquityForTrade(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NO_EQUITY; + return result; + } + + // + // Check Spread for Trade ... + result = CheckSpreadForSignalExecution(signal); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_SPREAD; + return result; + } + + // + return result; + } + + // + // Manage ... + // this must be Call on OnTick for Manage + // Positions ... + // NOTE: Call this Before Checking IsNewBar ... + void Manage() + { + // + // All required Position Managements Actions implemented here ... + datetime tmc = TimeCurrent(); + bool canManage = !IsValid(mLastManageOn) + ? true + : mLastManageOn + mManageInterval >= tmc; + if (!canManage) + { + return; + } + + // + mLastManageOn = tmc; + + // + // - [] Partial Close; + // - [] Risk Free; + // - [] Trail Stop; + // - [] SLS; + // - [] TPS; + + // + // - [] Data Collector; + // - [] Profit Management; + + // + // TODO: Implement them ... + + // + // Implement Signal Collector Inside this Class + // and Manipulate Signals when SL/TP/Partial Close/Trail Stop/Profit/Close/ Modify and etc Happens ... + } + + // + // Execute a Signal ... + bool ExecuteSignal( + XSignal &signal, // Signal + ENUM_X_SIGNAL_EXECUTION_RESULT &state, // Result + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime + datetime expiration = NULL, // order expiration time + bool checkPolicies = true // Check Account Policies + ) + { + // + bool result = false; + state = X_SIGNAL_EXECUTION_UNKNOWN; + + // + double currentEntry = GetEntry( + signal.symbol, + signal.type + // + ); + bool isLong = IsLong(signal.type); + + // + // Select SL and TP ... + + // + double selectedSL = 0; + signal.RegularSL(selectedSL); + + // + double selectedTP = 0; + signal.RegularTP(selectedTP); + + // + if (!signal.IsValid()) + { + // + state = X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS; + return result; + } + + // + // Handle Market Execution ... + if (signal.mode == X_ORDER_MODE_MARKET) + { + // + // Do Apply Policies here ... + bool hasPolicy = !checkPolicies + ? true + : CheckAccountPolicy(signal, state); + if (!hasPolicy) + { + result = false; + } + else + { + // + if (isLong) + { + // + result = Buy( + signal.symbol, + signal.period, + signal.volume, + signal.entry, + selectedSL, + selectedTP, + signal.comment + // + ); + } + else + { + // + result = Sell( + signal.symbol, + signal.period, + signal.volume, + signal.entry, + selectedSL, + selectedTP, + signal.comment + // + ); + } + } + } + // + // Handle Stop Execution ... + else if (signal.mode == X_ORDER_MODE_STOP) + { + + // + // Check Conditions ... + + // + // Check Price ... + result = isLong + ? signal.entry > currentEntry + : signal.entry < currentEntry; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR; + return result; + } + + // + // Execute Order ... + if (isLong) + { + // + result = BuyStop( + signal.symbol, + signal.period, + signal.volume, + signal.entry, + selectedSL, + selectedTP, + lifetime, + expiration, + signal.comment + // + ); + } + else + { + // + result = SellStop( + signal.symbol, + signal.period, + signal.volume, + signal.entry, + selectedSL, + selectedTP, + lifetime, + expiration, + signal.comment + // + ); + } + } + // + // Handle Limit Execution ... + else if (signal.mode == X_ORDER_MODE_LIMIT) + { + // + // Check Conditions ... + + // + // Check Price ... + result = isLong + ? signal.entry < currentEntry + : signal.entry > currentEntry; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR; + return result; + } + + // + // Execute Order ... + if (isLong) + { + // + result = BuyLimit( + signal.symbol, + signal.period, + signal.volume, + signal.entry, + selectedSL, + selectedTP, + lifetime, + expiration, + signal.comment + // + ); + } + else + { + // + result = SellLimit( + signal.symbol, + signal.period, + signal.volume, + signal.entry, + selectedSL, + selectedTP, + lifetime, + expiration, + signal.comment + // + ); + } + } + + // + // Handle Ticket ... + if (result) + { + // + state = X_SIGNAL_EXECUTION_SUCCEED; + + // + ulong ticket; + if (signal.mode == X_ORDER_MODE_MARKET) + { + ticket = GetLastOpenPositionTicket(); + } + else + { + ticket = GetLastPlacedOrderTicket(); + } + + // + signal.positionId = ticket; + + // + // Handle Store XPositionInfo ... + if (signal.mode == X_ORDER_MODE_MARKET) + { + // + // TODO: Implement this ... + } + + // + // Handle Executing Support Signals ... + int supportsCount = ArraySize(signal.supports); + if (supportsCount > 0) + { + // + int executed = 0; + for (int i = 0; i < supportsCount; i++) + { + // + XSignal iSupport = signal.supports[i]; + + // + int supIndex = i + 1; + string iComment = GenerateSupportTag(ticket); + + // + bool isExecuted = ExecuteSignal( + iSupport, + state, + lifetime, + expiration + // + ); + if (isExecuted) + { + executed++; + } + } + + // + result = executed == supportsCount; + } + } + + // + return result; + } + + // + // Execute a Collection Of Signals ... + int ExecuteSignals( + XSignal &signals[], // Collection of Signal for Execution + ENUM_X_SIGNAL_EXECUTION_RESULT &states[], // Signal Execution Result + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime + datetime expiration = NULL, // order expiration time + bool checkPolicies = true // Check Account Policies + ) + { + // + int result = 0; + + // + Clean(states); + + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + ArrayResize(states, signalsCount); + ArrayInitialize(states, X_SIGNAL_EXECUTION_UNKNOWN); + for (int i = 0; i < signalsCount; i++) + { + // + bool isExecuted = ExecuteSignal( + signals[i], + states[i], + lifetime, + expiration + // + ); + + // + if (isExecuted) + { + result++; + } + } + + // + return result; + } + + // + // Regular Trade Actions ... + + // + // Buy ... + + // + // Force Open a Buy/Long Position ... + bool Buy( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.Buy( + volume, + symbol, + price, + sl, + tp, + comment + // + ); + + // + return result; + } + + // + // Send BUY LIMIT order ... + bool BuyLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.BuyLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Send BUY STOP order ... + bool BuyStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.BuyStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Sell ... + + // + // Force Open a Sell/Short Position ... + bool Sell( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.Sell( + volume, + symbol, + price, + sl, + tp, + comment + // + ); + + // + return result; + } + + // + // Send SELL LIMIT order ... + bool SellLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.SellLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Send SELL STOP order ... + bool SellStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.SellStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Check a Position is Exists Open or not ... + bool IsOpen( + ulong ticket // Specified Position Ticket + ) + { + // + bool result = false; + + // + result = mPositionInfo + .SelectByTicket(ticket); + + // + return result; + } + + // + // Modify Position ... + bool Modify( + const ulong ticket, // position ticket + double sl = 0, // stop loss price + double tp = 0, // take profit + string comment = NULL // comment + ) + { + // + bool result = false; + + // + // Validate Args ... + result = + IsOpen(ticket) && + (tp >= 0 || sl >= 0); + if (!result) + { + return result; + } + + // + // Use Position Comment when there isn't new One ... + if (!IsValid(comment) == 0) + { + // + // if there isn't provided Comment + // Use Position Comment for default ... + comment = "Modify " + GetPositionComment(ticket); + } + + // + result = mTrader.PositionModify( + ticket, + sl, + tp, + comment + // + ); + + // + return result; + } + + // + // Close Position By Ticket ... + bool Close( + ulong ticket, // Position Ticket + string comment = NULL // Close Position By Specific Comment + ) + { + // + bool result = false; + + // + // Check Position Open ... + result = !IsOpen(ticket); + if (!result) + { + return result; + } + + // + // Use Default Position Comment if it's Not Provided ... + if (!IsValid(comment)) + { + comment = "Close " + GetPositionComment(ticket); + } + + // + // Close Position By Specific Comment ... + result = mTrader.PositionClose( + ticket, + mSlippage, + comment + // + ); + + // + return result; + } + + // + // Close Specified Positions ... + int Close( + string comment = NULL, // Close Position By Specific Comment + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_POSITION_TYPE type = NULL, // Long (Buy) or Short (Sell) + bool filterByMagic = true // Get Only Self Open Positions + ) + { + // + int result = 0; + + // + XPosition positions[]; + int positionsCount = GetPositions( + positions, + symbol, + provider, + period, + type, + filterByMagic); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isClosed = Close( + iPosition.ticket, + comment + // + ); + if (isClosed) + { + result++; + } + } + + // + return result; + } + + // + // Close a Collection of Positions ... + int Close( + XPosition &positions[], // Collection of Positions + string comment // Close Comment + ) + { + // + int result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isClosed = Close( + iPosition.ticket, + comment + // + ); + if (isClosed) + { + result++; + } + } + + // + return result; + } + + // + // Close Partial By Ticket ... + bool ClosePartial( + ulong ticket, // Position Ticket + double volume, // Volume Size for Partial Closing + string comment = NULL // Close Position By Specific Comment + ) + { + // + bool result = false; + + // + result = IsOpen(ticket); + if (!result) + { + return result; + } + + // + // Use Default Partial Close Comment ... + if (!IsValid(comment)) + { + // + comment += "PClose " + GetPositionComment(ticket); + } + + // + result = mTrader.PositionClosePartial( + ticket, + volume, + mSlippage, + comment + // + ); + + // + return result; + } + + // + // Cancel Specific Order ... + bool CancelOrder(ulong ticket) + { + return mTrader + .OrderDelete(ticket); + } + + // + // Cancel Specific Orders ... + int CancelOrders( + XOrder &orders[] // Specified Orders ... + ) + { + // + int result = 0; + + // + int ordersCount = ArraySize(orders); + if (ordersCount <= 0) + { + return result; + } + + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder = orders[i]; + + // + bool isDeleted = mTrader + .OrderDelete(iOrder.ticket); + if (isDeleted && !result) + { + result++; + } + } + + // + return result; + } + + // + // Extractors ... + + // + // Positions ... + + // + // Calculate Positions Profit ... + double Profit( + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_POSITION_TYPE type = NULL, // Long (Buy) or Short (Sell) + bool filterByMagic = true // Get Only Self Open Positions + ) + { + // + double result = 0; + + // + // Retrieve Positions ... + XPosition positions[]; + int positionsCount = GetPositions( + positions, + symbol, + provider, + period, + type, + filterByMagic + // + ); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + result += positions[i].profit; + } + + // + return result; + } + + // + // Retrieve Specific Position by Index ... + bool GetPosition( + int index, // Specified Index + XPosition &result // Hold's Result + ) + { + // + return result + .ByIndex(index); + } + + // + // Retrieve Specific Position by Ticket ... + bool GetPosition( + ulong ticket, // Specified Ticket + XPosition &result // Hold's Result + ) + { + // + return result + .ByTicket(ticket); + } + + // + // Retrieve Positions ... + int GetPositions( + XPosition &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_POSITION_TYPE type = NULL, // Long (Buy) or Short (Sell) + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + // Count Positions ... + int itemsCount = PositionsTotal(); + if (itemsCount <= 0) + { + return mResult; + } + + // + // Loop Through all Positions ... + for (int i = itemsCount - 1; i >= 0; i--) + { + // + XPosition iItem; + bool isLoaded = iItem.ByIndex(i); + if (!isLoaded) + { + continue; + } + + // + // Now we have to Check Given Filters ... + bool isFiltersPassed = + iItem.IsFiltersPassed( + symbol, + provider, + period, + type, + mMagicNumber, + filterByMagic + // + ); + if (!isFiltersPassed) + { + continue; + } + + // + // Add Filtered Item into Result ... + AddRef( + iItem, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Select In Profit Positions ... + int GetInProfitPositions( + XPosition &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_POSITION_TYPE type = NULL, // Long (Buy) or Short (Sell) + ENUM_X_POSITION_SELECT_METHODS method = NULL, // Selection Method + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + XPosition positions[]; + int positionsCount = GetPositions( + positions, + symbol, + provider, + period, + type, + filterByMagic, + forceClean); + if (positionsCount <= 0) + { + return mResult; + } + + // + XPosition min; + XPosition max; + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit <= 0) + { + continue; + } + + // + // Calculate Min and Max ... + + // + // Min ... + if (!min.IsValid() || min.profit <= 0 || min.profit > iPosition.profit) + { + min = iPosition; + } + + // + // Max ... + if (!max.IsValid() || max.profit <= 0 || max.profit < iPosition.profit) + { + max = iPosition; + } + + // + bool isSelectionMethodFilterPassed = + // + (method == NULL || + method == X_POSITION_SELECT_ALL || + method == X_POSITION_SELECT_ALL) + ? true + : false; + // + ; + if (!isSelectionMethodFilterPassed) + { + continue; + } + + // + AddRef( + iPosition, + result + // + ); + } + + // + if (min.IsValid() && + (method == X_POSITION_SELECT_MIN || + method == X_POSITION_SELECT_BOTH)) + { + // + AddRef( + min, + result + // + ); + } + + // + if (max.IsValid() && + (method == X_POSITION_SELECT_MAX || + method == X_POSITION_SELECT_BOTH)) + { + // + AddRef( + max, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Select In Drawdown Positions ... + int GetInDrawdownPositions( + XPosition &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_POSITION_TYPE type = NULL, // Long (Buy) or Short (Sell) + ENUM_X_POSITION_SELECT_METHODS method = NULL, // Selection Method + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + XPosition positions[]; + int positionsCount = GetPositions( + positions, + symbol, + provider, + period, + type, + filterByMagic, + forceClean); + if (positionsCount <= 0) + { + return mResult; + } + + // + XPosition min; + XPosition max; + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit >= 0) + { + continue; + } + + // + // Calculate Min and Max ... + + // + // Min ... + if (!min.IsValid() || min.profit <= 0 || min.profit > iPosition.profit) + { + min = iPosition; + } + + // + // Max ... + if (!max.IsValid() || max.profit <= 0 || max.profit < iPosition.profit) + { + max = iPosition; + } + + // + bool isSelectionMethodFilterPassed = + // + (method == NULL || + method == X_POSITION_SELECT_ALL || + method == X_POSITION_SELECT_ALL) + ? true + : false; + // + ; + if (!isSelectionMethodFilterPassed) + { + continue; + } + + // + AddRef( + iPosition, + result + // + ); + } + + // + if (min.IsValid() && + (method == X_POSITION_SELECT_MIN || + method == X_POSITION_SELECT_BOTH)) + { + // + AddRef( + min, + result + // + ); + } + + // + if (max.IsValid() && + (method == X_POSITION_SELECT_MAX || + method == X_POSITION_SELECT_BOTH)) + { + // + AddRef( + max, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Orders ... + + // + // Retrieve Specific Order by Index ... + bool GetOrder( + int index, // Specified Index + XOrder &result // Hold's Result + ) + { + // + return result + .ByIndex(index); + } + + // + // Retrieve Specific Positions Orders ... + int GetOrders( + ulong ticket, // Positions Ticket + XOrder &result[], // Hold's Result + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + // Select History by Specified Ticket ... + bool isHistorySelected = HistorySelectByPosition(ticket); + if (!isHistorySelected) + { + return mResult; + } + + // + int ordersCount = HistoryOrdersTotal(); + if (ordersCount <= 0) + { + return mResult; + } + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder; + bool isLoaded = iOrder.HistoryByIndex(i); + if (!isLoaded) + { + continue; + } + + // + bool isTicketFilterPassed = + // + iOrder.ticket = ticket + // + ; + if (!isTicketFilterPassed) + { + continue; + } + + // + AddRef( + iOrder, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Retrieve All Orders ... + int GetOrders( + XOrder &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_ORDER_TYPE type = NULL, // Long (Buy) or Short (Sell) + ENUM_ORDER_STATE state = NULL, // Order State + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + // Count Positions ... + int itemsCount = OrdersTotal(); + if (itemsCount <= 0) + { + return mResult; + } + + // + // Loop Through all Positions ... + for (int i = itemsCount - 1; i >= 0; i--) + { + // + XOrder iItem; + bool isLoaded = iItem.ByIndex(i); + if (!isLoaded) + { + continue; + } + + // + // Now we have to Check Given Filters ... + bool isFiltersPassed = + iItem.IsFiltersPassed( + symbol, + provider, + period, + type, + state, + mMagicNumber, + filterByMagic + // + ); + if (!isFiltersPassed) + { + continue; + } + + // + // Add Filtered Item into Result ... + AddRef( + iItem, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Retrieve Historical Orders ... + int GetOrders( + XOrder &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_ORDER_TYPE type = NULL, // Long (Buy) or Short (Sell) + ENUM_ORDER_STATE state = NULL, // Order State + datetime startDate = NULL, // Specify Start Date + datetime endDate = NULL, // Specify End Date + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + endDate = NormalizeTime(endDate); + + // + if (!IsValid(startDate)) + { + startDate = endDate - PeriodSeconds(PERIOD_D1); + } + + // + bool isHistorySelected = HistorySelect( + startDate, + endDate); + if (!isHistorySelected) + { + return mResult; + } + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + // Count Positions ... + int itemsCount = OrdersTotal(); + if (itemsCount <= 0) + { + return mResult; + } + + // + // Loop Through all Positions ... + for (int i = itemsCount - 1; i >= 0; i--) + { + // + XOrder iItem; + bool isLoaded = iItem.HistoryByIndex(i); + if (!isLoaded) + { + continue; + } + + // + // Now we have to Check Given Filters ... + bool isFiltersPassed = + iItem.IsFiltersPassed( + symbol, + provider, + period, + type, + state, + mMagicNumber, + filterByMagic + // + ); + if (!isFiltersPassed) + { + continue; + } + + // + // Add Filtered Item into Result ... + AddRef( + iItem, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Deals ... + + // + // Retrieve Specific Deal by Index ... + bool GetDeal( + int index, // Specified Index + XDeal &result // Hold's Result + ) + { + // + return result + .ByIndex(index); + } + + // + // Retrieve Specified Deal's History ... + int GetDealsHistory( + XDeal &deal, // Specified Deal + XOrder &history[], // Deals History + bool forceClean = true // Clean Result Array + ) + { + // + int result = 0; + + // + if (!deal.IsValid()) + { + return result; + } + + // + result = GetOrders( + deal.positionId, + history, + forceClean); + + // + return result; + } + + // + // Retrieve All Deals ... + int GetDeals( + XDeal &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_DEAL_TYPE type = NULL, // Deal Type + ENUM_DEAL_ENTRY entry = NULL, // Deal Entry + ENUM_DEAL_REASON reason = NULL, // Deal Reason + datetime startDate = NULL, // Specify Start Date + datetime endDate = NULL, // Specify End Date + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + endDate = NormalizeTime(endDate); + + // + if (!IsValid(startDate)) + { + startDate = endDate - PeriodSeconds(PERIOD_D1); + } + + // + bool isHistorySelected = HistorySelect( + startDate, + endDate); + if (!isHistorySelected) + { + return mResult; + } + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + // Count Positions ... + int itemsCount = HistoryDealsTotal(); + if (itemsCount <= 0) + { + return mResult; + } + + // + // Loop Through all Positions ... + for (int i = itemsCount - 1; i >= 0; i--) + { + // + XDeal iItem; + bool isLoaded = iItem.ByIndex(i); + if (!isLoaded) + { + continue; + } + + // + // Now we have to Check Given Filters ... + bool isFiltersPassed = + iItem.IsFiltersPassed( + symbol, + provider, + period, + type, + entry, + reason, + mMagicNumber, + filterByMagic + // + ); + if (!isFiltersPassed) + { + continue; + } + + // + // Add Filtered Item into Result ... + AddRef( + iItem, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Protected ... +protected: + // + // Props ... + + // + // Event Listener Notifiers ... + + // + // State ... + void NotifyTradeStateChangeEvent(const XOnTradeHandlerState &state) + { + // + int count = ArraySize(mTradeStateChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnTradeStateChanged iHandler = mTradeStateChangedEventHandlers[i]; + iHandler(state); + } + } + + // + // Deals ... + void NotifyDealsChangeEvent(int changes) + { + // + int count = ArraySize(mDealsChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnDealsChanged iHandler = mDealsChangedEventHandlers[i]; + iHandler(changes); + } + } + + // + // Orders ... + void NotifyOrdersChangeEvent(int changes) + { + // + int count = ArraySize(mOrdersChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnOrdersChanged iHandler = mOrdersChangedEventHandlers[i]; + iHandler(changes); + } + } + + // + // Positions ... + void NotifyPositionsChangeEvent(int changes) + { + // + int count = ArraySize(mPositionsChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnPositionsChanged iHandler = mPositionsChangedEventHandlers[i]; + iHandler(changes); + } + } + + // + // StopLoss ... + void NotifyStopLossEvent(const XDeal &deal) + { + // + int count = ArraySize(mStopLossEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnStopLoss iHandler = mStopLossEventHandlers[i]; + iHandler(deal); + } + } + + // + // Take Profit ... + void NotifyTakeProfitEvent(const XDeal &deal) + { + // + int count = ArraySize(mTakeProfitEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnTakeProfit iHandler = mTakeProfitEventHandlers[i]; + iHandler(deal); + } + } + + // + // Tools ... + + // + // Retrieve Specified Position Comment ... + string GetPositionComment(ulong ticket) + { + // + string result = NULL; + + // + if (!IsOpen(ticket)) + { + return result; + } + + // + XPosition position; + bool isLoaded = position.ByTicket(ticket); + if (!isLoaded) + { + return result; + } + + // + result = position.comment; + + // + return result; + } + + // + // Retrieve Last Open Position Ticket ... + ulong GetLastOpenPositionTicket() + { + // + ulong result = 0; + + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + result = PositionGetTicket(PositionsTotal() - 1); + + // + return result; + } + + // + // Retrieve Last Placed Order Ticket ... + ulong GetLastPlacedOrderTicket() + { + // + ulong result = 0; + + int ordersCount = OrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + if (mOrderInfo.SelectByIndex(ordersCount - 1)) + { + result = mOrderInfo.Ticket(); + } + + // + return result; + } + + // + // XPosition Pack ... + + // + // Extract specific Positions Pack ... + // in this senario there is no need to Position exists itself ... + bool GetPositionPack( + ulong ticket, // Specified Positions Ticket + string symbol, // Specified Position Symbol + ENUM_TIMEFRAMES period, // Specified Position Period + XPositionPack &pack // Hold Result + ) + { + // + bool result = false; + + // + pack.Clean(); + + // + XPosition position; + bool hasPosition = GetPosition( + ticket, + position + // + ); + if (hasPosition) + { + pack.position = position; + } + + // + XOrder supportOrders[]; + XPosition supportPositions[]; + + // + XOrder orders[]; + GetOrders( + orders, + symbol, // Specified Symbol + NULL, // All Providers + period, // Specified Period + NULL, // All Types + ORDER_STATE_PLACED, // Just UnTriggered Orders + true // Filter by Magic + ); + int ordersCount = ArraySize(orders); + + // + // Select Orders ... + if (ordersCount > 0) + { + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder = orders[i]; + + // + // Retrieve Order Supported Ticket ... + ulong parentTicket = ExtractSupportedTicket(iOrder.comment); + if (NotEmpty(parentTicket) && parentTicket == ticket) + { + // + AddRef( + iOrder, + supportOrders + // + ); + } + } + } + + // + int supportOrdersCount = ArraySize(supportOrders); + if (supportOrdersCount > 0) + { + // + pack.supportOrdersCount = supportOrdersCount; + + // + Copy( + supportOrders, + pack.supportOrders); + } + + // + XPosition positions[]; + GetPositions( + positions, + symbol, // Specified Symbol ... + NULL, // All Providers ... + period // Specified Period ... + ); + int positionsCount = ArraySize(positions); + + // + // Select Positions ... + if (positionsCount > 0) + { + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + ulong parentTicket = ExtractSupportedTicket(iPosition.comment); + if (NotEmpty(parentTicket) && parentTicket == ticket) + { + // + AddRef( + iPosition, + supportPositions + // + ); + } + } + } + + // + int supportPositionsCount = ArraySize(supportPositions); + if (supportPositionsCount > 0) + { + // + pack.supportPositionsCount = supportPositionsCount; + + // + Copy( + supportPositions, + pack.supportPositions); + } + + // + result = supportOrdersCount > 0 || supportPositionsCount > 0; + + // + return result; + } + + // + // Extract Specific Deals Position's Pack ... + // this used when a Position SL or TP triggered and we want to close + // all it's Supported Packs ... + bool GetDealPack( + XDeal &deal, + XPositionPack &pack // + ) + { + // + bool result = false; + + // + ulong ticket = deal.positionId; + ENUM_TIMEFRAMES dealPeriod = GetDealPeriod(deal); + string dealSymbol = deal.symbol; + + // + // So We Have to Get Positions Pack ... + result = GetPositionPack( + ticket, + dealSymbol, + dealPeriod, + pack + // + ); + + // + return result; + } + + // + ENUM_TIMEFRAMES GetDealPeriod(XDeal &deal) + { + // + ENUM_TIMEFRAMES result = NULL; + + // + XOrder orders[]; + int ordersCount = GetDealsHistory( + deal, + orders); + if (!ordersCount) + { + return result; + } + + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder = orders[i]; + + // + if (IsValid(iOrder.comment)) + { + // + ENUM_TIMEFRAMES iPeriod = ExtractPeriod(iOrder.comment); + if (IsValid(iPeriod)) + { + result = iPeriod; + break; + } + } + } + + // + return result; + } + + // + double GetMaxAllowedEquity() + { + // + double equity = mAccount.GetEquity(); + double balance = mAccount.GetBalance(); + + // + double balanceForFactor = MathAbs(equity - balance); + if (balanceForFactor <= 0) + { + balanceForFactor = balance; + } + else + { + balanceForFactor = equity; + } + + // + double result = balanceForFactor * mMaxAllowedDrawdownFactor; + + // + return result; + } + + // + // Private ... +private: + // + // Props ... + + // + int mSlippage; // Slippage ... + ulong mMagicNumber; // Magic Number (Unique Identifier) ... + + // + datetime mLastManageOn; // Last Manager Check + int mManageInterval; // Manager Check Intervals Seconds + + // + double mMaxAllowedSpread; // Max Allowed Spred for Opening Trades + int mMaxAllowedPositions; // Max Allowed Same Positions + double mMaxAllowedDrawdownFactor; // Max Allowed Drawdown Factor + + // + XSCAccount *mAccount; // Account Info Provider + XSCTradeBase *mTrader; // Base CTrade Manipulated Instance ... + + // + CDealInfo mDealInfo; // Deals Info ... + COrderInfo mOrderInfo; // Order Info ... + CPositionInfo mPositionInfo; // Positions Info + CHistoryOrderInfo mHistoryOrderInfo; // History Orders Info ... + + // + // Position Info Collector ... + + // + XSCPositionInfoCollector mPositionInfoCollector; // Position Info Data Collector ... + + // + void SyncPositionInfos() + { + // + // TODO: Complete this ... + + // + // Read All Stored Positions ... + // XPositionInfo infos[]; + // int infosCount = mPositionInfoCollector.Collect(infos); + + // // + // // Clear Store ... + // mPositionInfoCollector.Clear(); + + // // + // XPosition positions[]; + // int positionsCount = GetPositions(positions); + // if (positionsCount <= 0) + // { + // Clean(infos); + // } + + // // + // // Now we Have to Find each Position Info inside Positions and Update them ... + // XPositionInfo datas[]; + // for (int i = 0; i < infosCount; i++) + // { + // // + // XPositionInfo iInfo = infos[i]; + + // // + // // Check Positions Contains Specific ticket or not ... + // for (int j = 0; j < positionsCount; j++) + // { + // // + // XPosition jPosition = positions[j]; + + // // + // if (jPosition.ticket != iInfo.ticket) + // { + // // + // // this is a Position which is not listed in Collector ... + // } + // else + // { + // // + // // Now we have a Position which Listed Before in Collector ... + // // we Have to Update it ... + // } + // } + // } + } + + // + // Tools ... + + // + // OnTrade Event Handlers Section ... + + // + // Props ... + + // + int mDaysForRead; // Reading Dates for Trade History Checker ... + datetime mEndDate; // End Date for Trade history Checking ... + datetime mStartDate; // Start Date for Trade history Checking ... ... + int mOrdersCount; // Number of Active orders ... + int mPositionsCount; // Number of Open positions ... + int mDealsCount; // Number of Deals in the Trade History Checking ... + int mHistoryOrdersCount; // Number of Orders in the Trade History Checking ... + bool mScanStarted; // a Flag of counter relevance ... + + // + // Event Listeners ... + + // + // Deals Changed Event Handlers ... + TOnDealsChanged mDealsChangedEventHandlers[]; + + // + // Orders Changed Event Handlers ... + TOnOrdersChanged mOrdersChangedEventHandlers[]; + + // + // Positions Changed Event Handlers ... + TOnPositionsChanged mPositionsChangedEventHandlers[]; + + // + // Trade State Changed Event Handlers ... + TOnTradeStateChanged mTradeStateChangedEventHandlers[]; + + // + // TPSL ... + TOnStopLoss mStopLossEventHandlers[]; + TOnTakeProfit mTakeProfitEventHandlers[]; + + // + // Reset On Trade Scanner Context ... + void ResetOnTradeContext() + { + // + mEndDate = TimeCurrent(); + mStartDate = mEndDate - (mDaysForRead * PeriodSeconds(PERIOD_D1)); + } + + // + // Initial Context Of Trade Scanner ... + void InitOnTradeContext() + { + // + ResetLastError(); + + // + mOrdersCount = OrdersTotal(); + mPositionsCount = PositionsTotal(); + + // + // load history ... + bool selected = HistorySelect(mStartDate, mEndDate); + if (!selected) + { + return; + } + + // + // get the current value ... + mDealsCount = HistoryDealsTotal(); + mHistoryOrdersCount = HistoryOrdersTotal(); + + // + mScanStarted = true; + } + + // + // Check Statrt Date In Trade History ... + void CheckStartDateInTradeHistory() + { + // + // initial interval, if we were to start working right now .. + datetime currStart = TimeCurrent() - (mDaysForRead * PeriodSeconds(PERIOD_D1)); + + // + // make sure that the start limit of the trade history has not gone + // more than 1 day over the intended date ... + if (currStart - mStartDate > PeriodSeconds(PERIOD_D1)) + { + // + // correct the start date of history to be loaded in the cache ... + mStartDate = currStart; + + // + // now reload the trade history for the updated interval ... + HistorySelect(mStartDate, mEndDate); + + // + // correct the deal and order counters in history for further comparison + mHistoryOrdersCount = HistoryOrdersTotal(); + mDealsCount = HistoryDealsTotal(); + } + } + + // + // Process On Trade Context ... + void ProcessOnTradeContext( + XOnTradeHandlerState &result // Hold's Result + ) + { + // + mEndDate = TimeCurrent(); + + // + ResetLastError(); + + // + // download trading history from the specified interval to the program cache ... + bool selected = HistorySelect(mStartDate, mEndDate); + if (!selected) + { + return; + } + + // + // get the current values ... + int currOrders = OrdersTotal(); + int currPositions = PositionsTotal(); + int currDeals = HistoryDealsTotal(); + int currHistoryOrders = HistoryOrdersTotal(); + + // + // Orders ... + // check if the number of active orders has been changed ... + if (currOrders != mOrdersCount) + { + // + // number of active orders has been changed ... + result.hasNewOrder = true; + result.newOrders = currOrders - mOrdersCount; + + // + // update the value ... + mOrdersCount = currOrders; + } + + // + // Positions ... + // changes in the number of open positions ... + if (currPositions != mPositionsCount) + { + // + // number of open positions has been changed ... + result.hasNewPosition = true; + result.newPositions = currPositions - mPositionsCount; + + // + // update the value ... + mPositionsCount = currPositions; + } + + // + // Deals ... + // changes in the number of deals in the trade history cache ... + if (currDeals != mDealsCount) + { + // + // number of deals in the trade history cache has been changed ... + result.hasNewDeal = true; + result.newDeals = currDeals - mDealsCount; + + // + // update the value ... + mDealsCount = currDeals; + } + + // + // History Orders ... + // changes in the number of history orders in the trade history cache ... + if (currHistoryOrders != mHistoryOrdersCount) + { + // + // number of history orders in the trade history cache has been changed ... + result.hasNewHistoryOrder = true; + result.newHistoryOrders = currHistoryOrders - mHistoryOrdersCount; + + // + // update the value ... + mHistoryOrdersCount = currHistoryOrders; + } + + // + // checking if it is necessary to change the limits of the trade history to be requested in cache ... + CheckStartDateInTradeHistory(); + } +}; + +// \ No newline at end of file diff --git a/Helpers/x-saherelm.xama.helper.mq5 b/Helpers/x-saherelm.xama.helper.mq5 index 3e8ee7ef..227800b5 100644 --- a/Helpers/x-saherelm.xama.helper.mq5 +++ b/Helpers/x-saherelm.xama.helper.mq5 @@ -35,7 +35,7 @@ enum ENUM_XAMA_BUFFERS // // Input Models ... -struct XXAMAInputs +struct XAMAInputs { // // Props ... @@ -52,7 +52,7 @@ struct XXAMAInputs // // Constructor(s) ... - XXAMAInputs() + XAMAInputs() { // Clean(); @@ -148,7 +148,7 @@ public: bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XXAMAInputs &inputs // Inputs + XAMAInputs &inputs // Inputs ) { // @@ -204,14 +204,14 @@ public: // Inputs ... // - XXAMAInputs GetInputs() + XAMAInputs GetInputs() { return mInputs; } // bool SetInputs( - XXAMAInputs &inputs // Configs + XAMAInputs &inputs // Configs ) { // @@ -284,7 +284,7 @@ protected: private: // // Props ... - XXAMAInputs mInputs; // Inputs ... + XAMAInputs mInputs; // Inputs ... // // Buffers ... @@ -311,7 +311,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xcc.helper.mq5 b/Helpers/x-saherelm.xcc.helper.mq5 index 1e923eb2..c16b4bdf 100644 --- a/Helpers/x-saherelm.xcc.helper.mq5 +++ b/Helpers/x-saherelm.xcc.helper.mq5 @@ -29,7 +29,7 @@ // // Input Models ... -struct XXCCInputs +struct XCCInputs { // // Props ... @@ -49,7 +49,7 @@ struct XXCCInputs // // Constructor(s) ... - XXCCInputs() + XCCInputs() { // Clean(); @@ -147,7 +147,7 @@ public: bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XXCCInputs &inputs // Inputs + XCCInputs &inputs // Inputs ) { // @@ -203,14 +203,14 @@ public: // Inputs ... // - XXCCInputs GetInputs() + XCCInputs GetInputs() { return mInputs; } // bool SetInputs( - XXCCInputs &inputs // Configs + XCCInputs &inputs // Configs ) { // @@ -230,8 +230,8 @@ protected: private: // // Props ... - XXCCInputs mInputs; // Inputs ... -} + XCCInputs mInputs; // Inputs ... +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xchlh.helper.mq5 b/Helpers/x-saherelm.xchlh.helper.mq5 index 3425be8f..487f5bc6 100644 --- a/Helpers/x-saherelm.xchlh.helper.mq5 +++ b/Helpers/x-saherelm.xchlh.helper.mq5 @@ -49,7 +49,7 @@ enum ENUM_XCHLH_BUFFERS // // Input Models ... -struct XXCHLHInputs +struct XCHLHInputs { // // Props ... @@ -116,7 +116,7 @@ struct XXCHLHInputs // // Constructor(s) ... - XXCHLHInputs() + XCHLHInputs() { // Clean(); @@ -331,7 +331,7 @@ public: bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XXCHLHInputs &inputs // Inputs + XCHLHInputs &inputs // Inputs ) { // @@ -464,14 +464,14 @@ public: // Inputs ... // - XXCHLHInputs GetInputs() + XCHLHInputs GetInputs() { return mInputs; } // bool SetInputs( - XXCHLHInputs &inputs // Configs + XCHLHInputs &inputs // Configs ) { // @@ -853,7 +853,7 @@ protected: private: // // Props ... - XXCHLHInputs mInputs; // Inputs ... + XCHLHInputs mInputs; // Inputs ... // // Buffers ... @@ -961,7 +961,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xchma.helper.mq5 b/Helpers/x-saherelm.xchma.helper.mq5 index 20a329c8..a0a6c5d5 100644 --- a/Helpers/x-saherelm.xchma.helper.mq5 +++ b/Helpers/x-saherelm.xchma.helper.mq5 @@ -48,7 +48,7 @@ enum ENUM_XCHMA_BUFFERS // // Input Models ... -struct XXCHMAInputs +struct XCHMAInputs { // // Props ... @@ -116,7 +116,7 @@ struct XXCHMAInputs // // Constructor(s) ... - XXCHMAInputs() + XCHMAInputs() { // Clean(); @@ -325,7 +325,7 @@ public: bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XXCHMAInputs &inputs // Inputs + XCHMAInputs &inputs // Inputs ) { // @@ -457,14 +457,14 @@ public: // Inputs ... // - XXCHMAInputs GetInputs() + XCHMAInputs GetInputs() { return mInputs; } // bool SetInputs( - XXCHMAInputs &inputs // Configs + XCHMAInputs &inputs // Configs ) { // @@ -846,7 +846,7 @@ protected: private: // // Props ... - XXCHMAInputs mInputs; // Inputs ... + XCHMAInputs mInputs; // Inputs ... // // Buffers ... @@ -954,7 +954,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xct.helper.mq5 b/Helpers/x-saherelm.xct.helper.mq5 index b5030ab5..a7e87696 100644 --- a/Helpers/x-saherelm.xct.helper.mq5 +++ b/Helpers/x-saherelm.xct.helper.mq5 @@ -29,7 +29,7 @@ // // Input Models ... -struct XXCTInputs +struct XCTInputs { // // Props ... @@ -44,7 +44,7 @@ struct XXCTInputs // // Constructor(s) ... - XXCTInputs() + XCTInputs() { // Clean(); @@ -137,7 +137,7 @@ public: bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XXCTInputs &inputs // Inputs + XCTInputs &inputs // Inputs ) { // @@ -186,14 +186,14 @@ public: // Inputs ... // - XXCTInputs GetInputs() + XCTInputs GetInputs() { return mInputs; } // bool SetInputs( - XXCTInputs &inputs // Configs + XCTInputs &inputs // Configs ) { // @@ -213,8 +213,8 @@ protected: private: // // Props ... - XXCTInputs mInputs; // Inputs ... -} + XCTInputs mInputs; // Inputs ... +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xdon.helper.mq5 b/Helpers/x-saherelm.xdon.helper.mq5 index 78adc020..b694d62d 100644 --- a/Helpers/x-saherelm.xdon.helper.mq5 +++ b/Helpers/x-saherelm.xdon.helper.mq5 @@ -825,7 +825,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xfi.helper.mq5 b/Helpers/x-saherelm.xfi.helper.mq5 index 7701ec41..f0207604 100644 --- a/Helpers/x-saherelm.xfi.helper.mq5 +++ b/Helpers/x-saherelm.xfi.helper.mq5 @@ -35,7 +35,7 @@ enum ENUM_XFI_BUFFERS // // Input Models ... -struct XXFIInputs +struct XFIInputs { // // Props ... @@ -45,7 +45,7 @@ struct XXFIInputs // // Constructor(s) ... - XXFIInputs() + XFIInputs() { // Clean(); @@ -132,7 +132,7 @@ public: bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XXFIInputs &inputs // Inputs + XFIInputs &inputs // Inputs ) { // @@ -179,14 +179,14 @@ public: // Inputs ... // - XXFIInputs GetInputs() + XFIInputs GetInputs() { return mInputs; } // bool SetInputs( - XXFIInputs &inputs // Configs + XFIInputs &inputs // Configs ) { // @@ -259,7 +259,7 @@ protected: private: // // Props ... - XXFIInputs mInputs; // Inputs ... + XFIInputs mInputs; // Inputs ... // // Buffers ... @@ -286,7 +286,7 @@ private: // // // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xhk.helper.mq5 b/Helpers/x-saherelm.xhk.helper.mq5 index d1d00226..13da70c0 100644 --- a/Helpers/x-saherelm.xhk.helper.mq5 +++ b/Helpers/x-saherelm.xhk.helper.mq5 @@ -1022,7 +1022,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xhull.helper.mq5 b/Helpers/x-saherelm.xhull.helper.mq5 index 87ceb217..900f6298 100644 --- a/Helpers/x-saherelm.xhull.helper.mq5 +++ b/Helpers/x-saherelm.xhull.helper.mq5 @@ -2,7 +2,7 @@ // // SaherElm IT Center MQL5 Helper Class Library // ---------------------------------------------- -// Name: XSCXHULLCHelper +// Name: XSCXHULLHelper // Description: provides all Indicator // Helper requirements ... // @@ -36,7 +36,7 @@ enum ENUM_XHULLC_BUFFERS // // Input Models ... -struct XHULLCInputs +struct XHULLInputs { // // Props ... @@ -57,7 +57,7 @@ struct XHULLCInputs // // Constructor(s) ... - XHULLCInputs() + XHULLInputs() { // Clean(); @@ -142,7 +142,7 @@ struct XHULLCInputs // // Class ... -class XSCXHULLCHelper : public XSCBaseHelper +class XSCXHULLHelper : public XSCBaseHelper { // // Public ... @@ -152,20 +152,20 @@ public: // // Constructors ... - XSCXHULLCHelper() : XSCBaseHelper(_Symbol, _Period) + XSCXHULLHelper() : XSCBaseHelper(_Symbol, _Period) { } // // Deconstructor ... - ~XSCXHULLCHelper() {} + ~XSCXHULLHelper() {} // // Tools ... bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XHULLCInputs &inputs // Inputs + XHULLInputs &inputs // Inputs ) { // @@ -224,14 +224,14 @@ public: // Inputs ... // - XHULLCInputs GetInputs() + XHULLInputs GetInputs() { return mInputs; } // bool SetInputs( - XHULLCInputs &inputs // Configs + XHULLInputs &inputs // Configs ) { // @@ -354,7 +354,7 @@ protected: private: // // Props ... - XHULLCInputs mInputs; // Inputs ... + XHULLInputs mInputs; // Inputs ... // // Buffers ... @@ -393,7 +393,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xlh.helper.mq5 b/Helpers/x-saherelm.xlh.helper.mq5 index a4c57a08..400407a3 100644 --- a/Helpers/x-saherelm.xlh.helper.mq5 +++ b/Helpers/x-saherelm.xlh.helper.mq5 @@ -37,7 +37,7 @@ enum ENUM_XLH_BUFFERS // // Input Models ... -struct XXLHInputs +struct XLHInputs { // // Props ... @@ -47,7 +47,7 @@ struct XXLHInputs // // Constructor(s) ... - XXLHInputs() + XLHInputs() { // Clean(); @@ -134,7 +134,7 @@ public: bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XXLHInputs &inputs // Inputs + XLHInputs &inputs // Inputs ) { // @@ -185,14 +185,14 @@ public: // Inputs ... // - XXLHInputs GetInputs() + XLHInputs GetInputs() { return mInputs; } // bool SetInputs( - XXLHInputs &inputs // Configs + XLHInputs &inputs // Configs ) { // @@ -365,7 +365,7 @@ protected: private: // // Props ... - XXLHInputs mInputs; // Inputs ... + XLHInputs mInputs; // Inputs ... // // Buffers ... @@ -416,7 +416,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xmrb.helper.mq5 b/Helpers/x-saherelm.xmrb.helper.mq5 index 0977effa..171d3d5f 100644 --- a/Helpers/x-saherelm.xmrb.helper.mq5 +++ b/Helpers/x-saherelm.xmrb.helper.mq5 @@ -1223,7 +1223,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xobd.helper.mq5 b/Helpers/x-saherelm.xobd.helper.mq5 index ba39b9d9..968e9524 100644 --- a/Helpers/x-saherelm.xobd.helper.mq5 +++ b/Helpers/x-saherelm.xobd.helper.mq5 @@ -35,7 +35,7 @@ enum ENUM_XOBD_BUFFERS // // Input Models ... -struct XXOBDInputs +struct XOBDInputs { // // Props ... @@ -53,7 +53,7 @@ struct XXOBDInputs // // Constructor(s) ... - XXOBDInputs() + XOBDInputs() { // Clean(); @@ -144,7 +144,7 @@ public: bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XXOBDInputs &inputs // Inputs + XOBDInputs &inputs // Inputs ) { // @@ -193,14 +193,14 @@ public: // Inputs ... // - XXOBDInputs GetInputs() + XOBDInputs GetInputs() { return mInputs; } // bool SetInputs( - XXOBDInputs &inputs // Configs + XOBDInputs &inputs // Configs ) { // @@ -273,7 +273,7 @@ protected: private: // // Props ... - XXOBDInputs mInputs; // Inputs ... + XOBDInputs mInputs; // Inputs ... // // Buffers ... @@ -300,7 +300,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xosc.helper.mq5 b/Helpers/x-saherelm.xosc.helper.mq5 index 27380623..20f738ec 100644 --- a/Helpers/x-saherelm.xosc.helper.mq5 +++ b/Helpers/x-saherelm.xosc.helper.mq5 @@ -279,7 +279,7 @@ public: bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XOSCInputs &inputs // Inputs + XOSCInputs &inputs // Inputs ) { // @@ -315,6 +315,8 @@ public: ArraySetAsSeries(stochMainBuffer, true); ArraySetAsSeries(stochSignalBuffer, true); ArraySetAsSeries(stddevBuffer, true); + + // mHandler = iCustom( mSymbol, mPeriod, diff --git a/Helpers/x-saherelm.xpv.helper.mq5 b/Helpers/x-saherelm.xpv.helper.mq5 index d0716eaf..8045a2e4 100644 --- a/Helpers/x-saherelm.xpv.helper.mq5 +++ b/Helpers/x-saherelm.xpv.helper.mq5 @@ -65,7 +65,7 @@ enum ENUM_XPV_BUFFERS // // Input Models ... -struct XXPVInputs +struct XPVInputs { // // Props ... @@ -119,7 +119,7 @@ struct XXPVInputs // // Constructor(s) ... - XXPVInputs() + XPVInputs() { // Clean(); @@ -290,7 +290,7 @@ public: bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XXPVInputs &inputs // Inputs + XPVInputs &inputs // Inputs ) { // @@ -399,14 +399,14 @@ public: // Inputs ... // - XXPVInputs GetInputs() + XPVInputs GetInputs() { return mInputs; } // bool SetInputs( - XXPVInputs &inputs // Configs + XPVInputs &inputs // Configs ) { // @@ -1348,7 +1348,7 @@ protected: private: // // Props ... - XXPVInputs mInputs; // Inputs ... + XPVInputs mInputs; // Inputs ... // // Buffers ... @@ -1591,7 +1591,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xrsi.helper.mq5 b/Helpers/x-saherelm.xrsi.helper.mq5 index 09fc124f..804cf355 100644 --- a/Helpers/x-saherelm.xrsi.helper.mq5 +++ b/Helpers/x-saherelm.xrsi.helper.mq5 @@ -35,7 +35,7 @@ enum ENUM_XRSI_BUFFERS // // Input Models ... -struct XXRSIInputs +struct XRSIInputs { // // Props ... @@ -71,7 +71,7 @@ struct XXRSIInputs // // Constructor(s) ... - XXRSIInputs() + XRSIInputs() { // Clean(); @@ -206,7 +206,7 @@ public: bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XXRSIInputs &inputs // Inputs + XRSIInputs &inputs // Inputs ) { // @@ -279,14 +279,14 @@ public: // Inputs ... // - XXRSIInputs GetInputs() + XRSIInputs GetInputs() { return mInputs; } // bool SetInputs( - XXRSIInputs &inputs // Configs + XRSIInputs &inputs // Configs ) { // @@ -359,7 +359,7 @@ protected: private: // // Props ... - XXRSIInputs mInputs; // Inputs ... + XRSIInputs mInputs; // Inputs ... // // Buffers ... @@ -386,7 +386,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xsslc.helper.mq5 b/Helpers/x-saherelm.xsslc.helper.mq5 index c2c69f00..6198876a 100644 --- a/Helpers/x-saherelm.xsslc.helper.mq5 +++ b/Helpers/x-saherelm.xsslc.helper.mq5 @@ -402,7 +402,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xstr.helper.mq5 b/Helpers/x-saherelm.xstr.helper.mq5 index 9d954f6c..009f3bae 100644 --- a/Helpers/x-saherelm.xstr.helper.mq5 +++ b/Helpers/x-saherelm.xstr.helper.mq5 @@ -2,7 +2,7 @@ // // SaherElm IT Center MQL5 Helper Class Library // ---------------------------------------------- -// Name: XSCXSTRRHelper +// Name: XSCXSTRHelper // Description: provides all Indicator // Helper requirements ... // @@ -42,7 +42,7 @@ enum ENUM_XSTR_TREND_STATES // // Input Models ... -struct XSTRRInputs +struct XSTRInputs { // // Props ... @@ -60,7 +60,7 @@ struct XSTRRInputs // // Constructor(s) ... - XSTRRInputs() + XSTRInputs() { // Clean(); @@ -131,7 +131,7 @@ struct XSTRRInputs // // Class ... -class XSCXSTRRHelper : public XSCBaseHelper +class XSCXSTRHelper : public XSCBaseHelper { // // Public ... @@ -141,20 +141,20 @@ public: // // Constructors ... - XSCXSTRRHelper() : XSCBaseHelper(_Symbol, _Period) + XSCXSTRHelper() : XSCBaseHelper(_Symbol, _Period) { } // // Deconstructor ... - ~XSCXSTRRHelper() {} + ~XSCXSTRHelper() {} // // Tools ... bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XSTRRInputs &inputs // Inputs + XSTRInputs &inputs // Inputs ) { // @@ -212,14 +212,14 @@ public: // Inputs ... // - XSTRRInputs GetInputs() + XSTRInputs GetInputs() { return mInputs; } // bool SetInputs( - XSTRRInputs &inputs // Configs + XSTRInputs &inputs // Configs ) { // @@ -375,7 +375,7 @@ protected: private: // // Props ... - XSTRRInputs mInputs; // Inputs ... + XSTRInputs mInputs; // Inputs ... // // Buffers ... diff --git a/Helpers/x-saherelm.xtd.helper.mq5 b/Helpers/x-saherelm.xtd.helper.mq5 index 6de4d148..19fb46dc 100644 --- a/Helpers/x-saherelm.xtd.helper.mq5 +++ b/Helpers/x-saherelm.xtd.helper.mq5 @@ -37,7 +37,7 @@ enum ENUM_XTD_BUFFERS // // Input Models ... -struct XXTDInputs +struct XTDInputs { // // Props ... @@ -57,7 +57,7 @@ struct XXTDInputs // // Constructor(s) ... - XXTDInputs() + XTDInputs() { // Clean(); @@ -162,7 +162,7 @@ public: bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XXTDInputs &inputs // Inputs + XTDInputs &inputs // Inputs ) { // @@ -221,14 +221,14 @@ public: // Inputs ... // - XXTDInputs GetInputs() + XTDInputs GetInputs() { return mInputs; } // bool SetInputs( - XXTDInputs &inputs // Configs + XTDInputs &inputs // Configs ) { // @@ -401,7 +401,7 @@ protected: private: // // Props ... - XXTDInputs mInputs; // Inputs ... + XTDInputs mInputs; // Inputs ... // // Buffers ... @@ -452,7 +452,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xtm.helper.mq5 b/Helpers/x-saherelm.xtm.helper.mq5 index cbbb8e90..a55a04b3 100644 --- a/Helpers/x-saherelm.xtm.helper.mq5 +++ b/Helpers/x-saherelm.xtm.helper.mq5 @@ -35,7 +35,7 @@ enum ENUM_XTM_BUFFERS // // Input Models ... -struct XXTMInputs +struct XTMInputs { // // Props ... @@ -51,7 +51,7 @@ struct XXTMInputs // // Constructor(s) ... - XXTMInputs() + XTMInputs() { // Clean(); @@ -142,7 +142,7 @@ public: bool Init( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Period - XXTMInputs &inputs // Inputs + XTMInputs &inputs // Inputs ) { // @@ -197,14 +197,14 @@ public: // Inputs ... // - XXTMInputs GetInputs() + XTMInputs GetInputs() { return mInputs; } // bool SetInputs( - XXTMInputs &inputs // Configs + XTMInputs &inputs // Configs ) { // @@ -277,7 +277,7 @@ protected: private: // // Props ... - XXTMInputs mInputs; // Inputs ... + XTMInputs mInputs; // Inputs ... // // Buffers ... @@ -304,7 +304,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xts.helper.mq5 b/Helpers/x-saherelm.xts.helper.mq5 index 5ec27c29..924c05cd 100644 --- a/Helpers/x-saherelm.xts.helper.mq5 +++ b/Helpers/x-saherelm.xts.helper.mq5 @@ -544,7 +544,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Helpers/x-saherelm.xzg.helper.mq5 b/Helpers/x-saherelm.xzg.helper.mq5 index 097c084e..977135ad 100644 --- a/Helpers/x-saherelm.xzg.helper.mq5 +++ b/Helpers/x-saherelm.xzg.helper.mq5 @@ -521,7 +521,7 @@ private: // ); } -} +}; // // Tools ... \ No newline at end of file diff --git a/Indicators/x-saherelm.xct.mq5 b/Indicators/x-saherelm.xct.mq5 index dbb5011f..25b3b073 100644 --- a/Indicators/x-saherelm.xct.mq5 +++ b/Indicators/x-saherelm.xct.mq5 @@ -114,9 +114,16 @@ void OnDeinit(const int reason) // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value // REASON_CLOSE 9 Terminal closed + // + ulong chID = FindChartID( + _Symbol, + _Period + // + ); + // // Delete Object ... - ObjectDelete(0, ShortName); + ObjectDelete(chID, ShortName); // Comment(""); @@ -125,36 +132,16 @@ void OnDeinit(const int reason) // // Calculating what we want ... int OnCalculate( - // - // total Candles on chart ... - const int rates_total, - // - // total calculated Candles on charts ... - const int prev_calculated, - // - // history of Candles Open Time ... - const datetime &time[], - // - // history of Candles Open Price ... - const double &open[], - // - // history of Candles High Price ... - const double &high[], - // - // history of Candles Low Price ... - const double &low[], - // - // history of Candles Close Price ... - const double &close[], - // - // history of Tick Volumes on Candle ... - const long &tick_volume[], - // - // history of Trade Volumes ... - const long &volume[], - // - // history of Candles Spread Price ... - const int &spread[] // + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... ) { // @@ -166,6 +153,13 @@ int OnCalculate( return rates_total; } + // + ulong chID = FindChartID( + _Symbol, + _Period + // + ); + // XBarRemainsTime barRemains; barRemains.Init( @@ -201,10 +195,10 @@ int OnCalculate( string objText = "Spread: " + IntegerToString(mSpread) + _sp + " Next Bar in: " + msg; // - ObjectSetInteger(0, ShortName, OBJPROP_COLOR, clr); - ObjectSetString(0, ShortName, OBJPROP_TEXT, objText); - ObjectSetInteger(0, ShortName, OBJPROP_FONTSIZE, 10); - ObjectSetString(0, ShortName, OBJPROP_FONT, "Courier"); + ObjectSetInteger(chID, ShortName, OBJPROP_COLOR, clr); + ObjectSetString(chID, ShortName, OBJPROP_TEXT, objText); + ObjectSetInteger(chID, ShortName, OBJPROP_FONTSIZE, 10); + ObjectSetString(chID, ShortName, OBJPROP_FONT, "Courier"); // return rates_total; diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 index f0a644d4..da1eb5c6 100644 --- a/Libraries/x-saherelm.common.lib.mq5 +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -2233,6 +2233,48 @@ struct XMarketCycle return result; } + // + // Find Chart ID ... + ulong GetChartID() + { + // + ulong result = 0; + + // + long firstChart = ChartFirst(); + result = firstChart; + + // + while (result >= 0) + { + // + string chSymbol = ChartSymbol(result); + ENUM_TIMEFRAMES chPeriod = ChartPeriod(result); + + // + bool isOwnChart = + // + symbol == chSymbol && + period == chPeriod + // + ; + if (isOwnChart) + { + break; + } + + // + result = ChartNext(result); + if (result < 0) + { + break; + } + } + + // + return result; + } + // // Create and String Representation for Unique Taging ... string ToString() @@ -2470,6 +2512,43 @@ bool IsRunningOnTestMode() return result; } +// +// Find Chart ID ... +ulong FindChartID( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period +) +{ + // + ulong result = ChartFirst(); + + // + while (result >= 0) + { + // + string chSymbol = ChartSymbol(result); + ENUM_TIMEFRAMES chPeriod = ChartPeriod(result); + + // + bool isOwn = + // + chSymbol == mSymbol && + chPeriod == mPeriod + // + ; + if (isOwn) + { + break; + } + + // + result = ChartNext(result); + } + + // + return result; +} + // // Normalizers ... diff --git a/Libraries/x-saherelm.xtrade.lib.mq5 b/Libraries/x-saherelm.xtrade.lib.mq5 index fda76b6f..2aa189b8 100644 --- a/Libraries/x-saherelm.xtrade.lib.mq5 +++ b/Libraries/x-saherelm.xtrade.lib.mq5 @@ -22,6 +22,7 @@ // // Imports ... #include +#include "../Libraries/x-saherelm.common.lib.mq5" #include "../Classes/x-saherelm.xdata-collector.class.mq5" // @@ -33,10 +34,12 @@ // // Common ... string XIDToken = "ID"; +string XTicketToken = "TK"; string XModeToken = "MD"; string XTypeToken = "TY"; string XPeriodToken = "PR"; string XProviderToken = "PRV"; +string XProfitToken = "PF"; // string XTPToken = "TP"; @@ -50,6 +53,9 @@ string XSymbolToken = "SMBL"; string XSupportToken = "SP"; string XEQMSupportToken = "EQM"; +// +string XActionToken = "A"; + // // Available Order Modes ... enum ENUM_X_ORDER_MODES @@ -81,12 +87,26 @@ enum ENUM_X_SIGNAL_EXECUTION_RESULT // X_SIGNAL_EXECUTION_UNKNOWN, // Unknown X_SIGNAL_EXECUTION_SUCCEED, // Succed + X_SIGNAL_EXECUTION_FAILED_SPREAD, // Spread more than Max Allowed X_SIGNAL_EXECUTION_FAILED_NO_EQUITY, // No Equity for Trade X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR, // Price Error X_SIGNAL_EXECUTION_FAILED_MAX_REACHED, // Max Allowed Positions Reached X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS, // Invalid Params }; +// +// How to Manage Signal TP and SL ... +enum ENUM_X_SIGNAL_MANAGING_ACTIONS +{ + // + X_SIGNAL_USE_NOTHING, // Use 0 index if exists and ignore if not + X_SIGNAL_USE_MAX, // Use Max Value + X_SIGNAL_USE_MIN, // Use Min Value + X_SIGNAL_PARTIAL_CLOSE, // Use Max as Regular but Partial Close at each Step + X_SIGNAL_TRAIL, // Use 0 index as SL and Trail Stop on TP Levels + X_SIGNAL_PARTIAL_TRAIL, // Use 0 index as SL and Trail Stop on TP Levels and also Partial Close on TP Levels +}; + // // Structs ... @@ -106,6 +126,8 @@ struct XSignal datetime time; // Issue Time ... // + ENUM_X_SIGNAL_MANAGING_ACTIONS action; // Signal Managing Action ... + double tps[]; // a Collection of TP(s) ... double sls[]; // a Collection of SL(s) ... @@ -130,6 +152,54 @@ struct XSignal Clean(); } + // + // DO All Calculations and Normalizations ... + bool Normalize() + { + // + bool result = false; + + // + // Normalizations ... + symbol = NormalizeSymbol(symbol); + period = NormalizePeriod(period); + + // + entry = NormalizePrice(entry, symbol); + volume = NormalizeVolume(volume, symbol); + + // + time = NormalizeTime(time); + + // + int slsCount = ArraySize(sls); + if (slsCount > 0) + { + // + for (int i = 0; i < slsCount; i++) + { + sls[i] = NormalizePrice(sls[i], symbol); + } + } + + // + int tpsCount = ArraySize(tps); + if (tpsCount > 0) + { + // + for (int i = 0; i < tpsCount; i++) + { + tps[i] = NormalizePrice(tps[i], symbol); + } + } + + // + result = IsValid(); + + // + return result; + } + // bool Prepare( string mSymbol, // Trading Symbol @@ -162,6 +232,24 @@ struct XSignal return result; } + // + if (tp < 0) + { + tp = 0; + } + + // + if (sl < 0) + { + sl = 0; + } + + // + if (tp == 0 && sl == 0) + { + action = X_SIGNAL_USE_NOTHING; + } + // type = mType; mode = mMode; @@ -195,10 +283,7 @@ struct XSignal ); // - time = TimeCurrent(); - - // - result = IsValid(); + result = Normalize(); // return result; @@ -273,11 +358,10 @@ struct XSignal ) { // - return Prepare( + return PrepareLong( mSymbol, mProvider, mPeriod, - POSITION_TYPE_BUY, X_ORDER_MODE_MARKET, mEntry, mVolume, @@ -299,11 +383,10 @@ struct XSignal ) { // - return Prepare( + return PrepareShort( mSymbol, mProvider, mPeriod, - POSITION_TYPE_SELL, X_ORDER_MODE_MARKET, mEntry, mVolume, @@ -328,11 +411,10 @@ struct XSignal ) { // - return Prepare( + return PrepareLong( mSymbol, mProvider, mPeriod, - POSITION_TYPE_BUY, X_ORDER_MODE_STOP, mEntry, mVolume, @@ -354,11 +436,10 @@ struct XSignal ) { // - return Prepare( + return PrepareShort( mSymbol, mProvider, mPeriod, - POSITION_TYPE_SELL, X_ORDER_MODE_STOP, mEntry, mVolume, @@ -383,11 +464,10 @@ struct XSignal ) { // - return Prepare( + return PrepareLong( mSymbol, mProvider, mPeriod, - POSITION_TYPE_BUY, X_ORDER_MODE_LIMIT, mEntry, mVolume, @@ -409,11 +489,10 @@ struct XSignal ) { // - return Prepare( + return PrepareShort( mSymbol, mProvider, mPeriod, - POSITION_TYPE_SELL, X_ORDER_MODE_LIMIT, mEntry, mVolume, @@ -423,6 +502,102 @@ struct XSignal ); } + // + // here we Can Modify TP and SL and also Action ... + bool Modify( + ENUM_X_SIGNAL_MANAGING_ACTIONS mAction, + double &mTps[], + double &mSls[] + // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + // Only Position Manager works on Market Execution Positions ... + if (mAction != X_SIGNAL_USE_NOTHING && + mode != X_ORDER_MODE_MARKET) + { + return result; + } + + // + int mTpsCount = ArraySize(mTps); + int mSlsCount = ArraySize(mSls); + + // + if (mAction != X_SIGNAL_USE_NOTHING) + { + // + if (mAction == X_SIGNAL_USE_MAX || + mAction == X_SIGNAL_USE_MIN || + mAction == X_SIGNAL_PARTIAL_TRAIL) + { + result = mTpsCount > 0 || mSlsCount > 0; + } + else + { + result = mTpsCount > 0 && mSlsCount > 0; + } + } + + // + if (result) + { + // + double defaultValue = 0; + + // + Copy( + mTps, + tps + // + ); + if (ArraySize(tps) <= 0) + { + // + Add( + defaultValue, + tps + // + ); + } + + // + Copy( + mSls, + sls + // + ); + if (ArraySize(sls) <= 0) + { + // + Add( + defaultValue, + sls + // + ); + } + + // + action = mAction; + + // + result = IsValid(); + } + + // + return result; + } + // // Tools ... @@ -470,6 +645,48 @@ struct XSignal // ; + // + if (!result) + { + return result; + } + + // + // Validate Actions ... + + // + // Only Position Manager works on Market Execution Positions ... + result = + // + !(action != X_SIGNAL_USE_NOTHING && + mode != X_ORDER_MODE_MARKET) + // + ; + if (!result) + { + return result; + } + + // + int tpsCount = ArraySize(tps); + int slsCount = ArraySize(sls); + + // + if (action != X_SIGNAL_USE_NOTHING) + { + // + if (action == X_SIGNAL_USE_MAX || + action == X_SIGNAL_USE_MIN || + action == X_SIGNAL_PARTIAL_TRAIL) + { + result = tpsCount > 0 || slsCount > 0; + } + else + { + result = tpsCount > 0 && slsCount > 0; + } + } + // return result; } @@ -636,42 +853,7 @@ struct XSignal // string GetToken() { - // - string mType = GetTypeName(this); - - // - string result = mType; - - // - string parts[]; - int partsCount = SplitContent( - parts, - result, - " " - // - ); - if (partsCount <= 0) - { - // - result = mType; - return result; - } - - // - bool hasLastPart = GetLastItem( - result, - parts - // - ); - if (!hasLastPart) - { - // - result = mType; - return result; - } - - // - return result; + return GetToken(this); } // @@ -715,6 +897,9 @@ struct XSignal string volumeStr = Surround(XVolumeToken, volume); string timeStr = Surround(XTimeToken, time); + // + string actionStr = Surround(XActionToken, action); + // // TP ... string tpsContentStr = ToString(tps); @@ -739,6 +924,7 @@ struct XSignal positionIdStr + entryStr + volumeStr + + actionStr + tpsStr + slsStr + timeStr + @@ -795,6 +981,9 @@ struct XSignal mode = ((ENUM_X_ORDER_MODES)ParseIntSurrounded(value, XModeToken)); period = ((ENUM_TIMEFRAMES)ParseIntSurrounded(value, XPeriodToken)); + // + action = ((ENUM_X_SIGNAL_MANAGING_ACTIONS)ParseIntSurrounded(value, XActionToken)); + // // TPS ... ParseDoubleArraySurrounded( @@ -821,6 +1010,154 @@ struct XSignal // return result; } + + // + // Select Regular SL ... + bool RegularSL(double &sl) + { + // + bool result = false; + + // + sl = 0; + int slsCount = ArraySize(sls); + + // + result = IsValid() && slsCount > 0; + if (!result) + { + return result; + } + + // + if ( + action == X_SIGNAL_TRAIL || + action == X_SIGNAL_USE_NOTHING || + action == X_SIGNAL_PARTIAL_TRAIL) + { + sl = sls[0]; + } + else if (action == X_SIGNAL_USE_MAX || + action == X_SIGNAL_PARTIAL_CLOSE) + { + sl = GetMin(sls); + } + else if (action == X_SIGNAL_USE_MIN) + { + sl = GetMax(sls); + } + + // + return result; + } + + // + // Select Regular TP ... + bool RegularTP(double &tp) + { + // + bool result = false; + + // + tp = 0; + int tpsCount = ArraySize(tps); + + // + result = IsValid() && tpsCount > 0; + if (!result) + { + return result; + } + + // + if ( + action == X_SIGNAL_TRAIL || + action == X_SIGNAL_USE_NOTHING || + action == X_SIGNAL_PARTIAL_TRAIL) + { + tp = tps[0]; + } + else if (action == X_SIGNAL_USE_MAX || + action == X_SIGNAL_PARTIAL_CLOSE) + { + tp = GetMax(tps); + } + else if (action == X_SIGNAL_USE_MIN) + { + tp = GetMin(tps); + } + + // + return result; + } + + // + // 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; + } }; // @@ -1016,6 +1353,74 @@ struct XPosition return result; } + // + // 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; + } + // // Calculate Age ... int GetAge( @@ -2099,6 +2504,278 @@ struct XPositionPack } }; +// +// Use for Manage Positions ... +struct XPositionInfo +{ + // + // Props ... + ulong ticket; // Position Ticket + + // + + double tps[]; // Un Touched Tps ( not include regular TP ) / For Managing using XTrade Class ... + double sls[]; // Un Touched Sls ( not include regular SL ) / For Managing using XTrade Class ... + + // + ENUM_X_SIGNAL_MANAGING_ACTIONS action; // Managing Action + double profits[]; // Check Postion profit + datetime times[]; // Last Times prfoit Checking + + // + // Constructor ... + void XPositionInfo() + { + Clean(); + } + + // + // Fill from a Signal ... + // The Signal must Executed ... + bool BySignal( + XSignal &signal // the Signal which need to use + ) + { + // + bool result = false; + + // + Clean(); + + // + result = signal.IsValid() && signal.IsExecuted() && signal.mode == X_ORDER_MODE_MARKET; + if (!result) + { + return result; + } + + // + ticket = signal.positionId; + action = signal.action; + + // + // Select TPS and SLS from signal ... + + // + double sl = 0; + bool hasRegularSL = signal.RegularSL(sl); + Copy( + signal.sls, + sls + // + ); + if (hasRegularSL) + { + // + Remove( + sl, + sls + // + ); + } + + // + double tp = 0; + bool hasRegularTP = signal.RegularTP(tp); + Copy( + signal.tps, + tps + // + ); + if (hasRegularTP) + { + // + Remove( + tp, + tps + // + ); + } + + // + return result; + } + + // + // Fill from a Position ... + bool ByPosition( + XPosition &position // the Position which need to use + ) + { + // + bool result = false; + + // + Clean(); + + // + result = position.IsValid(); + if (!result) + { + return result; + } + + // + ticket = position.ticket; + + // + datetime time = TimeCurrent(); + + // + Add( + time, + times + // + ); + Add( + position.profit, + profits + // + ); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + ticket = 0; + + // + Clean(tps); + Clean(sls); + Clean(times); + Clean(profits); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = NotEmpty(ticket) && ticket > 0; + + // + return result; + } + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XPositionInfo &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + ticket == value.ticket + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XPositionInfo &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Retrieve Token ... + string GetToken() + { + return GetToken(this); + } + + // + // Convert to String Representation + string ToString() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string ticketStr = Surround(XTicketToken, ticket); + string actionStr = Surround(XActionToken, action); + // + string tpsStr = SurroundArray(XTPToken, tps); + string slsStr = SurroundArray(XSLToken, sls); + string timesStr = SurroundArray(XTimeToken, times); + string profitsStr = SurroundArray(XProfitToken, profits); + + // + result = + // + GetToken() + "[" + + // + ticketStr + + actionStr + + tpsStr + + slsStr + + timesStr + + profitsStr + + // + "]" + // + ; + + // + return result; + } + + // + // Parse and Fill from Given String Representation + bool Parse(string value) + { + // + bool result = false; + + // + ticket = ParseLongSurrounded(value, XTicketToken); + action = ((ENUM_X_SIGNAL_MANAGING_ACTIONS)ParseIntSurrounded(value, XActionToken)); + + // + ParseDoubleArraySurrounded(tps, value, XTPToken); + ParseDoubleArraySurrounded(sls, value, XSLToken); + ParseDoubleArraySurrounded(profits, value, XProfitToken); + ParseTimeArraySurrounded(times, value, XTimeToken); + + // + result = IsValid(); + + // + return result; + } +}; + // // TypeDefs ... @@ -2244,46 +2921,46 @@ public: // int mResult = 0; - // // - // XSignal signals[]; - // int signalsCount = Collect(signals); - // if (signalsCount <= 0) - // { - // return mResult; - // } + // + XSignal signals[]; + int signalsCount = Collect(signals); + if (signalsCount <= 0) + { + return mResult; + } - // // - // mResult = ArraySize(result); + // + mResult = ArraySize(result); - // // - // // Now we Have to Apply Filters ... - // for (int i = 0; i < signalsCount; i++) - // { - // // - // XSignal iSignal = signals[i]; + // + // Now we Have to Apply Filters ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; - // // // - // // bool isFiltersPassed = - // // iSignal.IsFilteresPassed( - // // symbol, - // // provider, - // // period, - // // type, - // // mode - // // // - // // ); - // // if (!isFiltersPassed) - // // { - // // continue; - // // } + // + bool isFiltersPassed = + iSignal.IsFiltersPassed( + symbol, + provider, + period, + type, + mode + // + ); + if (!isFiltersPassed) + { + continue; + } - // // // - // // AddRef( - // // iPosition, - // // result - // // // - // // ); - // } + // + AddRef( + iSignal, + result + // + ); + } // return mResult; @@ -2305,6 +2982,132 @@ private: // Tools ... }; +// +// Create a Position Info Data Collector ... +class XSCPositionInfoCollector +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor ... + void XSCPositionInfoCollector() + { + // + XSCDataCollector mBase; + mBase.Clear(); + } + + // + // Deconstructor ... + + // + // Tools ... + + // + // Inheritanced Functions ... + + // + // Cleaning Store ... + void Clear() + { + // + XSCDataCollector mBase; + + // + mBase.Clear(); + } + + // + // Collect All Store ... + int Collect(XPositionInfo &result[]) + { + // + int mResult = 0; + + // + XSCDataCollector mBase; + + // + mResult = mBase.Collect(result); + + // + return mResult; + } + + // + // Add Item To Store ... + bool Add(XPositionInfo &item) + { + // + bool result = false; + + // + XSCDataCollector mBase; + + // + result = mBase.Add(item); + + // + return result; + } + + // + // Add Item(s) To Store ... + int Add(XPositionInfo &items[]) + { + // + int result = 0; + + // + XSCDataCollector mBase; + + // + result = mBase.Add(items); + + // + return result; + } + + // + // Remove an Item from Store ... + bool Remove(XPositionInfo &item) + { + // + bool result = false; + + // + XSCDataCollector mBase; + + // + result = mBase.Remove(item); + + // + return result; + } + + // + // Custom Functions ... + + // + // Protected ... +protected: + // + // Tools ... + + // + // Private ... +private: + // + // Props ... + + // + // Tools ... +}; + // // Tools ...