/////////////////////////////////////////////////////// // // 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; } int CountByKind( ENUM_X_SIGNAL_KIND kind // Specify Kind of Positions ) { // int result = 0; // // Count Longs ... result = CountByKind( X_SIGNAL_UNKNOWN, kind); // return result; } // // Count Supported Positions belongs to Specified Parent Signal ... int CountSupportedPositions( XSignal &parent // Specified Parent Signal ) { // int result = 0; // XSignal supports[]; GetSupportedPositions(parent, supports); result = ArraySize(supports); // return result; } // // Retrieve Specified Position by it's Ticket ... XSignal GetPosition( ulong ticket // Specified Ticket ) { // XSignal result = {}; // result = PositionToSignal(ticket); // return result; } // // Retrieve all Positions ... void GetAllPositions( XSignal &result[] // Holds 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[] // Holds Result ... ) { GetAllPositionsByType(POSITION_TYPE_BUY, result); } // // Retrieve all Short Positions ... void GetShortPositions( XSignal &result[] // Holds 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); } } // // Retrieve List Of Supported Positions belongs to Specified Parent Signal ... void GetSupportedPositions( XSignal &parent, // Specified Parent Signal XSignal &result[] // Holds Result ... ) { // CleanBuffer(result); // // Validate Signal ... bool isValidSignal = IsValid(parent, mMagicNumber); if (!isValidSignal) { return; } // // Validate Signal is Parent Signal ... bool isParentSignal = parent.kind == X_KIND_TRADE; if (!isParentSignal) { return; } // // Retrieve All Support Signals ... XSignal supports[]; GetPositionsByKind( X_SIGNAL_UNKNOWN, X_KIND_SUPPORT, supports); int supportsCount = ArraySize(supports); if (supportsCount <= 0) { return; } // // Loop Through Supports ... for (int i = 0; i < supportsCount; i++) { // XSignal support = supports[i]; // bool isBelongsToParent = support.parent == parent.ticket; if (isBelongsToParent) { // Add( support, 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 // Specify Signal for Execution ) { // 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 = false; // // Validate Signal ... result = ValidateSignal(signal); if (!result) { // error = X_INVALID_SIGNAL_ERROR; return result; } // signal.symbol = mSymbol; // bool isTrade = signal.kind == X_KIND_TRADE; // // 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 Can Open Trades ... result = CanOpenNewTrade( signal.type, signal.kind); if (!result) { error = isTrade ? // X_XTRADER_MAX_ALLOWED_TRADE_KIND_REACHED_ERROR : // X_XTRADER_MAX_ALLOWED_SUPPORT_KIND_REACHED_ERROR // ; } // ResetLastError(); // // Execute Signal Trade ... 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) // { // // // int errorCode = GetLastError(); // // // // Not Enough Money, since Volume is High ... // if (errorCode == 4756) // { // // // signal.volume = NormalizeVolume(signal.volume / 3); // result = ExecuteSignal( // signal, // error); // } // } // 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 ... DrawSignalEvent(signal); } else { error = X_UNKNOWN_ERROR; } // return result; } // // Execute Support Signal ... bool ExecuteSupportSignal( XSignal &signal, // Specify Signal for Execution int &error // Error code if Happens ) { // bool result = false; error = X_UNKNOWN_ERROR; // // Validate Signal ... result = ValidateSignal(signal); if (!result) { // error = X_INVALID_SIGNAL_ERROR; return result; } // // Determines Signal is Long or Short ... bool isLong = signal.type == X_SIGNAL_LONG; // // Check Signal Kind ... result = signal.kind == X_KIND_SUPPORT; if (!result) { // error = X_INVALID_SIGNAL_ERROR; return result; } // // Check Signal Kind Based Properties ... result = signal.parent > 0; if (!result) { // error = X_INVALID_SIGNAL_ERROR; return result; } // // Check Support Trade Parent Position Existance ... XSignal parent = GetPosition(signal.parent); result = IsValid(parent, mMagicNumber); if (!result) { // error = X_INVALID_SIGNAL_ERROR; return result; } // // Check Max Number Of Support Trades which belongs to Parent ... int supportsCount = CountSupportedPositions(parent); result = supportsCount < mMaxAllowedSupportTrades; if (!result) { // error = X_XTRADER_MAX_ALLOWED_SUPPORT_KIND_REACHED_ERROR; return result; } // // Check Support Trade Price Distance Passed ... double supportTradesPriceDistance = PipsToPrice(mSupportTradesPriceDistanceInPips); double supportPriceDistance = MathAbs(parent.entry - signal.entry); result = supportPriceDistance >= supportTradesPriceDistance; if (!result) { // error = X_TRADER_SUPPORT_DISTANCE_NOT_HAPPENS_ERROR; return result; } // // Check Account Balance ... result = IsAccountBalanceReadyForTrade(); if (!result) { // error = X_XTRADER_NOT_ENOUGH_BALANCE_ERROR; return result; } // ResetLastError(); // // Execute Signal Trade ... 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) // { // // // int errorCode = GetLastError(); // // // // Not Enough Money, since Volume is High ... // if (errorCode == 4756) // { // // // signal.volume = NormalizeVolume(signal.volume / 3); // result = ExecuteSupportSignal( // signal, // error); // } // } // 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 ... DrawSignalEvent(signal); } else { error = X_UNKNOWN_ERROR; } // 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, // 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)) { return result; } // 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 volume = trade.volume; double riskFreeRate = trade.riskFreeRate; double riskFreeVolume = riskFreeRate * volume; riskFreeVolume = NormalizeVolume(riskFreeVolume); // // Check Trade Doesnt Closed Partial Before ... // Check Volume is Enough for Partial Closing ... if ( trade.sl > 0 || riskFreeVolume == volume) { continue; } // bool isPartialClosed = ClosePartial(trade.ticket, riskFreeVolume); if (isPartialClosed) { // bool isLong = trade.type == X_SIGNAL_LONG; double entry = GetEntry(trade.symbol, trade.type); // double tpValue = trade.tp; double slDistance = 0; // PipsToPrice(2); double slValue = isLong ? trade.entry - slDistance : trade.entry + slDistance; // ResetLastError(); bool isModified = Modify(trade.ticket, slValue, tpValue); if (isModified) { // Add( trade, riskFrees); // LogMessage("Order: " + (string)trade.ticket + " Modification Succeed ..."); } else { LogMessage("Order: " + (string)trade.ticket + " Modification Failed: " + (string)GetLastError() + ", Desc: " + GetErrorDescription(GetLastError())); } } } } 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); } } } // // Pyramid Open Trades ... void PyramidTrades( XSignal &closed[] // Holds Closed Trades ) { // CleanBuffer(closed); // // Check Open Positions In DrawDown Values ... // // Trades ... XSignal inDDTrades[]; GetInDrawDownTrades( 0, X_SIGNAL_UNKNOWN, X_KIND_TRADE, inDDTrades); int inDDTradesCount = ArraySize(inDDTrades); // // Supports ... XSignal inDDSupports[]; GetInDrawDownTrades( 0, X_SIGNAL_UNKNOWN, X_KIND_SUPPORT, inDDSupports); int inDDSupportsCount = ArraySize(inDDSupports); // // Prevent Going Forward ... if (inDDTradesCount == 0 && inDDSupportsCount == 0) { return; } // // Number Of In DD Trades ... int count = inDDTradesCount + inDDSupportsCount; if (count <= 1) { return; } // // Select Longest inDD ... XSignal longestDD = {}; // // Trades ... if (inDDTradesCount > 0) { // for (int i = 0; i < inDDTradesCount; i++) { // XSignal iSignal = inDDTrades[i]; // longestDD = longestDD.profit == 0 || longestDD.profit > iSignal.profit ? iSignal : longestDD; } } // // Supports ... if (inDDSupportsCount > 0) { // for (int i = 0; i < inDDSupportsCount; i++) { // XSignal iSignal = inDDSupports[i]; // longestDD = longestDD.profit == 0 || longestDD.profit > iSignal.profit ? iSignal : longestDD; } } // // Check Longest In DD ... LogMessage("Longest (" + (string)count + ") inDD: " + (string)longestDD.ticket + ", Profit: " + (string)longestDD.profit); // // Close Longest In DD ... Close(longestDD.ticket, "Longets In Drawdown Position"); // Add( longestDD, 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 ) { // 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.tp = tpPrice; result.sl = slPrice; result.entry = entry; result.parent = parent; result.symbol = mSymbol; result.riskFree = riskFreePrice; result.magicNumber = mMagicNumber; result.riskFreeRate = riskFreeRate; result.time = iTime(mSymbol, _Period, 0); result.volume = NormalizeVolume(volume, mSymbol); // // Since we Use signal instance to Generate Comment, this must be at the end ... result.comment = GetSignalComment(result); // 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 ) { // XSignal result = GenerateSignal( type, tp, sl, volume, riskFree, riskFreeRate, X_KIND_TRADE, 0 // ); // 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 ) { // XSignal result = GenerateSignal( type, tp, sl, volume, riskFree, riskFreeRate, X_KIND_SUPPORT, parent // ); // 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 + ")"; // // 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; } // // 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; } // // 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; } // // Position To Signal by Ticket ... XSignal PositionToSignal(ulong ticket) { // XSignal result = {}; // if (!mPositionInfo.SelectByTicket(ticket)) { return result; } // 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 DrawSignalEvent( 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); if (isCreated) { // DrawSignalShape( signal, longColor, shortColor); } } // // 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 Type and Check it Event ... int oType = (int)ObjectGetInteger(chartId, objectName, OBJPROP_TYPE); if (oType != OBJ_EVENT) { 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 ) { // 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); // 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; // return result; } string GetSignalComment( XSignal &signal // Specify Signal ) { // string result = GetSignalComment( signal.kind, signal.type, signal.parent, signal.volume, signal.riskFree, signal.riskFreeRate // ); // 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); // // "_E(" + (string)signal.entry + ")" ... result = 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); // // "_E(" + (string)signal.entry + ")" ... result = 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( ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions ENUM_X_SIGNAL_KIND kind // Specify Kind of Positions ) { // bool result = false; // int tradesCount = CountByKind( type, kind); // result = tradesCount <= 0; if (!result) { return result; } // bool isTradeKind = kind == X_KIND_TRADE; // // Check based on Trade Kind ... result = // isTradeKind // ? // tradesCount < mMaxAllowedTrades // : // tradesCount < mMaxAllowedSupportTrades // ; // 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; // double freeMargin = mAccountInfo.GetFreeMargin(); // result = freeMargin >= mMinAllowedFreeMarginForOpenTrades; // return result; } }; // // END Global Definitions: Variables, Properties and etc ... //