/////////////////////////////////////////////////////// // // 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 "x-saherelm.draw.lib.mq5" #include "x-saherelm.models.lib.mq5" #include "x-saherelm.common.lib.mq5" #include // // START Model Definitions ... // // // END Model Definitions ... // // // START Overrides ... // class XSCTrade : public CTrade { public: // // Specific Position Close ... bool PositionClose( const ulong ticket, // Position Ticket const ulong deviation, // Deviation const string comment // Comment For Close ) { // bool result = false; // // check stopped ... if (IsStopped(__FUNCTION__)) { return result; } // // check position existence if (!PositionSelectByTicket(ticket)) { return result; } // string symbol = PositionGetString(POSITION_SYMBOL); // // Clean ... ClearStructures(); // // Check Position Type ... // BUY / LONG ... 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); } // // SELL / Short ... else { // // Prepare Request for Close SELL Position ... m_request.type = ORDER_TYPE_BUY; m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); } // // Setting Request Fields ... m_request.symbol = symbol; m_request.magic = m_magic; m_request.position = ticket; m_request.action = TRADE_ACTION_DEAL; m_request.volume = PositionGetDouble(POSITION_VOLUME); m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; // // Specify Comment ... m_request.comment = comment; // PositionGetString(POSITION_COMMENT); // "Comment anything"; // // Log Info on Screen ... PrintFormat("PositionClose #%I64d %s %.2f", ticket, EnumToString((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)), m_request.volume); // // Close Position ... result = (OrderSend(m_request, m_result)); // return result; } // // Specific Position Close ... bool PositionClose( const ulong ticket, // Position Ticket const string comment = "" // Comment For Close ) { // bool result = false; // // check stopped ... if (IsStopped(__FUNCTION__)) { return result; } // // check position existence if (!PositionSelectByTicket(ticket)) { return result; } // string symbol = PositionGetString(POSITION_SYMBOL); // // Clean ... ClearStructures(); // // Check Position Type ... // BUY / LONG ... 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); } // // SELL / Short ... else { // // Prepare Request for Close SELL Position ... m_request.type = ORDER_TYPE_BUY; m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); } // // Setting Request Fields ... m_request.symbol = symbol; m_request.magic = m_magic; m_request.position = ticket; m_request.deviation = m_deviation; m_request.action = TRADE_ACTION_DEAL; m_request.volume = PositionGetDouble(POSITION_VOLUME); // // Specify Comment ... m_request.comment = comment; // PositionGetString(POSITION_COMMENT); // "Comment anything"; // // Log Info on Screen ... PrintFormat("PositionClose #%I64d %s %.2f", ticket, EnumToString((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)), m_request.volume); // // Close Position ... result = (OrderSend(m_request, m_result)); // return result; } }; // // END Overrides ... // // // 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; }; // // START Global Definitions: Variables, Properties and etc ... // // // XSaherElm Trade Class ... class XCTrade { // // all public features ... public: // // Constructor ... void XCTrade( string tag, // Specify a Tag for Trader instance string symbol, // Specify Trader Symbol int slippage, // Specify Slippage ulong magicNumber, // Specify Magic Number int maxAllowedTrades, // Specify Max Allowed Trades int maxAllowedSupportTrades, // Specify Max Allowed Support Trades for each Trade double minTradeProfitsInPips, // Minimum Profit of each Trade in Pips double supportTradesPriceDistanceInPips, // Support Trades Price Distance in Pips double minAllowedFreeMarginForOpenTrades, // Minimum Free Marging for Open Trades double minBallanceForOpenTrades // Minimum Balance for Open Trades ) { // mTag = tag; mSymbol = symbol; mSlippage = slippage; mMagicNumber = magicNumber; mMaxAllowedTrades = maxAllowedTrades; mMinTradeProfitsInPips = minTradeProfitsInPips; mMaxAllowedSupportTrades = maxAllowedSupportTrades; mMinBallanceForOpenTrades = minBallanceForOpenTrades; mSupportTradesPriceDistanceInPips = supportTradesPriceDistanceInPips; mMinAllowedFreeMarginForOpenTrades = minAllowedFreeMarginForOpenTrades; // mTrader = new XSCTrade(); // 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; } // // Count By Type and Kind ... int CountByKind( ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions ENUM_X_SIGNAL_KIND kind // Specify Kind of Positions ) { // int result = 0; // XSignal trades[]; GetPositionsByKind( type, kind, trades); // result = ArraySize(trades); // return result; } // // Retrieve all Positions ... void GetAllPositions(XSignal &result[]) { // CleanBuffer(result); // 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; } // // Position to Signal ... XSignal signal = PositionToSignal(i); Add( signal, result); } } // // 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 Positions by Specified Type ... void GetPositionsByType( ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions XSignal &result[] // Holds Result ... ) { // CleanBuffer(result); // switch (type) { // case X_SIGNAL_LONG: GetLongPositions(result); break; // case X_SIGNAL_SHORT: GetShortPositions(result); break; // case X_SIGNAL_UNKNOWN: default: GetAllPositions(result); break; } } // // Get Positions by Specified Type and Kind ... void GetPositionsByKind( ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions XSignal &result[] // Holds Result ... ) { // CleanBuffer(result); // XSignal trades[]; switch (type) { // case X_SIGNAL_LONG: GetLongPositions(trades); break; // case X_SIGNAL_SHORT: GetShortPositions(trades); break; // case X_SIGNAL_UNKNOWN: default: GetAllPositions(trades); break; } // int count = ArraySize(trades); if (count <= 0) { return; } // for (int i = 0; i < count; i++) { // XSignal trade = trades[i]; if (trade.kind != kind) { continue; } // Add( trade, 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 ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions XSignal &result[] // Holds Result ) { // CleanBuffer(result); // // Normalize Period ... if (period == EMPTY_VALUE) { period = _Period; } // XSignal positions[]; GetPositionsByKind( type, kind, 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) { // Add( trade, result); } } } // // Get In DrawDown Trades ... void GetInDrawDownTrades( double maxDrawDown, // Maximum DrawDown of Trades ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions XSignal &result[] // Holds Result ) { // CleanBuffer(result); // // Validate Args ... if (maxDrawDown <= 0) { maxDrawDown = 0; } // XSignal trades[]; // // Retrieve Signals ... GetPositionsByKind( type, kind, 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 = maxDrawDown == 0 ? true : (-1 * trade.profit) >= maxDrawDown; if (isPassed) { // Add( trade, result); } } } // // Get In Profit Trades ... void GetInProfitTrades( double minProfit, // Minimum Profit To Close Trades ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions XSignal &result[] // Holds Result ) { // CleanBuffer(result); // XSignal trades[]; GetPositionsByKind( type, kind, result); // // 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) { // Add( trade, result); } } } // // Filter Trades by Searching Comments ... void FilterTrades( string query, // Search String ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions XSignal &result[] // Holds Result ) { // // Free Buffer ... CleanBuffer(result); // XSignal source[]; GetPositionsByKind( type, kind, source); int sourceCount = ArraySize(source); // if (sourceCount <= 0) { return; } // // Do Filtering Signals ... FilterSignals( query, source, result); } // // Filter In DrawDown Trades by Searching Comments ... void FilterInDrawDowntTrades( string query, // Search String double maxDrawDown, // Maximum DrawDown of Trades ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions XSignal &result[] // Holds Result ) { // // Free Buffer ... CleanBuffer(result); // XSignal source[]; GetInDrawDownTrades( maxDrawDown, type, kind, source); int sourceCount = ArraySize(source); // if (sourceCount <= 0) { return; } // // Do Filtering Signals ... FilterSignals( query, source, result); } // // Filter In DrawDown Trades by Searching Comments ... void FilterInProfitTrades( string query, // Search String double minProfit, // Minimum Profit of Trades ENUM_X_SIGNAL_TYPE type, // Specify trades type to act ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions XSignal &result[] // Holds Result ) { // // Free Buffer ... CleanBuffer(result); // XSignal source[]; GetInProfitTrades( minProfit, type, kind, source); int sourceCount = ArraySize(source); // if (sourceCount <= 0) { return; } // // Do Filtering Signals ... FilterSignals( query, source, result); } // // Filter Trades by Searching Comments ... void FilterTrades( string query, // Search String XSignal &source[], // Source Buffer to Filter XSignal &result[] // Holds Result ) { // // Free Buffer ... CleanBuffer(result); // // Do Filtering Signals ... FilterSignals( query, source, result); } // // Force 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; } // // Force 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, // Specify Signal for Execution int &error // Error code if Happens ) { // bool result = ValidateSignal(signal); if (!result) { // error = X_INVALID_SIGNAL_ERROR; return result; } // signal.symbol = mSymbol; // bool isTrade = signal.kind == X_KIND_TRADE; // int kindCount = CountByKind( signal.type, signal.kind); // // Check Account Balance ... result = IsAccountBalanceReadyForTrade(); if (!result) { // error = X_XTRADER_NOT_ENOUGH_BALANCE_ERROR; return result; } // // Check Account Free Margin ... result = IsFreeMarginReadyForTrade(); if (!result) { // error = X_XTRADER_NOT_ENOUGH_MARIGIN_ERROR; return result; } // // Check Trade Count ... result = isTrade ? // mMaxAllowedTrades <= 0 ? // true : // kindCount < mMaxAllowedTrades : // mMaxAllowedSupportTrades <= 0 ? // true : // kindCount < mMaxAllowedSupportTrades // ; if (!result) { // error = isTrade ? X_XTRADER_MAX_ALLOWED_TRADE_KIND_REACHED_ERROR : X_XTRADER_MAX_ALLOWED_SUPPORT_KIND_REACHED_ERROR; return result; } // 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; // if (result) { // error = X_SUCCEED_EXECUTION; // ulong positionTicket = 0; if (mPositionInfo.SelectByIndex(PositionsTotal() - 1)) { positionTicket = mPositionInfo.Ticket(); } // signal.id = positionTicket; signal.ticket = positionTicket; // // Draw Signal On Chart ... DrawSignal(signal); } else { error = X_UNKNOWN_ERROR; } // return result; } // // Virtual TP and SL Handler ... void HandleVirtualTPSL( ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions XSignal &takeProfits[], // Holds all Take Profit Executed Signals XSignal &stopLosses[] // Holds all Stop Loss Executed Signals ) { // CleanBuffer(takeProfits); CleanBuffer(stopLosses); // XSignal trades[]; GetPositionsByKind( type, kind, trades); int count = ArraySize(trades); if (count <= 0) { return; } // // Loop ... for (int i = 0; i < count; i++) { // XSignal trade = trades[i]; // if (trade.virtualTP <= 0 && trade.virtualSL <= 0) { continue; } // double exitPrice = GetExit(trade.type); bool isLong = trade.type == X_SIGNAL_LONG; // // Handle Take Profits ... if (trade.virtualTP > 0) { // bool isPriceReached = isLong ? exitPrice >= trade.virtualTP : exitPrice <= trade.virtualTP; if (isPriceReached) { // string comment = GetSignalClosedOnTPComment(trade); bool isClosed = Close( trade.ticket, comment); if (isClosed) { Add( trade, takeProfits); } } } // // Handle Stop Losses ... if (trade.virtualSL > 0) { // bool isPriceReached = isLong ? exitPrice <= trade.virtualSL : exitPrice >= trade.virtualSL; if (isPriceReached) { // string comment = GetSignalClosedOnSLComment(trade); bool isClosed = Close( trade.ticket, comment); if (isClosed) { Add( trade, stopLosses); } } } } } void HandleVirtualTPSL( XSignal &takeProfits[], // Holds all Take Profit Executed Signals XSignal &stopLosses[] // Holds all Stop Loss Executed Signals ) { // CleanBuffer(takeProfits); CleanBuffer(stopLosses); // XSignal tradesTP[]; XSignal tradesSL[]; HandleVirtualTPSL( X_SIGNAL_UNKNOWN, X_KIND_TRADE, tradesTP, tradesSL); // XSignal supportsTP[]; XSignal supportsSL[]; HandleVirtualTPSL( X_SIGNAL_UNKNOWN, X_KIND_SUPPORT, supportsTP, supportsSL); // // TPs ... int tradesTPCount = ArraySize(tradesTP); if (tradesTPCount > 0) { // // Loop ... for (int i = 0; i < tradesTPCount; i++) { // XSignal fTrade = tradesTP[i]; // Add( fTrade, takeProfits); } } // // SLs ... int tradesSLCount = ArraySize(tradesSL); if (tradesSLCount > 0) { // // Loop ... for (int i = 0; i < tradesSLCount; i++) { // XSignal fTrade = tradesSL[i]; // Add( fTrade, stopLosses); } } // // TPs ... int supportsTPCount = ArraySize(supportsTP); if (supportsTPCount > 0) { // // Loop ... for (int i = 0; i < supportsTPCount; i++) { // XSignal fTrade = supportsTP[i]; // Add( fTrade, takeProfits); } } // // SLs ... int supportsSLCount = ArraySize(supportsSL); if (supportsSLCount > 0) { // // Loop ... for (int i = 0; i < supportsSLCount; i++) { // XSignal fTrade = supportsSL[i]; // Add( fTrade, stopLosses); } } } // // 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, // Position Ticket string comment // Close Position By Specific Comment ) { // bool result = false; // // Try to Select Position ... if (!mPositionInfo.SelectByTicket(ticket)) { return result; } // // Close Position By Specific Comment ... result = mTrader.PositionClose( ticket, comment); if (result) { RemoveSignal(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; } // // Partial Close all Reached Signals ... void RiskFreeSignals( ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions XSignal &riskFrees[] // Holds all Executed Signals ) { // CleanBuffer(riskFrees); // XSignal trades[]; GetPositionsByKind( type, kind, trades); int count = ArraySize(trades); if (count <= 0) { return; } // // Loop ... for (int i = 0; i < count; i++) { // XSignal trade = trades[i]; // // Ignore Not Risk Free Signal ... if ( trade.riskFree <= 0 || (trade.riskFree > 0 && trade.riskFreeRate <= 0)) { continue; } // bool isLong = trade.type == X_SIGNAL_LONG; // // Check Exit Price reached Risk Free ... double exitPrice = GetExit(trade.type); double isPriceReachedRiskFree = isLong ? exitPrice >= trade.riskFree : exitPrice <= trade.riskFree; if (!isPriceReachedRiskFree) { continue; } // double riskFreeRate = trade.riskFreeRate > 0.75 ? 0.75 : trade.riskFreeRate; double volume = NormalizeVolume(riskFreeRate * trade.volume); // bool isPartialClosed = ClosePartial(trade.ticket, volume); if (isPartialClosed) { // double tpValue = trade.virtualTP > 0 ? trade.virtualTP : trade.tp; double slValue = trade.virtualSL > 0 ? trade.virtualSL : trade.sl; // bool isModified = Modify(trade.ticket, tpValue, slValue); if (isModified) { Add( trade, riskFrees); } } } } void RiskFreeSignals( XSignal &riskFrees[] // Holds all Executed Signals ) { // CleanBuffer(riskFrees); // XSignal trades[]; RiskFreeSignals( X_SIGNAL_UNKNOWN, X_KIND_TRADE, trades); int tradesCount = ArraySize(trades); if (tradesCount > 0) { // // Loop ... for (int i = 0; i < tradesCount; i++) { // XSignal fTrade = trades[i]; // Add( fTrade, riskFrees); } } // XSignal supports[]; RiskFreeSignals( X_SIGNAL_UNKNOWN, X_KIND_SUPPORT, supports); int supportsCount = ArraySize(supports); if (supportsCount > 0) { // // Loop ... for (int i = 0; i < supportsCount; i++) { // XSignal fTrade = supports[i]; // Add( fTrade, riskFrees); } } } // // Close All Open Positions ... void CloseAllPositions( XSignal &closed[] // Holds Closed Positions ) { // CleanBuffer(closed); // XSignal allPositions[]; GetAllPositions(allPositions); // // Count all Specified Positions ... int total = ArraySize(allPositions); if (total <= 0) { return; } // for (int i = 0; i < total; i++) { // XSignal signal = allPositions[i]; string comment = GetSignalForceClosedComment(signal); bool isClosed = Close( signal.ticket, comment); if (isClosed) { // Add( signal, closed); } } } // // Close Positions By Type ... void ClosePositionsByType( ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions XSignal &closed[] // Holds Closed Positions ) { // CleanBuffer(closed); // XSignal allPositions[]; GetPositionsByType( type, allPositions); // // Count all Specified Positions ... int total = ArraySize(allPositions); if (total <= 0) { return; } // for (int i = 0; i < total; i++) { // XSignal signal = allPositions[i]; string comment = GetSignalForceClosedComment(signal); bool isClosed = Close( signal.ticket, comment); if (isClosed) { // Add( signal, closed); } } } // // Close Positions By Kind ... void ClosePositionsByKind( ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions XSignal &closed[] // Holds Closed Positions ) { // CleanBuffer(closed); // XSignal allPositions[]; GetPositionsByKind( type, kind, allPositions); // // Count all Specified Positions ... int total = ArraySize(allPositions); if (total <= 0) { return; } // for (int i = 0; i < total; i++) { // XSignal signal = allPositions[i]; string comment = GetSignalForceClosedComment(signal); bool isClosed = Close( signal.ticket, comment); if (isClosed) { // Add( signal, closed); } } } // // 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 ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions XSignal &closed[] // Holds Closed Trades ) { // CleanBuffer(closed); // // Normalize Period ... if (period == EMPTY_VALUE) { period = _Period; } // XSignal positions[]; GetLongTimeTrades( life, period, type, kind, positions); int count = ArraySize(positions); if (count <= 0) { return; } // // Loop through Positions ... for (int i = 0; i < count; i++) { // XSignal trade = positions[i]; string comment = GetSignalForceClosedComment(trade); bool isClosed = Close( trade.ticket, comment); if (isClosed) { // Add( trade, closed); } } } void CloseLongTimeTrades( int life, // Max Candle Passed after Trades Open ENUM_TIMEFRAMES period, // Calculate Candles based on time frame XSignal &closed[] // Holds Closed Trades ) { // CleanBuffer(closed); // XSignal trades[]; CloseLongTimeTrades( life, period, X_SIGNAL_UNKNOWN, X_KIND_TRADE, trades); int tradesCount = ArraySize(trades); if (tradesCount > 0) { // // Loop ... for (int i = 0; i < tradesCount; i++) { // XSignal fTrade = trades[i]; // Add( fTrade, closed); } } // XSignal supports[]; CloseLongTimeTrades( life, period, X_SIGNAL_UNKNOWN, X_KIND_SUPPORT, supports); int supportsCount = ArraySize(supports); if (supportsCount > 0) { // // Loop ... for (int i = 0; i < supportsCount; i++) { // XSignal fTrade = supports[i]; // Add( fTrade, closed); } } } // // Close In DrawDown Trades ... void CloseInDrawDownTrades( double maxDrawDown, // Maximum DrawDown of Trades ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions XSignal &closed[] // Holds Closed Trades ) { // CleanBuffer(closed); // // Validate Args ... if (maxDrawDown <= 0) { return; } // XSignal trades[]; GetInDrawDownTrades( maxDrawDown, type, kind, 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]; string comment = GetSignalInDistanceClosedComment(trade); bool isClosed = Close( trade.ticket, comment); if (isClosed) { Add( trade, closed); } } } void CloseInDrawDownTrades( double maxDrawDown, // Maximum DrawDown of Trades XSignal &closed[] // Holds Closed Trades ) { // CleanBuffer(closed); // XSignal trades[]; CloseInDrawDownTrades( maxDrawDown, X_SIGNAL_UNKNOWN, X_KIND_TRADE, trades); int tradesCount = ArraySize(trades); if (tradesCount > 0) { // // Loop ... for (int i = 0; i < tradesCount; i++) { // XSignal fTrade = trades[i]; // Add( fTrade, closed); } } // XSignal supports[]; CloseInDrawDownTrades( maxDrawDown, X_SIGNAL_UNKNOWN, X_KIND_SUPPORT, supports); int supportsCount = ArraySize(supports); if (supportsCount > 0) { // // Loop ... for (int i = 0; i < supportsCount; i++) { // XSignal fTrade = supports[i]; // Add( fTrade, closed); } } } // // Close All In Profit Trades ... void CloseInProfitTrades( double minProfit, // Minimum Profit To Close Trades ENUM_X_SIGNAL_TYPE type, // Specify trades type to act ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions XSignal &closed[] // Holds Closed Trades ) { // CleanBuffer(closed); // XSignal trades[]; GetInProfitTrades( minProfit, type, kind, 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]; string comment = GetSignalInDistanceClosedComment(trade); bool isClosed = Close( trade.ticket, comment); if (isClosed) { Add( trade, closed); } } } void CloseInProfitTrades( double minProfit, // Minimum Profit To Close Trades XSignal &closed[] // Holds Closed Trades ) { // CleanBuffer(closed); // XSignal trades[]; CloseInProfitTrades( minProfit, X_SIGNAL_UNKNOWN, X_KIND_TRADE, trades); int tradesCount = ArraySize(trades); if (tradesCount > 0) { // // Loop ... for (int i = 0; i < tradesCount; i++) { // XSignal fTrade = trades[i]; // Add( fTrade, closed); } } // XSignal supports[]; CloseInProfitTrades( minProfit, X_SIGNAL_UNKNOWN, X_KIND_SUPPORT, supports); int supportsCount = ArraySize(supports); if (supportsCount > 0) { // // Loop ... for (int i = 0; i < supportsCount; i++) { // XSignal fTrade = supports[i]; // Add( fTrade, closed); } } } // // START Signal Related ... // // // Prepare a Signall ... XSignal GenerateSignal( ENUM_X_SIGNAL_TYPE type, // Signal Type double tp = 0, // Take Profit double sl = 0, // Stop Loss double volume = 0, // Volume double riskFree = 0, // Risk Free Price double riskFreeRate = 0, // Risk Free Rate ENUM_X_SIGNAL_KIND kind = X_KIND_TRADE, // Signal Kind ulong parent = 0, // Support Kind Signal Parent bool useVirtualTPSL = false // Use Virtual TP and SL ) { // XSignal result = {}; // // Validate Arg ... if (type == X_SIGNAL_UNKNOWN) { return result; } // // Check Signal Type ... bool isLong = type == X_SIGNAL_LONG; // // Retrieve entry Price ... double entry = GetEntry(mSymbol, type); double spread = GetSpread(mSymbol); // double tpPrice = 0; double slPrice = 0; double riskFreePrice = 0; // // Normalize TP Value ... if (tp <= 0) { // double minReward = PipsToPrice(mMinTradeProfitsInPips); tp = minReward; } // if (riskFree > 0 && riskFreeRate > 0) { // riskFreePrice = type == X_SIGNAL_LONG ? entry + riskFree : entry - riskFree; riskFreePrice = NormalizePrice(riskFreePrice, mSymbol); } // if (tp > 0) { // tp += spread; // tpPrice = isLong ? entry + tp : entry - tp; tpPrice = NormalizePrice(tpPrice, mSymbol); } // if (sl > 0) { // sl += spread; // slPrice = isLong ? entry - sl : entry + sl; slPrice = NormalizePrice(slPrice, mSymbol); } // result.type = type; result.kind = kind; result.entry = entry; result.parent = parent; result.symbol = mSymbol; result.riskFree = riskFreePrice; result.magicNumber = mMagicNumber; result.riskFreeRate = riskFreeRate; result.tp = useVirtualTPSL ? 0 : tpPrice; result.sl = useVirtualTPSL ? 0 : slPrice; result.time = iTime(mSymbol, _Period, 0); result.virtualTP = useVirtualTPSL ? tpPrice : 0; result.virtualSL = useVirtualTPSL ? slPrice : 0; result.volume = NormalizeVolume(volume, mSymbol); result.comment = GetSignalComment(result, useVirtualTPSL); // return result; } XSignal GenerateTradeSignal( ENUM_X_SIGNAL_TYPE type, // Signal Type double tp, // Take Profit double sl, // Stop Loss double volume, // Volume double riskFree = 0, // Risk Free Price double riskFreeRate = 0, // Risk Free Rate bool useVirtualTPSL = false // Use Virtual TP and SL ) { // XSignal result = GenerateSignal( type, tp, sl, volume, riskFree, riskFreeRate, X_KIND_TRADE, 0, useVirtualTPSL); // return result; } XSignal GenerateSupportSignal( ENUM_X_SIGNAL_TYPE type, // Signal Type double tp, // Take Profit double sl, // Stop Loss double volume, // Volume double riskFree, // Risk Free Price double riskFreeRate, // Risk Free Rate ulong parent, // Support Kind Signal Parent bool useVirtualTPSL = false // Use Virtual TP and SL ) { // XSignal result = GenerateSignal( type, tp, sl, volume, riskFree, riskFreeRate, X_KIND_TRADE, parent, useVirtualTPSL); // return result; } // // Calculate SignalAge ... int GetSignalAge( datetime time // Signal Execution Time ) { // int result = 0; // // Validate Arg ... if (time <= 0) { return result; } // int sIndex = iBarShift( mSymbol, _Period, time); // datetime cTime = iTime( mSymbol, _Period, 0); int cIndex = iBarShift( mSymbol, _Period, cTime); // result = MathAbs(cIndex - sIndex); // return result; } int GetSignalAge( datetime time, // Signal Execution Time ENUM_TIMEFRAMES period // Specify Time Frame ) { // int result = 0; // // Validate Arg ... if (time <= 0) { return result; } // int sIndex = iBarShift( mSymbol, period, time); // datetime cTime = iTime( mSymbol, period, 0); int cIndex = iBarShift( mSymbol, _Period, cTime); // result = MathAbs(cIndex - sIndex); // return result; } int GetSignalAge( XSignal &signal // Specify Signal ) { // int result = 0; // // Validate Arg ... if ( signal.time <= 0 || !IsValid(signal, mMagicNumber)) { return result; } // result = GetSignalAge(signal.time); // return result; } int GetSignalAge( XSignal &signal, // Specify Signal ENUM_TIMEFRAMES period // Specify Time Frame ) { // int result = 0; // // Validate Arg ... if ( signal.time <= 0 || !IsValid(signal, mMagicNumber)) { return result; } // result = GetSignalAge( signal.time, period); // return result; } // // Generate a Signal Object name for Draw Events On Chart ... string GetSignalObjectName( ulong ticket // Specify Ticket ) { // string result = ""; // // Validate Arg ... if (ticket <= 0) { return result; } // // TICKET ... // it is very importants since they hold position info ... result += "T(" + (string)ticket + ")"; // return result; } string GetSignalObjectName( XSignal &signal // Specify Signal ) { // string result = ""; // // Validate Arg ... if (!IsValid(signal, mMagicNumber)) { return result; } // result = GetSignalObjectName(signal.ticket); // return result; } // // Convert a Signal to String Representation ... string ToString( XSignal &signal // Specify Signal ) { // string result = ""; // if (!IsValid(signal, mMagicNumber) || signal.ticket <= 0) { return result; } // // TICKET ... // it is very importants since they hold position info ... result += "T(" + (string)signal.ticket + ")"; // // TYPE ... string typeStr = GetSignalType(signal.type); result += "_TY(" + typeStr + ")"; // // KIND ... string kindStr = GetSignalKind(signal.kind); result += "_K(" + kindStr + ")"; // // PARENT ... result += "_PR(" + (string)signal.parent + ")"; // // ENTRY ... result += "_E(" + (string)signal.entry + ")"; // // VIRTUALTP ... result += "_VT(" + (string)signal.virtualTP + ")"; // // VIRTUALSL ... result += "_VS(" + (string)signal.virtualSL + ")"; // // RISKFREE ... result += "_RF(" + (string)signal.riskFree + ")"; // // RISKFREERATE ... result += "_RR(" + (string)signal.riskFreeRate + ")"; // // VOLUME ... result += "_V(" + (string)signal.volume + ")"; // // TYPE ... // KIND ... // ENTRY ... // TICKET ... // PARENT ... // VOLUME ... // RISKFREE ... // VIRTUALTP ... // VIRTUALSL ... // RISKFREERATE ... // an String Representation of a Signal Carry above fields ... // // ID ... // TP ... // SL ... // TIME ... // SYMBOL ... // PROFIT ... // COMMENT ... // MAGICNUMBER ... // these above items can read using PositionInfo instance ... // so they are not necessary ... // return result; } // // Convert an string to signal ... XSignal FromString( string represent // String Represenation of a Signal ) { // XSignal result = {}; // // Validate Arg ... if (StringLen(represent) == 0) { return result; } // // TICKET ... string ticketStr = ExtractString( represent, "T(", ")"); if (StringLen(ticketStr) > 0) { result.ticket = (ulong)ticketStr; } // // TYPE ... string typeStr = ExtractString( represent, "_TY(", ")"); if (StringLen(typeStr) > 0) { // ENUM_X_SIGNAL_TYPE type = GetSignalType(typeStr); result.type = type; } // // KIND ... string kindStr = ExtractString( represent, "_K(", ")"); if (StringLen(kindStr) > 0) { // ENUM_X_SIGNAL_KIND kind = GetSignalKind(kindStr); result.kind = kind; } // // PARENT ... string parentStr = ExtractString( represent, "_PR(", ")"); if (StringLen(parentStr) > 0) { result.parent = (ulong)parentStr; } // // ENTRY ... string entryStr = ExtractString( represent, "_E(", ")"); if (StringLen(entryStr) > 0) { result.entry = (double)entryStr; } // // VIRTUALTP ... string virtualTPStr = ExtractString( represent, "_VT(", ")"); if (StringLen(virtualTPStr) > 0) { result.virtualTP = (double)virtualTPStr; } // // VIRTUALSL ... string virtualSLStr = ExtractString( represent, "_VS(", ")"); if (StringLen(virtualSLStr) > 0) { result.virtualSL = (double)virtualSLStr; } // // RISKFREE ... string riskFreeStr = ExtractString( represent, "_RF(", ")"); if (StringLen(riskFreeStr) > 0) { result.riskFree = (double)riskFreeStr; } // // RISKFREERATE ... string riskFreeRateStr = ExtractString( represent, "_RR(", ")"); if (StringLen(riskFreeRateStr) > 0) { result.riskFreeRate = (double)riskFreeRateStr; } // // VOLUME ... string volumeStr = ExtractString( represent, "_V(", ")"); if (StringLen(volumeStr) > 0) { result.volume = (double)volumeStr; } // return result; } void FromString( XSignal &result, // Holds Result string represent // String Represenation of a Signal ) { // // Validate Arg ... if (StringLen(represent) == 0) { return; } // // TICKET ... string ticketStr = ExtractString( represent, "T(", ")"); if (StringLen(ticketStr) > 0) { result.ticket = (ulong)ticketStr; } // // TYPE ... string typeStr = ExtractString( represent, "_TY(", ")"); if (StringLen(typeStr) > 0) { // ENUM_X_SIGNAL_TYPE type = GetSignalType(typeStr); result.type = type; } // // KIND ... string kindStr = ExtractString( represent, "_K(", ")"); if (StringLen(kindStr) > 0) { // ENUM_X_SIGNAL_KIND kind = GetSignalKind(kindStr); result.kind = kind; } // // PARENT ... string parentStr = ExtractString( represent, "_PR(", ")"); if (StringLen(parentStr) > 0) { result.parent = (ulong)parentStr; } // // ENTRY ... string entryStr = ExtractString( represent, "_E(", ")"); if (StringLen(entryStr) > 0) { result.entry = (double)entryStr; } // // VIRTUALTP ... string virtualTPStr = ExtractString( represent, "_VT(", ")"); if (StringLen(virtualTPStr) > 0) { result.virtualTP = (double)virtualTPStr; } // // VIRTUALSL ... string virtualSLStr = ExtractString( represent, "_VS(", ")"); if (StringLen(virtualSLStr) > 0) { result.virtualSL = (double)virtualSLStr; } // // RISKFREE ... string riskFreeStr = ExtractString( represent, "_RF(", ")"); if (StringLen(riskFreeStr) > 0) { result.riskFree = (double)riskFreeStr; } // // RISKFREERATE ... string riskFreeRateStr = ExtractString( represent, "_RR(", ")"); if (StringLen(riskFreeRateStr) > 0) { result.riskFreeRate = (double)riskFreeRateStr; } // // VOLUME ... string volumeStr = ExtractString( represent, "_V(", ")"); if (StringLen(volumeStr) > 0) { result.volume = (double)volumeStr; } } // // END Signal Related ... // // // all protected features ... protected: // // all private features ... private: // // Specified Unique Tag ... string mTag; // // which Symbol ... string mSymbol; // // using deviation, it must be in Point ... int mSlippage; // // using magic number ... ulong mMagicNumber; // // Specify Max Allowed Trades int mMaxAllowedTrades; // // Specify Max Allowed Support Trades for each Trade int mMaxAllowedSupportTrades; // // Minimum Profit of each Trade in Pips double mMinTradeProfitsInPips; // // Support Trades Price Distance in Pips double mSupportTradesPriceDistanceInPips; // // Minimum Free Marging for Open Trades double mMinAllowedFreeMarginForOpenTrades; // // Minimum Balance for Open Trades double mMinBallanceForOpenTrades; // // using CTrade instance ... XSCTrade mTrader; // // An Instance Of XCAccount Info for Handling Account Related Actions ... XCAccountInfo mAccountInfo; // // using PositionInfo instance ... CPositionInfo mPositionInfo; // // For Manage Deals ... CDealInfo mDealInfo; // // 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; } // ulong ticket = mPositionInfo.Ticket(); string signalContent = RetrieveSignalContent(ticket); if (StringLen(signalContent) > 0) { // // Fill Additional Contents ... FromString( result, signalContent); } // // Ticket ... result.ticket = mPositionInfo.Ticket(); // // 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(); // // 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; } // // Draw a Signal on Screen ... void DrawSignal( XSignal &signal, // Specify Draw which Signal on Screen color longColor = clrAqua, // Long Signal Object Color color shortColor = clrFuchsia, // Short Signal Object Color int chartId = -1, // Specify Chart ID int subWindow = -1 // Specify SubWindow ID ) { // // Validate Args ... if ( signal.ticket <= 0 || !IsValid(signal, mMagicNumber) || signal.type == X_SIGNAL_UNKNOWN) { return; } // // Normalize Chart and SubWindow ID ... if (chartId == -1) { chartId = 0; } if (subWindow == -1) { subWindow = 0; } // bool isLong = signal.type == X_SIGNAL_LONG; // // Simply Draw an Arrow on Chart for Representing Signal Info ... string name = GetSignalObjectName(signal); string content = ToString(signal); if (StringLen(content) == 0) { return; } // color signalColor = isLong ? longColor : shortColor; // // Create an Event On Chart ... bool isCreated = EventCreate( chartId, name, subWindow, content, signal.time, signalColor); } // // Filter Trades Buffer ... void FilterSignals( string query, // Search String XSignal &source[], // Source Buffer to Filter XSignal &result[] // Holds Result ) { // // Free Buffer ... CleanBuffer(result); // int sourceCount = ArraySize(source); // // Check Conditions and Validate Args ... if ( sourceCount == 0 || StringLen(query) == 0) { return; } // // Loop Through Source ... for (int i = 0; i < sourceCount; i++) { // // Retrieve Indexed Item ... XSignal trade = source[i]; // // Check Query Exists or not ... int pos = StringFind( trade.comment, query); // // Continue if nothing found ... if (pos <= -1) { continue; } // // Resize the result array ... ArrayResize( result, ArraySize(result) + 1); result[ArraySize(result) - 1] = trade; } } // // Get all Positions based on Position Type ... void GetAllPositionsByType(ENUM_POSITION_TYPE type, XSignal &result[]) { // int existsTotal = CountByType(type); // CleanBuffer(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++; } } // // Retrieve Signal Specified Object Text ... string RetrieveSignalContent( ulong ticket, // Specify Position Ticket int chartId = -1, // Specify Chart ID int subWindow = -1 // Specify SubWindow ID ) { // string result = ""; // // Validate Arg ... if (ticket <= 0) { return result; } // string signalObjectName = GetSignalObjectName(ticket); if (StringLen(signalObjectName) == 0) { return result; } // // Normalize Chart and SubWindow ID ... if (chartId == -1) { chartId = 0; } if (subWindow == -1) { subWindow = 0; } // // Search For Signal Object Name ... int objectIndex = ObjectFind( chartId, signalObjectName); if (objectIndex < 0) { return result; } // // Loop Through Objects ... int count = ObjectsTotal( chartId, subWindow); for (int i = count - 1; i >= 0; i--) { // // Retrieve Object Name ... string objectName = ObjectName(chartId, i, subWindow); // // Find Signal Ticket Position in Object Name ... int stPos = StringFind( objectName, signalObjectName); if (stPos < 0) { continue; } // // Retrieve Object Text as String Representation OF Signal ... result = ObjectGetString(chartId, objectName, OBJPROP_TEXT); break; } // return result; } string RetrieveSignalContent( XSignal &signal, // Specify Signal int chartId = -1, // Specify Chart ID int subWindow = -1 // Specify SubWindow ID ) { // string result = ""; // result = RetrieveSignalContent( signal.ticket, chartId, subWindow); // return result; } // // Remove Signal Object from Chart ... bool RemoveSignal( ulong ticket, // Specify Position Ticket int chartId = -1 // Specify Chart ID ) { // bool result = false; // // Validate Arg ... if (ticket <= 0) { return result; } // // Normalize Chart Id ... if (chartId <= 0) { chartId = 0; } // // Generate Signal Object Name ... string signalObjectName = GetSignalObjectName(ticket); // // Remove Object from Chart ... result = ObjectDelete(chartId, signalObjectName); // return result; } bool RemoveSignal( XSignal &signal, // Specify Signal int chartId = -1 // Specify Chart ID ) { // bool result = false; // result = RemoveSignal( signal.ticket, chartId); // return result; } // // Generate Comments for Specific Signal ... string GetSignalComment( ENUM_X_SIGNAL_KIND kind, // Specify Kind ENUM_X_SIGNAL_TYPE type, // Specify Kind Signal Type ulong parentTicket, // Parent Signal Ticket double volume, // Signal Volume double riskFree, // Risk Free Price double riskFreeRate, // Risk Free Volume Multiplier double virtualTP, // Virtual TP double virtualSL // Virtual SL ) { // string result = ""; // string kindStr = GetSignalKind(kind); string typeStr = GetSignalType(type); if ( volume <= 0 || StringLen(kindStr) == 0 || StringLen(typeStr) == 0 || (parentTicket <= 0 && kind == X_KIND_SUPPORT)) { return result; } // // Normalize Data ... // if (riskFreeRate < 0) { riskFreeRate = 0; } else if (riskFreeRate > 1) { riskFreeRate = 0.75; } // volume = NormalizeVolume(volume, mSymbol); riskFree = NormalizePrice(riskFree, mSymbol); virtualTP = NormalizePrice(virtualTP, mSymbol); virtualSL = NormalizePrice(virtualSL, mSymbol); // if (riskFree > 0 && riskFreeRate == 0) { riskFreeRate = 0.75; } else if (riskFree <= 0 && riskFreeRate > 0) { riskFreeRate = 0; } // string kindTitle = kind == X_KIND_TRADE ? kindStr : kindStr + "_For_" + (string)parentTicket; result = mTag + "_" + typeStr + "_" + kindTitle; // result = kindTitle; // // // if (virtualTP > 0) // { // result += "_P(" + (string)virtualTP + ")"; // } // // // if (virtualSL > 0) // { // result += "_L(" + (string)virtualSL + ")"; // } // // // if (riskFree > 0 && riskFreeRate > 0) // { // result += "_R(" + (string)riskFree + ")_M(" + (string)riskFreeRate + ")"; // } // return result; } string GetSignalComment( XSignal &signal, // Specify Signal bool useVirtualTPSL = false // Use Virtual TP and SL ) { // string result = GetSignalComment( signal.kind, signal.type, signal.parent, signal.volume, signal.riskFree, signal.riskFreeRate, useVirtualTPSL ? signal.virtualTP : 0, useVirtualTPSL ? signal.virtualSL : 0); // return result; } // // Generate TP Comment For Closing Signal ... string GetSignalClosedOnTPComment( XSignal &signal // Model Signal to Use ) { // string result = ""; // if (signal.ticket <= 0 || !IsValid(signal, mMagicNumber)) { return result; } // double exitPrice = GetExit(signal.type); string prefix = GetSignalObjectName(signal); // bool isVirtual = signal.tp <= 0 && signal.virtualTP > 0; // // "_E(" + (string)signal.entry + ")" ... result = (isVirtual ? "V_" : "") + prefix + "_TP(" + (string)exitPrice + ")"; // return result; } // // Generate SL Comment For Closing Signal ... string GetSignalClosedOnSLComment( XSignal &signal // Model Signal to Use ) { // string result = ""; // if (signal.ticket <= 0 || !IsValid(signal, mMagicNumber)) { return result; } // double exitPrice = GetExit(signal.type); string prefix = GetSignalObjectName(signal); // bool isVirtual = signal.sl <= 0 && signal.virtualSL > 0; // // "_E(" + (string)signal.entry + ")" ... result = (isVirtual ? "V_" : "") + prefix + "_SL(" + (string)exitPrice + ")"; // return result; } // // Generate Comment For Force Closing Signal ... string GetSignalForceClosedComment( XSignal &signal // Model Signal to Use ) { // string result = ""; // if (signal.ticket <= 0 || !IsValid(signal, mMagicNumber)) { return result; } // double exitPrice = GetExit(signal.type); string prefix = GetSignalObjectName(signal); // // "_E(" + (string)signal.entry + ")" ... result = "F_" + prefix + "_P(" + (string)exitPrice + ")"; // return result; } // // Generate Comment For In DrawDown and In Profit Closing Signal ... string GetSignalInDistanceClosedComment( XSignal &signal // Model Signal to Use ) { // string result = ""; // if (signal.ticket <= 0 || !IsValid(signal, mMagicNumber)) { return result; } // double exitPrice = GetExit(signal.type); string prefix = GetSignalObjectName(signal); string distanceStr = signal.profit > 0 ? "InP" : "InDD"; // // "_E(" + (string)signal.entry + ") ... // "_P(" + (string)exitPrice + ")" ... result = distanceStr + "_" + prefix + "_D(" + (string)signal.profit + ")"; // return result; } // // Generate Comment For Long Time Closing Signal ... string GetSignalLongTimeClosedComment( XSignal &signal // Model Signal to Use ) { // string result = ""; // if (signal.ticket <= 0 || !IsValid(signal, mMagicNumber)) { return result; } // double exitPrice = GetExit(signal.type); string prefix = GetSignalObjectName(signal); // int signalAge = GetSignalAge(signal); // // "_E(" + (string)signal.entry + ")" ... // "_P(" + (string)exitPrice + ")" ... result = "LT_" + prefix + "_A(" + (string)signalAge + ")" + "_D(" + (string)signal.profit + ")"; // return result; } // // Check Number Of Trades is Valid ... bool CanOpenNewTrade() { // bool result = false; // int count = Count(); result = mMaxAllowedTrades <= 0 ? true : count < mMaxAllowedTrades; // return result; } // // Check Number Of Support Trades is Valid ... bool CanOpenSupportTrade() { // bool result = false; // return result; } // // Check Account Has Minimum Balance For Trade ... bool IsAccountBalanceReadyForTrade() { // bool result = false; // result = mAccountInfo.GetBalance() >= mMinBallanceForOpenTrades; // return result; } // // Check Free Margin Has Enough For Trade ... bool IsFreeMarginReadyForTrade() { // bool result = false; // result = mAccountInfo.GetFreeMargin() >= mMinAllowedFreeMarginForOpenTrades; // return result; } }; // // END Global Definitions: Variables, Properties and etc ... //