/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // -------------------------------------- // Name: XClass // Description: provides all classes for use ... // // // 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 // #include #include #include #include #include #include "x-saherelm.models.lib.mq5" // // END Model Definitions ... // // // START Global Definitions: Variables, Properties and etc ... // // // XSaherElm Trade Class ... class XCTrade { // // all public features ... public: // // Constructor ... void XCTrade( string symbol, int slippage, ulong magicNumber) { // mSymbol = symbol; mSlippage = slippage; mMagicNumber = magicNumber; // mTrader = new CTrade(); // mTrader.SetAsyncMode(false); mTrader.SetDeviationInPoints(mSlippage); mTrader.SetExpertMagicNumber(mMagicNumber); } // // Deconstructor ... void ~XCTrade() { } // // Count Open Positions ... int Count() { // int result = 0; // int total = PositionsTotal(); for (int i = 0; i < total; i++) { // if (!mPositionInfo.SelectByIndex(i)) { continue; } // if (mPositionInfo.Magic() != mMagicNumber) { continue; } // if (mPositionInfo.Symbol() != mSymbol) { continue; } // result++; } // return result; } // // Count Longs ... int CountLongs() { int result = CountByType(X_SIGNAL_LONG); return result; } // // Count Shorts ... int CountShorts() { int result = CountByType(X_SIGNAL_SHORT); return result; } // // Count By Type ... int CountByType(ENUM_X_SIGNAL_TYPE type) { // // Validate Args ... ENUM_POSITION_TYPE mType = POSITION_TYPE_BUY; if (type == X_SIGNAL_LONG) { mType = POSITION_TYPE_BUY; } else if (type == X_SIGNAL_SHORT) { mType = POSITION_TYPE_SELL; } // int result = CountByType(mType); return result; } // // Retrieve all Positions ... void GetAllPositions(XSignal &result[]) { // ArrayFree(result); // int total = Count(); ArrayResize(result, total); // int filledIndex = 0; int totalPositions = PositionsTotal(); for (int i = 0; i < totalPositions; i++) { // if (!mPositionInfo.SelectByIndex(i)) { continue; } // if (mPositionInfo.Magic() != mMagicNumber) { continue; } // if (mPositionInfo.Symbol() != mSymbol) { continue; } // result[filledIndex] = PositionToSignal(i); filledIndex++; } } // // Retrieve all Long Positions ... void GetLongPositions(XSignal &result[]) { GetAllPositionsByType(POSITION_TYPE_BUY, result); } // // Retrieve all Short Positions ... void GetShortPositions(XSignal &result[]) { GetAllPositionsByType(POSITION_TYPE_SELL, result); } // // Get All Trades Which Candle Passed after Open ... void GetLongTimeTrades( int life, // Max Candle Passed after Trades Open ENUM_TIMEFRAMES period, // Calculate Candles based on time frame XSignal &result[] // Holds Result ) { // ArrayFree(result); ArrayResize(result, 0); // // Normalize Period ... if (period == EMPTY_VALUE) { period = _Period; } // XSignal positions[]; GetAllPositions(positions); int count = ArraySize(positions); if (count <= 0) { return; } // // Current Time Frame Candle Index ... int currentBarIndex = 0; // // Loop through Positions ... for (int i = 0; i < count; i++) { // XSignal trade = positions[i]; // // Retrieve Trade Open Bar Index based on Current Period ... int tradeOpenBarIndex = iBarShift( mSymbol, period, trade.time); // // Calculate Trade Life ... int diff = MathAbs(currentBarIndex - tradeOpenBarIndex); if (diff >= life) { // ArrayResize( result, ArraySize(result) + 1); result[ArraySize(result) - 1] = trade; } } } // // Get In DrawDown Trades ... void GetInDrawDownTrades( double maxDrawDown, // Maximum DrawDown which trades going to close if bigger than or equal it ENUM_X_SIGNAL_TYPE type, // specify trades type to close, if none all tardes which in max drawdown was closed XSignal &result[] // Holds Result ) { // ArrayFree(result); ArrayResize(result, 0); // // Validate Args ... if (maxDrawDown <= 0) { return; } // XSignal trades[]; // // Retrieve Signals ... if ( type == X_SIGNAL_UNKNOWN || (type != X_SIGNAL_LONG && type != X_SIGNAL_SHORT)) { GetAllPositions(trades); } else if (type == X_SIGNAL_LONG) { GetLongPositions(trades); } else if (type == X_SIGNAL_SHORT) { GetShortPositions(trades); } // // Check Trades Count ... int count = ArraySize(trades); if (count <= 0) { return; } // // Loop through all retrieved trades ... for (int i = 0; i < count; i++) { // XSignal trade = trades[i]; if (trade.profit > 0) { continue; } // bool isPassed = (-1 * trade.profit) >= maxDrawDown; if (isPassed) { // ArrayResize( result, ArraySize(result) + 1); result[ArraySize(result) - 1] = trade; } } } // // Get In Profit Trades ... void GetInProfitTrades( double minProfit, // Minimum Profit To Close Trades ENUM_X_SIGNAL_TYPE type, // specify trades type to close, if none all tardes which in max drawdown was closed XSignal &result[] // Holds Result ) { // ArrayFree(result); ArrayResize(result, 0); // XSignal trades[]; // // Retrieve Signals ... if ( type == X_SIGNAL_UNKNOWN || (type != X_SIGNAL_LONG && type != X_SIGNAL_SHORT)) { GetAllPositions(trades); } else if (type == X_SIGNAL_LONG) { GetLongPositions(trades); } else if (type == X_SIGNAL_SHORT) { GetShortPositions(trades); } // // Check Trades Count ... int count = ArraySize(trades); if (count <= 0) { return; } // // Loop through all retrieved trades ... for (int i = 0; i < count; i++) { // XSignal trade = trades[i]; if (trade.profit < 0) { continue; } // bool isPassed = minProfit <= 0 ? true : trade.profit >= minProfit; if (isPassed) { // ArrayResize( result, ArraySize(result) + 1); result[ArraySize(result) - 1] = trade; } } } // // Open a Buy/Long Position ... bool Buy( double volume, // position volume double price, // execution price double sl = 0, // stop loss price double tp = 0, // take profit price const string comment = "" // comment ) { // bool result = false; // result = mTrader.Buy( volume, mSymbol, price, sl, tp, comment); // return result; } // // Open a Sell/Short Position ... bool Sell( double volume, // position volume double price, // execution price double sl = 0, // stop loss price double tp = 0, // take profit price const string comment = "" // comment ) { // bool result = false; // result = mTrader.Sell( volume, mSymbol, price, sl, tp, comment); // return result; } // // Validate Signal ... bool ValidateSignal(XSignal &signal) { // bool result = false; // // Validate Signal Type ... result = signal.type != X_SIGNAL_UNKNOWN; if (!result) { return result; } // // Check Symbol ... result = StringLen(signal.symbol) == 0 ? true : signal.symbol == mSymbol; if (!result) { return result; } // // Check magic number ... result = signal.magicNumber <= 0 ? true : signal.magicNumber == mMagicNumber; if (!result) { return result; } // // Check Entry ... result = signal.entry > 0; if (!result) { return result; } // // Check SL ... result = signal.sl == 0 ? true : signal.type == X_SIGNAL_LONG ? signal.sl < signal.entry : signal.sl > signal.entry; if (!result) { return result; } // // Check TP ... result = signal.tp == 0 ? true : signal.type == X_SIGNAL_LONG ? signal.tp > signal.entry : signal.tp < signal.entry; if (!result) { return result; } // // Check Volume ... result = signal.volume > 0; if (!result) { return result; } // // Check Time ... result = signal.time > 0; if (!result) { return result; } // return result; } // // Execute an Specific XSignal instance ... bool ExecuteSignal(XSignal &signal) { // bool result = ValidateSignal(signal); if (!result) { return result; } // signal.symbol = mSymbol; // result = signal.type == X_SIGNAL_LONG ? Buy( signal.volume, signal.entry, signal.sl, signal.tp, signal.comment) : signal.type == X_SIGNAL_SHORT ? Sell( signal.volume, signal.entry, signal.sl, signal.tp, signal.comment) : false; // return result; } // // Modify Position ... bool Modify( const ulong ticket, // position ticket double sl = 0, // stop loss price double tp = 0 // take profit ) { // bool result = false; // // Validate Args ... if (tp <= 0 && sl <= 0) { result = false; return result; } // result = mTrader.PositionModify( ticket, sl, tp); // return result; } // // Close Position By Ticket ... bool Close(ulong ticket) { // bool result = false; // // Try to Select Position ... if (!mPositionInfo.SelectByTicket(ticket)) { // result = false; return result; } // result = mTrader.PositionClose(ticket); // return result; } // // Close Partial By Ticket ... bool ClosePartial(ulong ticket, double volume) { // bool result = false; // if (!mPositionInfo.SelectByTicket(ticket)) { // result = false; return result; } // mTrader.PositionClosePartial( ticket, volume); // return result; } // // Close All Positions ... void CloseAllPositions( XSignal &closed[] // holds Closed Positions ) { // ArrayFree(closed); ArrayResize(closed, 0); // // Count all Specified Positions ... int total = Count(); if (total <= 0) { return; } // XSignal allPositions[]; GetAllPositions(allPositions); // int allPositionsSize = ArraySize(allPositions); if (allPositionsSize == 0 || allPositionsSize != total) { return; } // for (int i = 0; i < total; i++) { // XSignal signal = allPositions[i]; bool isClosed = Close(signal.ticket); if (isClosed) { // ArrayResize( closed, ArraySize(closed) + 1); closed[ArraySize(closed) - 1] = signal; } } } // // Close All Longs Positions ... void CloseLongPositions( XSignal &closed[] // holds Closed Positions ) { // ArrayFree(closed); ArrayResize(closed, 0); // // Count all Specified Positions ... int total = CountLongs(); if (total <= 0) { return; } // XSignal longPositions[]; GetLongPositions(longPositions); // int longPositionsSize = ArraySize(longPositions); if (longPositionsSize == 0 || longPositionsSize != total) { return; } // for (int i = 0; i < total; i++) { // XSignal signal = longPositions[i]; bool isClosed = Close(signal.ticket); if (isClosed) { // ArrayResize( closed, ArraySize(closed) + 1); closed[ArraySize(closed) - 1] = signal; } } } // // Close All Shorts Positions ... void CloseShortPositions( XSignal &closed[] // holds Closed Positions ) { // ArrayFree(closed); ArrayResize(closed, 0); // // Count all Specified Positions ... int total = CountShorts(); if (total <= 0) { return; } // XSignal shortPositions[]; GetShortPositions(shortPositions); // int shortPositionsSize = ArraySize(shortPositions); if (shortPositionsSize == 0 || shortPositionsSize != total) { return; } // for (int i = 0; i < total; i++) { // XSignal signal = shortPositions[i]; bool isClosed = Close(signal.ticket); if (isClosed) { // ArrayResize( closed, ArraySize(closed) + 1); closed[ArraySize(closed) - 1] = signal; } } } // // Close All Trades Which Candle Passed after Open ... void CloseLongTimeTrades( int life, // Max Candle Passed after Trades Open ENUM_TIMEFRAMES period, // Calculate Candles based on time frame XSignal &closed[] // holds Closed Trades ... ) { // ArrayFree(closed); ArrayResize(closed, 0); // // Normalize Period ... if (period == EMPTY_VALUE) { period = _Period; } // XSignal positions[]; GetAllPositions(positions); int count = ArraySize(positions); if (count <= 0) { return; } // // Current Time Frame Candle Index ... int currentBarIndex = 0; // // Loop through Positions ... for (int i = 0; i < count; i++) { // XSignal trade = positions[i]; // // Retrieve Trade Open Bar Index based on Current Period ... int tradeOpenBarIndex = iBarShift( mSymbol, period, trade.time); // // Calculate Trade Life ... int diff = MathAbs(currentBarIndex - tradeOpenBarIndex); if (diff >= life) { bool isClosed = Close(trade.ticket); if (isClosed) { // ArrayResize( closed, ArraySize(closed) + 1); closed[ArraySize(closed) - 1] = trade; } } } } // // Close In DrawDown Trades ... void CloseInDrawDownTrades( double maxDrawDown, // Maximum DrawDown which trades going to close if bigger than or equal it ENUM_X_SIGNAL_TYPE type, // specify trades type to close, if none all tardes which in max drawdown was closed XSignal &closed[] // holds Closed Trades ... ) { // ArrayFree(closed); ArrayResize(closed, 0); // // Validate Args ... if (maxDrawDown <= 0) { return; } // XSignal trades[]; // // Retrieve Signals ... if ( type == X_SIGNAL_UNKNOWN || (type != X_SIGNAL_LONG && type != X_SIGNAL_SHORT)) { GetAllPositions(trades); } else if (type == X_SIGNAL_LONG) { GetLongPositions(trades); } else if (type == X_SIGNAL_SHORT) { GetShortPositions(trades); } // // Check Trades Count ... int count = ArraySize(trades); if (count <= 0) { return; } // // Loop through all retrieved trades ... for (int i = 0; i < count; i++) { // XSignal trade = trades[i]; if (trade.profit > 0) { continue; } // bool isPassed = (-1 * trade.profit) >= maxDrawDown; if (isPassed) { // bool isClosed = Close(trade.ticket); if (isClosed) { // ArrayResize( closed, ArraySize(closed) + 1); closed[ArraySize(closed) - 1] = trade; } } } } // // Close All In Profit Trades ... void CloseInProfitTrades( double minProfit, // Minimum Profit To Close Trades ENUM_X_SIGNAL_TYPE type, // specify trades type to close, if none all tardes which in max drawdown was closed XSignal &closed[] // holds Closed Trades ... ) { // ArrayFree(closed); ArrayResize(closed, 0); // XSignal trades[]; // // Retrieve Signals ... if ( type == X_SIGNAL_UNKNOWN || (type != X_SIGNAL_LONG && type != X_SIGNAL_SHORT)) { GetAllPositions(trades); } else if (type == X_SIGNAL_LONG) { GetLongPositions(trades); } else if (type == X_SIGNAL_SHORT) { GetShortPositions(trades); } // // Check Trades Count ... int count = ArraySize(trades); if (count <= 0) { return; } // // Loop through all retrieved trades ... for (int i = 0; i < count; i++) { // XSignal trade = trades[i]; if (trade.profit < 0) { continue; } // bool isPassed = minProfit <= 0 ? true : trade.profit >= minProfit; if (isPassed) { // bool isClosed = Close(trade.ticket); if (isClosed) { // ArrayResize( closed, ArraySize(closed) + 1); closed[ArraySize(closed) - 1] = trade; } } } } // // all protected features ... protected: // // all private features ... private: // // which Symbol ... string mSymbol; // // using deviation, it must be in Point ... int mSlippage; // // using magic number ... ulong mMagicNumber; // // using CTrade instance ... CTrade mTrader; // // using PositionInfo instance ... CPositionInfo mPositionInfo; // // using OrderInfo instance ... COrderInfo mPendingInfo; // // using HistoryOrderInfo instance ... CHistoryOrderInfo mHistoryInfo; // // Count Specific Type Of Positions ... int CountByType(ENUM_POSITION_TYPE type) { // int result = 0; // int total = PositionsTotal(); for (int i = 0; i < total; i++) { // if (!mPositionInfo.SelectByIndex(i)) { continue; } // if (mPositionInfo.Symbol() != mSymbol) { continue; } // if (mPositionInfo.PositionType() != type) { continue; } // result++; } // return result; } // // Convert Position to Signal by Index ... XSignal PositionToSignal(int index) { // XSignal result = {}; // if (!mPositionInfo.SelectByIndex(index)) { return result; } // // ID ... result.id = mPositionInfo.Identifier(); // // Symbol ... result.symbol = mPositionInfo.Symbol(); // // Type ... ENUM_POSITION_TYPE pType = (ENUM_POSITION_TYPE)mPositionInfo.PositionType(); ENUM_X_SIGNAL_TYPE type = pType == POSITION_TYPE_BUY ? X_SIGNAL_LONG : X_SIGNAL_SHORT; result.type = type; // // MagicNumber ... result.magicNumber = mPositionInfo.Magic(); // // Ticket ... result.ticket = mPositionInfo.Ticket(); // // Entry/Open Price ... result.entry = mPositionInfo.PriceOpen(); // // Take Profit ... result.tp = mPositionInfo.TakeProfit(); // // Stop Loss ... result.sl = mPositionInfo.StopLoss(); // // Profit ... result.profit = mPositionInfo.Profit(); // // Time ... result.time = mPositionInfo.Time(); // // Volume ... result.volume = mPositionInfo.Volume(); // // Comment ... result.comment = mPositionInfo.Comment(); // return result; } // // Convert Position to Signal by Index ... XSignal OrderToSignal(int index) { // XSignal result = {}; // if (!mHistoryInfo.SelectByIndex(index)) { return result; } // // ID ... result.id = mHistoryInfo.PositionId(); // // Symbol ... result.symbol = mHistoryInfo.Symbol(); // // Type ... ENUM_ORDER_TYPE pType = (ENUM_ORDER_TYPE)mHistoryInfo.OrderType(); ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN; switch (pType) { // case ORDER_TYPE_BUY: case ORDER_TYPE_BUY_LIMIT: case ORDER_TYPE_BUY_STOP: case ORDER_TYPE_BUY_STOP_LIMIT: type = X_SIGNAL_LONG; break; // case ORDER_TYPE_SELL: case ORDER_TYPE_SELL_LIMIT: case ORDER_TYPE_SELL_STOP: case ORDER_TYPE_SELL_STOP_LIMIT: type = X_SIGNAL_SHORT; break; // // Default ... default: type = X_SIGNAL_UNKNOWN; break; } result.type = type; // // MagicNumber ... result.magicNumber = mHistoryInfo.Magic(); // // Ticket ... result.ticket = mHistoryInfo.Ticket(); // // Entry/Open Price ... result.entry = mHistoryInfo.PriceOpen(); // // Take Profit ... result.tp = mHistoryInfo.TakeProfit(); // // Stop Loss ... result.sl = mHistoryInfo.StopLoss(); // // Profit ... // TODO Calculate it ... // result.profit = mHistoryInfo.Profit(); // // // // Time ... // result.time = mHistoryInfo.Time(); // // // // Volume ... // result.volume = mHistoryInfo.Volume(); // // Comment ... result.comment = mHistoryInfo.Comment(); // return result; } // // Get all Positions based on Position Type ... void GetAllPositionsByType(ENUM_POSITION_TYPE type, XSignal &result[]) { // int existsTotal = CountByType(type); // ArrayFree(result); ArrayResize(result, existsTotal); // int filledIndex = 0; int total = PositionsTotal(); for (int i = 0; i < total; i++) { // if (!mPositionInfo.SelectByIndex(i)) { continue; } // if (mPositionInfo.Magic() != mMagicNumber) { continue; } // if (mPositionInfo.Symbol() != mSymbol) { continue; } // if (mPositionInfo.PositionType() != type) { continue; } // result[filledIndex] = PositionToSignal(i); filledIndex++; } } }; // // XSaherElm Account Info Class ... class XCAccountInfo { // // Public properties ... public: // // Constructro ... void XCAccountInfo() { // mAccountInfo = new CAccountInfo(); // mInitialBalance = mAccountInfo.Balance(); } // // Deconstructor ... void ~XCAccountInfo() { // mInitialBalance = 0; } // // 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) ... ENUM_ACCOUNT_TRADE_MODE GetTradeMode() { return mAccountInfo.TradeMode(); } // // Get Account Balance ... double GetBalance() { return mAccountInfo.Balance(); } // // Get Initial Deposit Balance ... double GetInitialBalance() { return mInitialBalance; } // // 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; } // // Protected properties ... protected: // // Private properties ... private: // // Initial Account Balance ... double mInitialBalance; // // Account Info ... CAccountInfo mAccountInfo; }; // // END Global Definitions: Variables, Properties and etc ... //