/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // -------------------------------------- // Name: XClass // Description: provides all classes for use ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // #include #include #include #include #include #include // #include "../Libraries/x-saherelm.draw.lib.mq5" #include "../Libraries/x-saherelm.alert.lib.mq5" #include "../Libraries/x-saherelm.models.lib.mq5" #include "../Libraries/x-saherelm.common.lib.mq5" // // START Constant Definitions ... // static uchar _md5_PADDING[64] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #define _md5_F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define _md5_G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define _md5_H(x, y, z) ((x) ^ (y) ^ (z)) #define _md5_I(x, y, z) ((y) ^ ((x) | (~z))) #define _md5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) #define _md5_FF(a, b, c, d, x, s, ac) \ { \ (a) += _md5_F((b), (c), (d)) + (x) + (uint)(ac); \ (a) = _md5_ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define _md5_GG(a, b, c, d, x, s, ac) \ { \ (a) += _md5_G((b), (c), (d)) + (x) + (uint)(ac); \ (a) = _md5_ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define _md5_HH(a, b, c, d, x, s, ac) \ { \ (a) += _md5_H((b), (c), (d)) + (x) + (uint)(ac); \ (a) = _md5_ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define _md5_II(a, b, c, d, x, s, ac) \ { \ (a) += _md5_I((b), (c), (d)) + (x) + (uint)(ac); \ (a) = _md5_ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define _md5_INIT_STATE_0 0x67452301 #define _md5_INIT_STATE_1 0xefcdab89 #define _md5_INIT_STATE_2 0x98badcfe #define _md5_INIT_STATE_3 0x10325476 #define _md5_S11 7 #define _md5_S12 12 #define _md5_S13 17 #define _md5_S14 22 #define _md5_S21 5 #define _md5_S22 9 #define _md5_S23 14 #define _md5_S24 20 #define _md5_S31 4 #define _md5_S32 11 #define _md5_S33 16 #define _md5_S34 23 #define _md5_S41 6 #define _md5_S42 10 #define _md5_S43 15 #define _md5_S44 21 // // END Constant Definitions ... // // // START Model Definitions ... // // string X_SIGNAL_TP = "TP"; string X_SIGNAL_SL = "SL"; string X_SIGNAL_TYPE = "TY"; string X_SIGNAL_TICKET = "T"; string X_SIGNAL_RISKFREE_STEP = "RFS"; string X_SIGNAL_RISKFREE_RATE = "RFR"; // struct XTraderHandlerResult { // // List Of Closed On SL Signals ... XSignal sl[]; // // List Of Closed On TP Signals ... XSignal tp[]; // // List Of Risk Free Signals ... XSignal rf[]; }; // // Define Volume States ... struct XVolumeInfo { // // Current Available Static Volume ... double staticVolume; // // Static Volume Calculation Method ... string staticVolumeCalculationMethod; // // Current Maximum Appliable Volume ... double maxAllowedVolume; // // Static Volume Increase Multiplier ... double volumeIncreaseMultiplier; // // Multiply Volume Based On Balance Growing ... double balanceGowingToApplyMultiplier; // // Where to Increase MaxAllowed Volume ... double balanceGrowingToIncreaseMaxAllowedVolume; }; // // Model a Simple Provider Status ... struct XSignallerInfo { // // Provider Name ... string name; // // Number of Longs ... int longs; // // Number of Shorts ... int shorts; }; // // Model Some of Usefull Signals and Market Data ... struct XSummaryInfo { // // Define Max Signal Volume ... double maxSignalVolume; // // Max DrawDown ... double maxDrawDown; // // Max DrawUp ... double maxDrawUp; // // Max Number of Same Time Signals ... int maxSameTimeSignals; // // Number of Long Trades ... int longSignals; // // Number of Short Trades ... int shortSignals; // // Number of TPs Attached ... int numberOfTPs; // // Number of SLs Attached ... int numberOfSLs; }; // // Model Account info ... struct XAccountInfo { // // User Account ... string user; // // Name of Client ... string name; // // Trade Server Name ... string server; // // Broker Name ... string broker; // // Account Trade Mode ... ENUM_ACCOUNT_TRADE_MODE mode; // // Account Leverage ... long leverage; // // Currency ... string currency; // // Deposit ... double deposit; // // Balance ... double balance; // // Min Balance for Open Trades ... double minBalanceForOpenTrades; }; // // this is a Model Which holds Reports for Specific Time Periods ... struct XReport { // datetime start; // datetime end; // XAccountInfo accountInfo; // XVolumeInfo volumeInfo; // XSignallerInfo signallersInfo[]; // XSummaryInfo summaryInfo; }; // // an Enumeration Object which determines Report Type ... enum ENUM_XREPORT_TYPES { // // Main Report ... XREPORT_MAIN, // // Daily Report ... XREPORT_DAILY, // // Weekly Report ... XREPORT_WEEKLY, // // Monthly Report ... XREPORT_MONTHLY, }; // // END Model Definitions ... // // // START Overrides ... // class XSCTrade : public CTrade { public: // // Modify Specific Position, by Specific Comment ... bool PositionModify( const string symbol, // Symbol const double sl, // Stop Loss const double tp, // Take Profit const string comment = "" // Comment For Modify ) { // // check stopped if (IsStopped(__FUNCTION__)) { return (false); } // // check position existence if (!SelectPosition(symbol)) { return (false); } // // clean ClearStructures(); // // setting request m_request.action = TRADE_ACTION_SLTP; m_request.symbol = symbol; m_request.magic = m_magic; m_request.sl = sl; m_request.tp = tp; m_request.position = PositionGetInteger(POSITION_TICKET); // // Specified Comment ... if (StringLen(comment) > 0) { m_request.comment = comment; } // // action and return the result return (OrderSend(m_request, m_result)); } bool PositionModify( const ulong ticket, // Position Ticket const double sl, // Stop Loss const double tp, // Take Profit const string comment = "" // Comment For Modify ) { // // check stopped if (IsStopped(__FUNCTION__)) { return (false); } // // check position existence if (!PositionSelectByTicket(ticket)) { return (false); } // // clean ClearStructures(); // // setting request m_request.action = TRADE_ACTION_SLTP; m_request.position = ticket; m_request.symbol = PositionGetString(POSITION_SYMBOL); m_request.magic = m_magic; m_request.sl = sl; m_request.tp = tp; // // Specified Comment ... if (StringLen(comment) > 0) { m_request.comment = comment; } // // action and return the result return (OrderSend(m_request, m_result)); } // // Close Specific Position, by Specific Comment ... bool PositionClose( const string symbol, // Symbol const ulong deviation, // Deviation const string comment = "" // Comment For Close ) { // bool partial_close = false; int retry_count = 10; uint retcode = TRADE_RETCODE_REJECT; // // check stopped if (IsStopped(__FUNCTION__)) { return (false); } // // clean ClearStructures(); // // check filling if (!FillingCheck(symbol)) { return (false); } // do { // // check if (SelectPosition(symbol)) { // if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { // // prepare request for close BUY position m_request.type = ORDER_TYPE_SELL; m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); } else { // // prepare request for close SELL position m_request.type = ORDER_TYPE_BUY; m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); } } else { // // position not found m_result.retcode = retcode; return (false); } // // setting request m_request.action = TRADE_ACTION_DEAL; m_request.symbol = symbol; m_request.volume = PositionGetDouble(POSITION_VOLUME); m_request.magic = m_magic; m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; m_request.position = PositionGetInteger(POSITION_TICKET); // // Specify Comment ... m_request.comment = comment; // // check volume double max_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX); if (m_request.volume > max_volume) { // m_request.volume = max_volume; partial_close = true; } else { partial_close = false; } // // hedging? just send order if (IsHedging()) { return (OrderSend(m_request, m_result)); } // // order send if (!OrderSend(m_request, m_result)) { // if (--retry_count != 0) { continue; } // if (retcode == TRADE_RETCODE_DONE_PARTIAL) { m_result.retcode = retcode; } // return (false); } // //--- WARNING. If position volume exceeds the maximum volume allowed for deal, //--- and when the asynchronous trade mode is on, for safety reasons, position is closed not completely, //--- but partially. It is decreased by the maximum volume allowed for deal. if (m_async_mode) { break; } // retcode = TRADE_RETCODE_DONE_PARTIAL; if (partial_close) { Sleep(1000); } } while (partial_close); // // succeed return (true); } bool PositionClose( const ulong ticket, // Position Ticket const ulong deviation, // Deviation const string comment = "" // Comment For Close ) { // // check stopped if (IsStopped(__FUNCTION__)) { return (false); } // // check position existence if (!PositionSelectByTicket(ticket)) { return (false); } // string symbol = PositionGetString(POSITION_SYMBOL); // // clean ClearStructures(); // // check filling if (!FillingCheck(symbol)) { return (false); } // // check if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { // // prepare request for close BUY position m_request.type = ORDER_TYPE_SELL; m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); } else { // // prepare request for close SELL position m_request.type = ORDER_TYPE_BUY; m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); } // // setting request m_request.action = TRADE_ACTION_DEAL; m_request.position = ticket; m_request.symbol = symbol; m_request.volume = PositionGetDouble(POSITION_VOLUME); m_request.magic = m_magic; m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; // // Specify Comment ... m_request.comment = comment; // // close position return (OrderSend(m_request, m_result)); } // // Partial Close Specific Position, by Specific Comment ... bool PositionClosePartial( const string symbol, // Symbol const double volume, // Partial Closing Volume const ulong deviation, // Deviation const string comment = "" // Comment For Close ) { // uint retcode = TRADE_RETCODE_REJECT; // // check stopped if (IsStopped(__FUNCTION__)) { return (false); } // // for hedging mode only if (!IsHedging()) { return (false); } // // clean ClearStructures(); // // check filling if (!FillingCheck(symbol)) { return (false); } // // check if (SelectPosition(symbol)) { // if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { // // prepare request for close BUY position m_request.type = ORDER_TYPE_SELL; m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); } else { // // prepare request for close SELL position m_request.type = ORDER_TYPE_BUY; m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); } } else { // // position not found m_result.retcode = retcode; return (false); } // // check volume double position_volume = PositionGetDouble(POSITION_VOLUME); if (position_volume > volume) { position_volume = volume; } // // setting request m_request.action = TRADE_ACTION_DEAL; m_request.symbol = symbol; m_request.volume = position_volume; m_request.magic = m_magic; m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; m_request.position = PositionGetInteger(POSITION_TICKET); // // Specifieng Comment ... m_request.comment = comment; // // hedging? just send order return (OrderSend(m_request, m_result)); } bool PositionClosePartial( const ulong ticket, // Position Ticket const double volume, // Partial Closing Volume const ulong deviation, // Deviation const string comment = "" // Comment For Close ) { // // check stopped if (IsStopped(__FUNCTION__)) { return (false); } // // for hedging mode only if (!IsHedging()) { return (false); } // // check position existence if (!PositionSelectByTicket(ticket)) { return (false); } // string symbol = PositionGetString(POSITION_SYMBOL); // // clean ClearStructures(); // // check filling if (!FillingCheck(symbol)) { return (false); } // // check if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { // // prepare request for close BUY position m_request.type = ORDER_TYPE_SELL; m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); } else { // // prepare request for close SELL position m_request.type = ORDER_TYPE_BUY; m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); } // // check volume double position_volume = PositionGetDouble(POSITION_VOLUME); if (position_volume > volume) { position_volume = volume; } // // setting request m_request.action = TRADE_ACTION_DEAL; m_request.position = ticket; m_request.symbol = symbol; m_request.volume = position_volume; m_request.magic = m_magic; m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; // // Specifieng Comment ... m_request.comment = comment; // // close position return (OrderSend(m_request, m_result)); } }; // // END Overrides ... // // // XCMD5 a library for Hashing ... class XCMD5 { // // Public Provides ... public: // // Protected Provides ... // // Constructor ... XCMD5(void) {} // // Deconstructor ... ~XCMD5(void) {} // // Hash Specified Char Array ... string Hash( uchar &source[], // Specify Char Array to Hash int length = 0 // Specify Length of Char Array which required to hash ) { // string result = ""; // int sourceCount = ArraySize(source); // // Validate Args ... if ( sourceCount <= 0 || (sourceCount > 0 && length > sourceCount)) { return result; } // // Normalize Args ... if (length == 0) { length = sourceCount; } // // Init MD5 ... MD5Init(); // // Update Buffer ... MD5Update(source, length); // // Calculate Result ... result = MD5Final(); // return result; } // // Hash Specified String ... string Hash( string source // Specified String ) { // string result = ""; // // Converts String to Char Array ... uchar bytes[]; StringToCharArray( source, bytes, 0, StringLen(source)); // result = Hash( bytes, ArraySize(bytes)); // return result; } protected: // // Private Provides ... private: // uint m_lMD5[4]; uint m_nCount[2]; uchar m_lpszBuffer[64]; // // Convert Byte to DWord ... void ByteToDWord(int &out[], uint &in[], uint len) { // uint i = 0; uint j = 0; // for (; j < len; i++, j += 4) { out[i] = (int)in[j] | (int)in[j + 1] << 8 | (int)in[j + 2] << 16 | (int)in[j + 3] << 24; } } // // Convert DWord to Byte ... void DWordToByte(uchar &out[], int &in[], uint len) { // uint i = 0; uint j = 0; // for (; j < len; i++, j += 4) { // out[j] = (uchar)(in[i] & 0xff); out[j + 1] = (uchar)((in[i] >> 8) & 0xff); out[j + 2] = (uchar)((in[i] >> 16) & 0xff); out[j + 3] = (uchar)((in[i] >> 24) & 0xff); } } // // Init MD5 Array ... void MD5Init() { // ArrayInitialize(m_lpszBuffer, 64); // m_nCount[0] = m_nCount[1] = 0; m_lMD5[0] = _md5_INIT_STATE_0; m_lMD5[1] = _md5_INIT_STATE_1; m_lMD5[2] = _md5_INIT_STATE_2; m_lMD5[3] = _md5_INIT_STATE_3; } // // Update MD5 ... void MD5Update(uchar &inBuf[], uint inLen) { // int i, ii; int mdi; // uint in[16]; int i0 = 0; // mdi = (int)((m_nCount[0] >> 3) & 0x3F); // if ((m_nCount[0] + ((uint)inLen << 3)) < m_nCount[0]) { m_nCount[1]++; } // m_nCount[0] += ((uint)inLen << 3); m_nCount[1] += ((uint)inLen >> 29); // while ((inLen--) > 0) { // m_lpszBuffer[mdi++] = inBuf[i0++]; if (mdi == 0x40) { // for (i = 0, ii = 0; i < 16; i++, ii += 4) { in[i] = (((uint)m_lpszBuffer[ii + 3]) << 24) | (((uint)m_lpszBuffer[ii + 2]) << 16) | (((uint)m_lpszBuffer[ii + 1]) << 8) | ((uint)m_lpszBuffer[ii]); } // Transform(m_lMD5, in); // mdi = 0; } } } // // Finalize an MD5 Expression ... string MD5Final() { // uchar bits[8]; int nIndex; uint nPadLen; const int nMD5Size = 16; uchar lpszMD5[16]; string temp; string out = ""; int i; // DWordToByte(bits, m_nCount, 8); nIndex = (int)((m_nCount[0] >> 3) & 0x3f); nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex); MD5Update(_md5_PADDING, nPadLen); MD5Update(bits, 8); DWordToByte(lpszMD5, m_lMD5, nMD5Size); // for (i = 0; i < nMD5Size; i++) { // if (lpszMD5[i] == 0) { temp = "00"; } else if (lpszMD5[i] <= 15) { temp = StringFormat("0%x", lpszMD5[i]); } else { temp = StringFormat("%x", lpszMD5[i]); } // out += temp; } // lpszMD5[0] = '\0'; // return (out); } // // Transform Buffers ... void Transform(uint &buf[], uint &in[]) { // uint a = buf[0], b = buf[1], c = buf[2], d = buf[3]; // _md5_FF(a, b, c, d, in[0], _md5_S11, 0xD76AA478); _md5_FF(d, a, b, c, in[1], _md5_S12, 0xE8C7B756); _md5_FF(c, d, a, b, in[2], _md5_S13, 0x242070DB); _md5_FF(b, c, d, a, in[3], _md5_S14, 0xC1BDCEEE); _md5_FF(a, b, c, d, in[4], _md5_S11, 0xF57C0FAF); _md5_FF(d, a, b, c, in[5], _md5_S12, 0x4787C62A); _md5_FF(c, d, a, b, in[6], _md5_S13, 0xA8304613); _md5_FF(b, c, d, a, in[7], _md5_S14, 0xFD469501); _md5_FF(a, b, c, d, in[8], _md5_S11, 0x698098D8); _md5_FF(d, a, b, c, in[9], _md5_S12, 0x8B44F7AF); _md5_FF(c, d, a, b, in[10], _md5_S13, 0xFFFF5BB1); _md5_FF(b, c, d, a, in[11], _md5_S14, 0x895CD7BE); _md5_FF(a, b, c, d, in[12], _md5_S11, 0x6B901122); _md5_FF(d, a, b, c, in[13], _md5_S12, 0xFD987193); _md5_FF(c, d, a, b, in[14], _md5_S13, 0xA679438E); _md5_FF(b, c, d, a, in[15], _md5_S14, 0x49B40821); // _md5_GG(a, b, c, d, in[1], _md5_S21, 0xF61E2562); _md5_GG(d, a, b, c, in[6], _md5_S22, 0xC040B340); _md5_GG(c, d, a, b, in[11], _md5_S23, 0x265E5A51); _md5_GG(b, c, d, a, in[0], _md5_S24, 0xE9B6C7AA); _md5_GG(a, b, c, d, in[5], _md5_S21, 0xD62F105D); _md5_GG(d, a, b, c, in[10], _md5_S22, 0x02441453); _md5_GG(c, d, a, b, in[15], _md5_S23, 0xD8A1E681); _md5_GG(b, c, d, a, in[4], _md5_S24, 0xE7D3FBC8); _md5_GG(a, b, c, d, in[9], _md5_S21, 0x21E1CDE6); _md5_GG(d, a, b, c, in[14], _md5_S22, 0xC33707D6); _md5_GG(c, d, a, b, in[3], _md5_S23, 0xF4D50D87); _md5_GG(b, c, d, a, in[8], _md5_S24, 0x455A14ED); _md5_GG(a, b, c, d, in[13], _md5_S21, 0xA9E3E905); _md5_GG(d, a, b, c, in[2], _md5_S22, 0xFCEFA3F8); _md5_GG(c, d, a, b, in[7], _md5_S23, 0x676F02D9); _md5_GG(b, c, d, a, in[12], _md5_S24, 0x8D2A4C8A); // _md5_HH(a, b, c, d, in[5], _md5_S31, 0xFFFA3942); _md5_HH(d, a, b, c, in[8], _md5_S32, 0x8771F681); _md5_HH(c, d, a, b, in[11], _md5_S33, 0x6D9D6122); _md5_HH(b, c, d, a, in[14], _md5_S34, 0xFDE5380C); _md5_HH(a, b, c, d, in[1], _md5_S31, 0xA4BEEA44); _md5_HH(d, a, b, c, in[4], _md5_S32, 0x4BDECFA9); _md5_HH(c, d, a, b, in[7], _md5_S33, 0xF6BB4B60); _md5_HH(b, c, d, a, in[10], _md5_S34, 0xBEBFBC70); _md5_HH(a, b, c, d, in[13], _md5_S31, 0x289B7EC6); _md5_HH(d, a, b, c, in[0], _md5_S32, 0xEAA127FA); _md5_HH(c, d, a, b, in[3], _md5_S33, 0xD4EF3085); _md5_HH(b, c, d, a, in[6], _md5_S34, 0x04881D05); _md5_HH(a, b, c, d, in[9], _md5_S31, 0xD9D4D039); _md5_HH(d, a, b, c, in[12], _md5_S32, 0xE6DB99E5); _md5_HH(c, d, a, b, in[15], _md5_S33, 0x1FA27CF8); _md5_HH(b, c, d, a, in[2], _md5_S34, 0xC4AC5665); // _md5_II(a, b, c, d, in[0], _md5_S41, 0xF4292244); _md5_II(d, a, b, c, in[7], _md5_S42, 0x432AFF97); _md5_II(c, d, a, b, in[14], _md5_S43, 0xAB9423A7); _md5_II(b, c, d, a, in[5], _md5_S44, 0xFC93A039); _md5_II(a, b, c, d, in[12], _md5_S41, 0x655B59C3); _md5_II(d, a, b, c, in[3], _md5_S42, 0x8F0CCC92); _md5_II(c, d, a, b, in[10], _md5_S43, 0xFFEFF47D); _md5_II(b, c, d, a, in[1], _md5_S44, 0x85845DD1); _md5_II(a, b, c, d, in[8], _md5_S41, 0x6FA87E4F); _md5_II(d, a, b, c, in[15], _md5_S42, 0xFE2CE6E0); _md5_II(c, d, a, b, in[6], _md5_S43, 0xA3014314); _md5_II(b, c, d, a, in[13], _md5_S44, 0x4E0811A1); _md5_II(a, b, c, d, in[4], _md5_S41, 0xF7537E82); _md5_II(d, a, b, c, in[11], _md5_S42, 0xBD3AF235); _md5_II(c, d, a, b, in[2], _md5_S43, 0x2AD7D2BB); _md5_II(b, c, d, a, in[9], _md5_S44, 0xEB86D391); // buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } }; // // 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) ... // -------------------------- // ACCOUNT_TRADE_MODE_DEMO // ACCOUNT_TRADE_MODE_CONTEST // ACCOUNT_TRADE_MODE_REAL ENUM_ACCOUNT_TRADE_MODE GetTradeMode() { return mAccountInfo.TradeMode(); } // // Get Account Balance ... double GetBalance() { return mAccountInfo.Balance(); } // // Get 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; }; // // XSaherElm Report Info Class ... class XCReporter { // // Public Provided ... public: // // Constructro ... void XCReporter() { // mAccountInfo = new XCAccountInfo(); // ResetReports(); } // // Deconstructor ... void ~XCReporter() { } // // Reset Specific Report ... void ResetReport( ENUM_XREPORT_TYPES type // Specify Report Type ) { CleanReport(type); } // // Reset All Reports ... void ResetReports() { // CleanReport(XREPORT_MAIN); CleanReport(XREPORT_MONTHLY); CleanReport(XREPORT_WEEKLY); CleanReport(XREPORT_DAILY); } // // Update Volume Info ... void UpdateReportVolumeInfo( ENUM_XREPORT_TYPES type, // Specified Report Type // double staticVolume, // Current Available Static Volume string staticVolumeCalculationMethod, // Static Volume Calculation Method double maxAllowedVolume, // Current Maximum Appliable Volume double volumeIncreaseMultiplier, // Static Volume Increase Multiplier double balanceGowingToApplyMultiplier, // Multiply Volume Based On Balance Growing double balanceGrowingToIncreaseMaxAllowedVolume // Where to Increase MaxAllowed Volume ) { // // Filling Account Info ... FillReportAccountInfo(type); // switch (type) { // // Main ... case XREPORT_MAIN: // FillingVolumeInfo( mMainReport, staticVolume, staticVolumeCalculationMethod, maxAllowedVolume, volumeIncreaseMultiplier, balanceGowingToApplyMultiplier, balanceGrowingToIncreaseMaxAllowedVolume); break; // // Monthly ... case XREPORT_MONTHLY: // FillingVolumeInfo( mMonthlyReport, staticVolume, staticVolumeCalculationMethod, maxAllowedVolume, volumeIncreaseMultiplier, balanceGowingToApplyMultiplier, balanceGrowingToIncreaseMaxAllowedVolume); break; // // Weekly ... case XREPORT_WEEKLY: // FillingVolumeInfo( mWeeklyReport, staticVolume, staticVolumeCalculationMethod, maxAllowedVolume, volumeIncreaseMultiplier, balanceGowingToApplyMultiplier, balanceGrowingToIncreaseMaxAllowedVolume); break; // // Daily ... case XREPORT_DAILY: // FillingVolumeInfo( mDailyReport, staticVolume, staticVolumeCalculationMethod, maxAllowedVolume, volumeIncreaseMultiplier, balanceGowingToApplyMultiplier, balanceGrowingToIncreaseMaxAllowedVolume); break; } } // // Update Volume Info on All Reports ... void UpdateReportsVolumeInfo( double staticVolume, // Current Available Static Volume string staticVolumeCalculationMethod, // Static Volume Calculation Method double maxAllowedVolume, // Current Maximum Appliable Volume double volumeIncreaseMultiplier, // Static Volume Increase Multiplier double balanceGowingToApplyMultiplier, // Multiply Volume Based On Balance Growing double balanceGrowingToIncreaseMaxAllowedVolume // Where to Increase MaxAllowed Volume ) { // // Main ... UpdateReportVolumeInfo( XREPORT_MAIN, staticVolume, staticVolumeCalculationMethod, maxAllowedVolume, volumeIncreaseMultiplier, balanceGowingToApplyMultiplier, balanceGrowingToIncreaseMaxAllowedVolume); // // Monthly ... UpdateReportVolumeInfo( XREPORT_MONTHLY, staticVolume, staticVolumeCalculationMethod, maxAllowedVolume, volumeIncreaseMultiplier, balanceGowingToApplyMultiplier, balanceGrowingToIncreaseMaxAllowedVolume); // // Weekly ... UpdateReportVolumeInfo( XREPORT_WEEKLY, staticVolume, staticVolumeCalculationMethod, maxAllowedVolume, volumeIncreaseMultiplier, balanceGowingToApplyMultiplier, balanceGrowingToIncreaseMaxAllowedVolume); // // Daily ... UpdateReportVolumeInfo( XREPORT_DAILY, staticVolume, staticVolumeCalculationMethod, maxAllowedVolume, volumeIncreaseMultiplier, balanceGowingToApplyMultiplier, balanceGrowingToIncreaseMaxAllowedVolume); } // // Add Specific Signal to Report ... void AddSignalToReport( ENUM_XREPORT_TYPES type, // Specified Report Type const XSignal &signal, // Specified Signal const string &providers[] // Specified Signal Providers ) { // // // Filling Account Info ... FillReportAccountInfo(type); // switch (type) { // // Main ... case XREPORT_MAIN: AddSignalToReport( mMainReport, signal, providers); break; // // Monthly ... case XREPORT_MONTHLY: AddSignalToReport( mMonthlyReport, signal, providers); break; // // Weekly ... case XREPORT_WEEKLY: AddSignalToReport( mWeeklyReport, signal, providers); break; // // Daily ... case XREPORT_DAILY: AddSignalToReport( mDailyReport, signal, providers); break; } } // // Add Specific Signal to All Reports ... void AddSignalToReports( const XSignal &signal, // Specified Signal const string &providers[] // Specified Signal Providers ) { // // Main ... AddSignalToReport( XREPORT_MAIN, signal, providers); // // Monthly ... AddSignalToReport( XREPORT_MONTHLY, signal, providers); // // Weekly ... AddSignalToReport( XREPORT_WEEKLY, signal, providers); // // Daily ... AddSignalToReport( XREPORT_DAILY, signal, providers); } // // Report a TP for Specific Report ... void AddTradeTPInReport( ENUM_XREPORT_TYPES type // Specified Report Type ) { // switch (type) { // // Main ... case XREPORT_MAIN: AddTradeTPInReport(mMainReport); break; // // Monthly ... case XREPORT_MONTHLY: AddTradeTPInReport(mMonthlyReport); break; // // Weekly ... case XREPORT_WEEKLY: AddTradeTPInReport(mWeeklyReport); break; // // Daily ... case XREPORT_DAILY: AddTradeTPInReport(mDailyReport); break; } } // // Report a TP for All Reports ... void AddTradeTPInReports() { // // Main ... AddTradeTPInReport(XREPORT_MAIN); // // Monthly ... AddTradeTPInReport(XREPORT_MONTHLY); // // Weekly ... AddTradeTPInReport(XREPORT_WEEKLY); // // Daily ... AddTradeTPInReport(XREPORT_DAILY); } // // Report a SL for Specific Report ... void AddTradeSLInReport( ENUM_XREPORT_TYPES type // Specified Report Type ) { // switch (type) { // // Main ... case XREPORT_MAIN: AddTradeSLInReport(mMainReport); break; // // Monthly ... case XREPORT_MONTHLY: AddTradeSLInReport(mMonthlyReport); break; // // Weekly ... case XREPORT_WEEKLY: AddTradeSLInReport(mWeeklyReport); break; // // Daily ... case XREPORT_DAILY: AddTradeSLInReport(mDailyReport); break; } } // // Report a SL for All Reports ... void AddTradeSLInReports() { // // Main ... AddTradeSLInReport(XREPORT_MAIN); // // Monthly ... AddTradeSLInReport(XREPORT_MONTHLY); // // Weekly ... AddTradeSLInReport(XREPORT_WEEKLY); // // Daily ... AddTradeSLInReport(XREPORT_DAILY); } // // Update Number of Same Time Trades in Specific Report ... void UpdateMaxSameTimeTradesInReport( ENUM_XREPORT_TYPES type, // Specified Report Type int value // number of same time trades ) { // switch (type) { // // Main ... case XREPORT_MAIN: UpdateMaxSameTimeTradesInReport( mMainReport, value); break; // // Monthly ... case XREPORT_MONTHLY: UpdateMaxSameTimeTradesInReport( mMonthlyReport, value); break; // // Weekly ... case XREPORT_WEEKLY: UpdateMaxSameTimeTradesInReport( mWeeklyReport, value); break; // // Daily ... case XREPORT_DAILY: UpdateMaxSameTimeTradesInReport( mDailyReport, value); break; } } // // Update Number of Same Time Trades in All Report ... void UpdateMaxSameTimeTradesInReports( int value // number of same time trades ) { // // Main ... UpdateMaxSameTimeTradesInReport( XREPORT_MAIN, value); // // Monthly ... UpdateMaxSameTimeTradesInReport( XREPORT_MONTHLY, value); // // Weekly ... UpdateMaxSameTimeTradesInReport( XREPORT_WEEKLY, value); // // Daily ... UpdateMaxSameTimeTradesInReport( XREPORT_DAILY, value); } // // Update Max DrawDown in Specific Report ... void UpdateMaxDrawDownInReport( ENUM_XREPORT_TYPES type, // Specified Report Type double value // draw down value ) { // switch (type) { // // Main ... case XREPORT_MAIN: UpdateMaxDrawDownInReport( mMainReport, value); break; // // Monthly ... case XREPORT_MONTHLY: UpdateMaxDrawDownInReport( mMonthlyReport, value); break; // // Weekly ... case XREPORT_WEEKLY: UpdateMaxDrawDownInReport( mWeeklyReport, value); break; // // Daily ... case XREPORT_DAILY: UpdateMaxDrawDownInReport( mDailyReport, value); break; } } // // Update Max DrawDown in All Report ... void UpdateMaxDrawDownInReports( double value // draw down value ) { // // Main ... UpdateMaxDrawDownInReport( XREPORT_MAIN, value); // // Monthly ... UpdateMaxDrawDownInReport( XREPORT_MONTHLY, value); // // Weekly ... UpdateMaxDrawDownInReport( XREPORT_WEEKLY, value); // // Daily ... UpdateMaxDrawDownInReport( XREPORT_DAILY, value); } // // Update Max DrawUp in Specific Report ... void UpdateMaxDrawUpInReport( ENUM_XREPORT_TYPES type, // Specified Report Type double value // draw up value ) { // switch (type) { // // Main ... case XREPORT_MAIN: UpdateMaxDrawUpInReport( mMainReport, value); break; // // Monthly ... case XREPORT_MONTHLY: UpdateMaxDrawUpInReport( mMonthlyReport, value); break; // // Weekly ... case XREPORT_WEEKLY: UpdateMaxDrawUpInReport( mWeeklyReport, value); break; // // Daily ... case XREPORT_DAILY: UpdateMaxDrawUpInReport( mDailyReport, value); break; } } // // Update Max DrawUp in All Report ... void UpdateMaxDrawUpInReports( double value // draw up value ) { // // Main ... UpdateMaxDrawUpInReport( XREPORT_MAIN, value); // // Monthly ... UpdateMaxDrawUpInReport( XREPORT_MONTHLY, value); // // Weekly ... UpdateMaxDrawUpInReport( XREPORT_WEEKLY, value); // // Daily ... UpdateMaxDrawUpInReport( XREPORT_DAILY, value); } // // Update Min Balance for Open Trades in Specific Report ... void UpdateMinBalanceForOpenTradesInReport( ENUM_XREPORT_TYPES type, // Specified Report Type double value // min balance for open trades ) { // switch (type) { // // Main ... case XREPORT_MAIN: UpdateMinBalanceForOpenTradesInReport( mMainReport, value); break; // // Monthly ... case XREPORT_MONTHLY: UpdateMinBalanceForOpenTradesInReport( mMonthlyReport, value); break; // // Weekly ... case XREPORT_WEEKLY: UpdateMinBalanceForOpenTradesInReport( mWeeklyReport, value); break; // // Daily ... case XREPORT_DAILY: UpdateMinBalanceForOpenTradesInReport( mDailyReport, value); break; } } // // Update Min Balance for Open Trades in All Report ... void UpdateMinBalanceForOpenTradesInReports( double value // min balance for open trades ) { // // Main ... UpdateMinBalanceForOpenTradesInReport( XREPORT_MAIN, value); // // Monthly ... UpdateMinBalanceForOpenTradesInReport( XREPORT_MONTHLY, value); // // Weekly ... UpdateMinBalanceForOpenTradesInReport( XREPORT_WEEKLY, value); // // Daily ... UpdateMinBalanceForOpenTradesInReport( XREPORT_DAILY, value); } // // Gnerate Specific Type Of Report String Representation ... string GenerateReportString( ENUM_XREPORT_TYPES type, // Specified Report Type string separator = "\n" // Separator ) { // string result = ""; // switch (type) { // // Main ... case XREPORT_MAIN: result = GenerateReportString( mMainReport, separator); break; // // Monthly ... case XREPORT_MONTHLY: result = GenerateReportString( mMonthlyReport, separator); break; // // Weekly ... case XREPORT_WEEKLY: result = GenerateReportString( mWeeklyReport, separator); break; // // Daily ... case XREPORT_DAILY: result = GenerateReportString( mDailyReport, separator); break; } // return result; } // // Protected Provided ... protected: // // Private Provided ... private: // // Account Info Instance ... XCAccountInfo mAccountInfo; // // Main Report ... XReport mMainReport; // // Monthly Report ... XReport mMonthlyReport; // // Weekly Report ... XReport mWeeklyReport; // // Daily Report ... XReport mDailyReport; // // Clean Specific Report ... void CleanReport( XReport &report // Specified Report ) { // datetime time = TimeCurrent(); // // Reset Times ... report.start = time; report.end = -1; // // Reset Account Info ... FillReportAccountInfo(report); // // Reset Summary Info ... report.summaryInfo.maxDrawUp = 0; report.summaryInfo.maxDrawDown = 0; report.summaryInfo.longSignals = 0; report.summaryInfo.numberOfTPs = 0; report.summaryInfo.numberOfSLs = 0; report.summaryInfo.shortSignals = 0; report.summaryInfo.maxSignalVolume = 0; report.summaryInfo.maxSameTimeSignals = 0; // // Reset Volume Info ... report.volumeInfo.staticVolume = 0; report.volumeInfo.maxAllowedVolume = 0; report.volumeInfo.volumeIncreaseMultiplier = 0; report.volumeInfo.balanceGowingToApplyMultiplier = 0; report.volumeInfo.staticVolumeCalculationMethod = NULL; report.volumeInfo.balanceGrowingToIncreaseMaxAllowedVolume = 0; // // Reset Signallers Info ... CleanBuffer(report.signallersInfo); } void CleanReport( ENUM_XREPORT_TYPES type // Specify Report Type ) { // switch (type) { // // Main ... case XREPORT_MAIN: CleanReport(mMainReport); break; // // Monthly ... case XREPORT_MONTHLY: CleanReport(mMonthlyReport); break; // // Weekly ... case XREPORT_WEEKLY: CleanReport(mWeeklyReport); break; // // Daily ... case XREPORT_DAILY: CleanReport(mDailyReport); break; } } // // Update Specific Reports End Time ... void FillReportEndTime( XReport &report // Specified Report ) { // datetime time = TimeCurrent(); report.end = time; } // // Filleing Report Account Info ... void FillReportAccountInfo( XReport &report // Specified Report ) { // FillReportEndTime(report); // report.accountInfo.user = (string)mAccountInfo.GetUserAccount(); report.accountInfo.name = mAccountInfo.GetName(); report.accountInfo.server = mAccountInfo.GetServerName(); report.accountInfo.broker = mAccountInfo.GetCompany(); report.accountInfo.mode = mAccountInfo.GetTradeMode(); report.accountInfo.leverage = mAccountInfo.GetLeverage(); report.accountInfo.currency = mAccountInfo.GetCurrency(); report.accountInfo.deposit = mAccountInfo.GetInitialBalance(); report.accountInfo.balance = mAccountInfo.GetBalance(); } void FillReportAccountInfo( ENUM_XREPORT_TYPES type // Specify Report Type ) { // switch (type) { // // Main ... case XREPORT_MAIN: FillReportAccountInfo(mMainReport); break; // // Monthly ... case XREPORT_MONTHLY: FillReportAccountInfo(mMonthlyReport); break; // // Weekly ... case XREPORT_WEEKLY: FillReportAccountInfo(mWeeklyReport); break; // // Daily ... case XREPORT_DAILY: FillReportAccountInfo(mDailyReport); break; } } // // Filling Volume Info ... void FillingVolumeInfo( XReport &report, // Specified Report // double staticVolume, // Current Available Static Volume string staticVolumeCalculationMethod, // Static Volume Calculation Method double maxAllowedVolume, // Current Maximum Appliable Volume double volumeIncreaseMultiplier, // Static Volume Increase Multiplier double balanceGowingToApplyMultiplier, // Multiply Volume Based On Balance Growing double balanceGrowingToIncreaseMaxAllowedVolume // Where to Increase MaxAllowed Volume ) { // FillReportEndTime(report); // report.volumeInfo.staticVolume = staticVolume; report.volumeInfo.maxAllowedVolume = maxAllowedVolume; report.volumeInfo.volumeIncreaseMultiplier = volumeIncreaseMultiplier; report.volumeInfo.staticVolumeCalculationMethod = staticVolumeCalculationMethod; report.volumeInfo.balanceGowingToApplyMultiplier = balanceGowingToApplyMultiplier; report.volumeInfo.balanceGrowingToIncreaseMaxAllowedVolume = balanceGrowingToIncreaseMaxAllowedVolume; } // // Add Signal to Report ... void AddSignalToReport( XReport &report, // Specified Report const XSignal &signal, // Specified Signal const string &providers[] // Specified Signal Providers ) { // FillReportEndTime(report); // double volume = signal.volume; bool isLong = signal.type == X_SIGNAL_LONG; // // Update Longs and Shorts ... if (isLong) { report.summaryInfo.longSignals++; } else { report.summaryInfo.shortSignals++; } // // Chack Max Volume ... if (volume > report.summaryInfo.maxSignalVolume) { report.summaryInfo.maxSignalVolume = volume; } // // Update Signallers Info ... for (int i = 0; i < ArraySize(providers); i++) { // string iProvider = providers[i]; // AddOrUpdateSignaller( report, iProvider, signal); } } // // Add or Update Signaller Info of Specific Report ... void AddOrUpdateSignaller( XReport &report, // Specified Report const string provider, // Signal Provider name const XSignal &signal // Specified Signal ) { // int providerIdx = -1; int signallersInfoCount = 0; bool isLong = signal.type == X_SIGNAL_LONG; // // Prepare New One Provider ... XSignallerInfo info = {}; info.name = provider; if (isLong) { info.longs = 1; } else { info.shorts = 1; } // // Find Provider idx if Exists ... providerIdx = FindProviderInSignallersInfo( provider, report.signallersInfo); // // Check IDX ... if (providerIdx > -1) { // // Update Exists ... if (isLong) { report.signallersInfo[providerIdx].longs++; } else { report.signallersInfo[providerIdx].shorts++; } } else { // // Add New One ... Add( info, report.signallersInfo); } } // // Add TP in Report ... void AddTradeTPInReport( XReport &report // Specified Report ) { // FillReportEndTime(report); // report.summaryInfo.numberOfTPs++; } // // Add SL in Report ... void AddTradeSLInReport( XReport &report // Specified Report ) { // FillReportEndTime(report); // report.summaryInfo.numberOfSLs++; } // // Update Number of Same Time Trades in Report ... void UpdateMaxSameTimeTradesInReport( XReport &report, // Specified Report int value // number of same time trades ) { // // Validate Args ... if (value <= report.summaryInfo.maxSameTimeSignals) { return; } // FillReportEndTime(report); // report.summaryInfo.maxSameTimeSignals = value; } // // Update Number of Same Time Trades in Report ... void UpdateMaxDrawUpInReport( XReport &report, // Specified Report double value // draw up value ) { // // Validate Args ... if (value <= report.summaryInfo.maxDrawUp) { return; } // FillReportEndTime(report); // report.summaryInfo.maxDrawUp = value; } // // Update Number of Same Time Trades in Report ... void UpdateMaxDrawDownInReport( XReport &report, // Specified Report double value // draw down value ) { // // Validate Args ... if (value <= report.summaryInfo.maxDrawDown) { return; } // FillReportEndTime(report); // report.summaryInfo.maxDrawDown = value; } // // Update Min Balance for Open Trades Value in Report ... void UpdateMinBalanceForOpenTradesInReport( XReport &report, // Specified Report double value // min balance for open trades ) { // // Validate Arg ... if (value <= 0) { return; } // FillReportEndTime(report); // report.accountInfo.minBalanceForOpenTrades = value; } // // Generate Specific Report String Representation ... string GenerateReportString( XReport &report, // Specified Report string separator = "\n" // Separator ) { // string result = ""; // // Start and End Date ... result += "Start: " + (string)report.start + separator; result += "End: " + (string)report.end + separator; // // Account Info ... string accountStr = GenerateAccountInfoReportString(report.accountInfo); result += "Account: " + separator + accountStr + separator; // // Summary Info ... string summaryStr = GenerateSummaryInfoReportString(report.summaryInfo); result += "Summary: " + separator + summaryStr + separator; // // Volume Info ... string volumeStr = GenerateVolumeInfoReportString(report.volumeInfo); result += "Volume: " + separator + volumeStr + separator; // // Signallers Info ... string signallersStr = GenerateSignallersInfoReportString(report.signallersInfo); result += "Signallers: " + separator + signallersStr + separator; // return result; } // // Generate Account info String Representation ... string GenerateAccountInfoReportString( XAccountInfo &info, // Specified Account Info string separator = "\n" // Separator ) { // string result = ""; // // Generate Report ... result += "user: " + info.user + separator; result += "name: " + info.name + separator; result += "server: " + info.server + separator; result += "broker: " + info.broker + separator; result += "mode: " + EnumToString(info.mode) + separator; result += "leverage: " + (string)info.leverage + separator; result += "currency: " + info.currency + separator; result += "deposit: " + (string)info.deposit + separator; result += "balance: " + (string)info.balance + separator; result += "minBalanceForTrading: " + (string)info.minBalanceForOpenTrades + separator; // return result; } // // Generate Summary info String Representation ... string GenerateSummaryInfoReportString( XSummaryInfo &info, // Specified Summary Info string separator = "\n" // Separator ) { // string result = ""; // // Generate Report ... result += "longSignals: " + (string)info.longSignals + separator; result += "shortSignals: " + (string)info.shortSignals + separator; result += "numberOfTps: " + (string)info.numberOfTPs + separator; result += "numberOfSLs: " + (string)info.numberOfSLs + separator; result += "maxDrawUp: " + (string)info.maxDrawUp + separator; result += "maxDrawDown: " + (string)info.maxDrawDown + separator; result += "maxSignalVolume: " + (string)info.maxSignalVolume + separator; result += "maxSameTimeSignals: " + (string)info.maxSameTimeSignals + separator; // return result; } // // Generate Volume info String Representation ... string GenerateVolumeInfoReportString( XVolumeInfo &info, // Specified Volume Info string separator = "\n" // Separator ) { // string result = ""; // // Generate Report ... result += "staticVolume: " + (string)info.staticVolume + separator; result += "staticVolumeCalculationMethod: " + info.staticVolumeCalculationMethod + separator; result += "maxAllowedVolume: " + (string)info.maxAllowedVolume + separator; result += "volumeIncreaseMultiplier: " + (string)info.volumeIncreaseMultiplier + separator; result += "balanceGowingToApplyMultiplier: " + (string)info.balanceGowingToApplyMultiplier + separator; result += "balanceGrowingToIncreaseMaxAllowedVolume: " + (string)info.balanceGrowingToIncreaseMaxAllowedVolume + separator; // return result; } // // Generate Signallers info String Representation ... string GenerateSignallersInfoReportString( XSignallerInfo &infos[], // Specified Signallers Info string separator = "\n" // Separator ) { // string result = ""; // // Validate Signallers Array Size ... int signallersCount = ArraySize(infos); if (signallersCount <= 0) { // result += "EMPTY" + separator; return result; } // // Generate Report ... for (int i = 0; i < signallersCount; i++) { // XSignallerInfo iSignaller = infos[i]; // result += "name: " + iSignaller.name + separator; result += "longs: " + (string)iSignaller.longs + separator; result += "shorts: " + (string)iSignaller.shorts + separator; // if (i < signallersCount - 1) { result += separator; } } // return result; } // // Add New SignallerInfo to List ... void Add( XSignallerInfo &item, XSignallerInfo &buffer[]) { // ArrayResize( buffer, ArraySize(buffer) + 1); // buffer[ArraySize(buffer) - 1] = item; } // // Clean Signaller Info Buffer ... void CleanBuffer(XSignallerInfo &buffer[]) { // ArrayFree(buffer); ArrayResize(buffer, 0); } // // Copy Signaller Info ... void CopyBuffer( const XSignallerInfo &source[], // Source Buffer ... XSignallerInfo &dest[] // Dest Buffer ... ) { // CleanBuffer(dest); // int sourceCount = ArraySize(source); if (sourceCount <= 0) { return; } // // Loop ... for (int i = 0; i < sourceCount; i++) { // XSignallerInfo iInfo = source[i]; // Add( iInfo, dest); } } // // Find a Provider Index in SignallersInfo ... int FindProviderInSignallersInfo( string provider, // Specified Provider Name ... XSignallerInfo &infoBuffer[] // Specified XSignallerInfo Buffer ... ) { // int result = -1; // int bufferSize = ArraySize(infoBuffer); if (bufferSize <= 0) { return result; } // // Loop through buffer to find provider index ... for (int i = 0; i < bufferSize; i++) { // XSignallerInfo iInfo = infoBuffer[i]; // if (iInfo.name != provider) { continue; } // result = i; } // return result; } }; // // a Class For Managing Signals Additional Data ... class XCSignalManager { // // Public ... public: // // Constructor ... XCSignalManager(void) { CleanData(); } // // Deconstructor ... ~XCSignalManager(void) {} // // Retrieve All Signals ... void GetAll( XSignal &result[] // Hold's Result ) { // CleanBuffer(result); // int signalsCount = ArraySize(mSignals); if (signalsCount <= 0) { return; } // for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = mSignals[i]; // AddItemToBuffer( iSignal, result); } } // // Count Items ... int Count() { return ArraySize(mSignals); } // // Retrieve Specific Signal by Ticket ... XSignal Get( ulong ticket // Signals Ticket ... ) { // XSignal result = {}; // // Check Exists ... bool isExists = IsExists(ticket); if (!isExists) { return result; } // int signalsCount = ArraySize(mSignals); if (signalsCount <= 0) { return result; } // for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = mSignals[i]; // if (iSignal.ticket == ticket) { // result = iSignal; break; } } // return result; } // // Check Signal Exists or not ... bool IsExists( ulong ticket // Specified Signal Ticket ) { // bool result = false; // int signalsCount = ArraySize(mSignals); if (signalsCount <= 0) { return result; } // for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = mSignals[i]; // if (iSignal.ticket == ticket) { // result = true; break; } } // return result; } bool IsExists( XSignal &signal // Specified Signal ) { // bool result = false; // int signalsCount = ArraySize(mSignals); if (signalsCount <= 0) { return result; } // for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = mSignals[i]; // if (iSignal.ticket == signal.ticket) { // result = true; break; } } // return result; } // // Add Signal ... bool Add( XSignal &signal // Specified Signal ) { // bool result = false; // // Validate Args ... if (signal.ticket <= 0) { return result; } // // Chekc Signal Exists ... bool isExists = IsExists(signal); if (isExists) { return result; } // AddItemToBuffer( signal, mSignals); result = true; // return result; } // // Update Specific Buffer ... bool Update( XSignal &signal // Specified Signal ) { // bool result = false; // // Validate Args ... if (signal.ticket <= 0) { return result; } // // Chekc Signal Exists ... bool isExists = IsExists(signal); if (!isExists) { return result; } // // Remove Signal ... Remove(signal); // // Add new One ... AddItemToBuffer( signal, mSignals); // result = true; // return result; } // // Remove Signal ... void Remove( ulong ticket // Specified Signal Ticket ) { // // Check Signal Exists ... bool isExists = IsExists(ticket); if (!isExists) { return; } // int signalsCount = ArraySize(mSignals); if (signalsCount <= 0) { return; } // XSignal signals[]; // for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = mSignals[i]; // if (iSignal.ticket != ticket) { AddItemToBuffer( iSignal, signals); } } // // Now we have to Clean All Signals and Replace them by signals[] buffer ... UpdateData(signals); } void Remove( XSignal &signal // Specified Signal ) { // // Check Signal Exists ... bool isExists = IsExists(signal); if (!isExists) { return; } // int signalsCount = ArraySize(mSignals); if (signalsCount <= 0) { return; } // XSignal signals[]; // for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = mSignals[i]; // if (iSignal.ticket != signal.ticket) { AddItemToBuffer( iSignal, signals); } } // // Now we have to Clean All Signals and Replace them by signals[] buffer ... UpdateData(signals); } // // Add Or Update ... bool AddOrUpdate( XSignal &signal // Specified Signal ) { // bool result = false; // // Validate Args ... if (signal.ticket <= 0) { return result; } // // Chekc Signal Exists ... bool isExists = IsExists(signal); if (!isExists) { result = Add(signal); } else { result = Update(signal); } // return result; } // // Protected ... protected: // // Private ... private: // // Holds Signals ... XSignal mSignals[]; // // Clean All Exists Data ... void CleanData() { CleanBuffer(mSignals); } // // Update Data ... void UpdateData( XSignal &source[] // a Buffer which needs to Replace ... ) { // CleanData(); // int sourceCount = ArraySize(source); if (sourceCount <= 0) { return; } // for (int i = 0; i < sourceCount; i++) { // XSignal iSignal = source[i]; // AddItemToBuffer( iSignal, mSignals); } } // void AddItemToBuffer( XSignal &item, XSignal &buffer[]) { // ArrayResize( buffer, ArraySize(buffer) + 1); // buffer[ArraySize(buffer) - 1] = item; } }; // // 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 double minBallanceForOpenTrades, // Specify Minimum Balance for Open Trades double minAllowedFreeMarginForOpenTrades // Specify Minimum Free Marging for Open Trades ) { // mTag = tag; mSymbol = symbol; mSlippage = slippage; mMagicNumber = magicNumber; mMaxAllowedTrades = maxAllowedTrades; mMinBallanceForOpenTrades = minBallanceForOpenTrades; mMinAllowedFreeMarginForOpenTrades = minAllowedFreeMarginForOpenTrades; // mTrader = new XSCTrade(); // mTrader.SetAsyncMode(false); mTrader.SetDeviationInPoints(mSlippage); mTrader.SetExpertMagicNumber(mMagicNumber); // // Setting Log Level ... mTrader.LogLevel(LOG_LEVEL_ERRORS); // mSignalManager = new XCSignalManager(); } // // Deconstructor ... void ~XCTrade() { } // // START Configuring Class Functions ... // // // Update Min Balance For Trading ... bool SetMinBalanceForTradingPrice( double price // Specified Price for use as Min Account Balance for Trading ) { // bool result = false; // // Validate Arg ... result = price > mMinBallanceForOpenTrades; if (!result) { return result; } // mMinBallanceForOpenTrades = price; // return result; } // // END Configuring Class Functions ... // // // START Count ... // // // 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 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; } // // 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; } // // END Count ... // // // START Retrieve ... // // // Retrieve Specified Position by it's Ticket ... XSignal GetSignal( ulong ticket // Specified Ticket ) { // XSignal result = {}; // result = PositionToSignal(ticket); // return result; } // // Get Last Signal ... XSignal GetLastSignal() { // XSignal result = {}; // XSignal signals[]; GetSignals(signals); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return result; } // result = signals[0]; // return result; } // // Retrieve Last Executed Signal ... bool GetLastSignal(XSignal &signal) { // bool result = false; // XSignal signals[]; GetSignals(signals); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return result; } // signal = signals[0]; result = true; // return result; } // // Retrieve All Positions ... void GetSignals( 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 Type Specific Signals ... void GetSignals( XSignal &result[], // Holds Result ... ENUM_X_SIGNAL_TYPE type // Specified Sginal Type ... ) { // CleanBuffer(result); // XSignal signals[]; GetSignals(signals); // int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return; } // // Loop ... for (int i = signalsCount - 1; i >= 0; i--) { // XSignal iSignal = signals[i]; // if (type == X_SIGNAL_UNKNOWN) { Add( iSignal, result); } else if (iSignal.type == type) { Add( iSignal, result); } } } // // Filter Signals By Searching Comments ... void FilterSignals( XSignal &result[], // Holds Result ... const string query, // Search in Comment Qeury ... ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specified Sginal Type ... ) { // CleanBuffer(result); // XSignal signals[]; GetSignals( signals, type); int signalsCount = ArraySize(signals); // // Validate Args ... if ( StringLen(query) <= 0 || signalsCount <= 0) { return; } // // Loop ... for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // int queryPos = StringFind( iSignal.comment, query); bool isContains = queryPos > -1; if (!isContains) { continue; } // Add( iSignal, result); } } // // Get All Trades Which Candle Passed after Open ... void GetOldSignals( XSignal &result[], // Holds Result int life, // Max Candle Passed after Trades Open ENUM_TIMEFRAMES period = NULL, // Calculate Candles based on time frame ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions ) { // CleanBuffer(result); // // Normalize Period ... if (period == NULL) { period = _Period; } // XSignal signals[]; GetSignals( signals, type); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return; } // // Current Time Frame Candle Index ... int currentBarIndex = 0; // // Loop through Positions ... for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // // Retrieve Trade Open Bar Index based on Current Period ... int tradeOpenBarIndex = iBarShift( mSymbol, period, iSignal.time); // // Calculate Trade Life ... int diff = MathAbs(currentBarIndex - tradeOpenBarIndex); // bool isPassed = diff >= life; if (isPassed) { // Add( iSignal, result); } } } // // Get In Profit Signals ... void GetInProfitSignals( XSignal &result[], // Holds Result double minProfit = 0, // Minimum Profit To Close Trades ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions ) { // CleanBuffer(result); // XSignal signals[]; GetSignals( signals, type); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return; } // // Loop ... for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // bool isPassed = minProfit <= 0 && iSignal.profit > 0 ? true : iSignal.profit >= minProfit; if (isPassed) { Add( iSignal, result); } } } // // Get In Drawdown Signals ... void GetInDrawdownSignals( XSignal &result[], // Holds Result double maxDrawDown = 0, // Minimum Profit To Close Trades ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions ) { // CleanBuffer(result); // XSignal signals[]; GetSignals( signals, type); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return; } // // Loop ... for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // bool isPassed = maxDrawDown <= 0 && iSignal.profit < 0 ? true : iSignal.profit >= (-1 * maxDrawDown); if (isPassed) { Add( iSignal, result); } } } // // Retrieve Max In Draw Down Trade ... XSignal GetMaxInDrawdownSignal( ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions ) { // XSignal result = {}; // XSignal signals[]; GetInDrawdownSignals( signals, 0, type); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return result; } // // Loop ... for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // result = (result.ticket <= 0 && result.profit == 0) || result.profit > iSignal.profit ? iSignal : result; } // return result; } // // Calculate Profits Of all Open Signals ... double GetSignalsProfit( ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions ) { // double result = 0; // XSignal signals[]; GetSignals(signals, type); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return result; } // // Loop ... for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // result += iSignal.profit; } // return result; } // // END Retrieve ... // // // START Signal Execution Actions ... // // // Execute a Signal in Market ... ENUM_EXECUTION_SIGNAL_RESULT ExecuteSignal( XSignal &signal, // Specified Signal bool ignoreTPSL = false, // Ignore Signal TP and SL for Virtal Handling bool ignoreNumberOfTraes = false, // Ignore Number of Trades bool checkAccountConditions = true // Check Account Balance, Equity and Free Margin for Signal Execution ) { // ENUM_EXECUTION_SIGNAL_RESULT result = X_TRADER_UNKNOWN_ERROR; // // Validate Signal ... bool isValid = IsValidSignal(signal); if (!isValid) { // result = X_TRADER_INVALID_SIGNAL_ERROR; return result; } // // Check Account Equity ... bool isEquityPassed = !checkAccountConditions ? true : IsEquityReadyForTrade(); if (!isEquityPassed) { // result = X_TRADER_NOT_ENOUGH_EQUITY_ERROR; return result; } // // Check Account Balance ... bool isBalancePassed = !checkAccountConditions ? true : IsBalanceReadyForTrade(); if (!isBalancePassed) { // result = X_TRADER_NOT_ENOUGH_BALANCE_ERROR; return result; } // // Check Account FreeMargin ... bool isFreeMarginPassed = !checkAccountConditions ? true : IsFreeMarginReadyForTrade(); if (!isFreeMarginPassed) { // result = X_TRADER_NOT_ENOUGH_MARIGIN_ERROR; return result; } // // Check Number of Open Trades ... int openTradesCount = Count(); bool isTradeCountPassed = ignoreNumberOfTraes ? true : openTradesCount < mMaxAllowedTrades; if (!isTradeCountPassed) { // result = X_TRADER_MAX_TRADES_REACHED_ERROR; return result; } // bool isExecuted = signal.type == X_SIGNAL_LONG ? Buy( signal.volume, signal.entry, ignoreTPSL ? 0 : signal.sl, ignoreTPSL ? 0 : signal.tp, signal.comment) : signal.type == X_SIGNAL_SHORT ? Sell( signal.volume, signal.entry, ignoreTPSL ? 0 : signal.sl, ignoreTPSL ? 0 : signal.tp, signal.comment) : false; if (isExecuted) { // ulong ticket = PositionGetTicket(PositionsTotal() - 1); // signal.id = ticket; signal.ticket = ticket; // AddOrUpdateSignalInfo(signal); // result = X_TRADER_SUCCEED_EXECUTION; } // return result; } // // This Function, Handling Following Works on Open Positions: // - Close On SL if Reached ... // - Close On TP if Reached ... // - Make Risk Free Trades ... void HandleSignals( XTraderHandlerResult &result, // Holds Result bool ignoreTPSL = true, // Ignore Signal TP and SL for Virtal Handling bool ignoreRiskFree = false // Ignore Risk Free Trdaes ) { // // Cleanup Result ... CleanBuffer(result.sl); CleanBuffer(result.tp); CleanBuffer(result.rf); // // Reading Open Positions ... XSignal signals[]; GetSignals(signals); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return; } // double deviation = mSlippage * GetPoints(mSymbol); // // Loop ... for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // bool isLong = iSignal.type == X_SIGNAL_LONG; double entry = GetEntry(iSignal.symbol, iSignal.type); double exit = GetExit(iSignal.symbol, iSignal.type); double appliedTPPrice = iSignal.tp > 0 ? isLong ? iSignal.tp - deviation : iSignal.tp + deviation : 0; double appliedSLPrice = iSignal.sl > 0 ? isLong ? iSignal.sl + deviation : iSignal.sl - deviation : 0; // // Handle SL ... if ( // !ignoreTPSL // && // iSignal.sl > 0 // && // exit <= appliedSLPrice // ) { // string comment = GenerateSignalSLComment(iSignal); // bool isClosed = Close( iSignal.ticket, comment); if (isClosed) { Add( iSignal, result.sl); } } // // Handle TP ... if ( // !ignoreTPSL // && // iSignal.tp > 0 // && // exit >= appliedTPPrice // ) { // string comment = GenerateSignalTPComment(iSignal); // bool isClosed = Close( iSignal.ticket, comment); if (isClosed) { Add( iSignal, result.tp); } } // // Handle Risk Free ... if ( // !ignoreRiskFree // && // iSignal.riskFreeStep > 0 // && // iSignal.riskFreeRate > 0 // ) { // // Base Price is ENTRY, then Last Level, in each level SL is Last Level ... int level = 1; double stepPrice = PipsToPrice(iSignal.riskFreeStep); double basePrice = isLong ? iSignal.sl != 0 && iSignal.sl > iSignal.entry ? iSignal.sl : iSignal.entry : iSignal.sl != 0 && iSignal.sl < iSignal.entry ? iSignal.sl : iSignal.entry; double priceLevel = MathAbs(exit - basePrice) / stepPrice; // if (priceLevel > 1) { // while (priceLevel > level && priceLevel > level + 1) { level++; } // double baseRiskFreeLevelExitPrice = (level * stepPrice); double riskFreeLevelExitPrice = isLong ? (basePrice + baseRiskFreeLevelExitPrice) - deviation : (basePrice - baseRiskFreeLevelExitPrice) + deviation; // bool canRiskFree = isLong ? exit >= riskFreeLevelExitPrice : exit <= riskFreeLevelExitPrice; // if (canRiskFree) { // double volume = iSignal.volume; double riskFreeRate = iSignal.riskFreeRate; double riskFreeVolume = riskFreeRate * volume; riskFreeVolume = NormalizeVolume(riskFreeVolume); // double entry = GetEntry( iSignal.symbol, iSignal.type); double exit = GetExit( iSignal.symbol, iSignal.type); double spread = GetSpread(iSignal.symbol); long stopLevels = SymbolInfoInteger( iSignal.symbol, SYMBOL_TRADE_STOPS_LEVEL) + SymbolInfoInteger(iSignal.symbol, SYMBOL_SPREAD); double slDistance = spread * 2; // double sl = isLong ? iSignal.tp - slDistance : iSignal.tp + slDistance; sl = NormalizePrice(sl, iSignal.symbol); // double tp = isLong ? iSignal.tp + stepPrice : iSignal.tp - stepPrice; tp = NormalizePrice(tp, iSignal.symbol); // string comment = GenerateSignalRFComment(iSignal, (int)level); // ResetLastError(); // bool isClosedPartial = ClosePartial( iSignal.ticket, riskFreeVolume, comment); // if (isClosedPartial) { // // // bool isModified = Modify( // iSignal.ticket, // 0, // tp); // // if (isModified) // { // Add( iSignal, result.rf); // AddOrUpdateSignalInfo(iSignal); // } } } } } } } // // Close All Trades ... void CloseSignals( XSignal &result[], // Holds Result ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions ) { // CleanBuffer(result); // XSignal signals[]; GetSignals( signals, type); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return; } // for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // string comment = GenerateSignalForceCloseComment(iSignal); // bool isClosed = Close( iSignal.ticket, comment); if (isClosed) { Add( iSignal, result); } } } // // Close Pyramid Signals ... void CloseInPyramidSignals( XSignal &result[], // Holds Result double pyramid = 0, // Close Pyramid Profit ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions ) { // CleanBuffer(result); // XSignal signals[]; GetSignals( signals, type); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return; } // double profit = 0; for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // profit += iSignal.profit; } // // Normalize Pyramid ... if (pyramid < 0) { pyramid = 0; } // if (profit > pyramid) { CloseSignals(result); } } // // Close All Trades Which Candle Passed after Open ... void CloseOldSignals( XSignal &result[], // Holds Result int life, // Max Candle Passed after Trades Open ENUM_TIMEFRAMES period = NULL, // Calculate Candles based on time frame ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions ) { // CleanBuffer(result); // XSignal signals[]; GetOldSignals( signals, life, period, type); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return; } // for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // string comment = GenerateSignalAgeComment(iSignal); // bool isClosed = Close( iSignal.ticket, comment); if (isClosed) { Add( iSignal, result); } } } // // Close In Profit Signals ... void CloseInProfitSignals( XSignal &result[], // Holds Result double minProfit = 0, // Minimum Profit To Close Trades ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions ) { // CleanBuffer(result); // XSignal signals[]; GetInProfitSignals( signals, minProfit, type); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return; } // for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // string comment = GenerateSignalProfitComment(iSignal); // bool isClosed = Close( iSignal.ticket, comment); if (isClosed) { Add( iSignal, result); } } } // // Close In Drawdown Signals ... void CloseInDrawdownSignals( XSignal &result[], // Holds Result double maxDrawDown = 0, // Minimum Profit To Close Trades ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions ) { // CleanBuffer(result); // XSignal signals[]; GetInDrawdownSignals( signals, maxDrawDown, type); int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return; } // for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // string comment = GenerateSignalProfitComment(iSignal); // bool isClosed = Close( iSignal.ticket, comment); if (isClosed) { Add( iSignal, result); } } } // // END Signal Execution Actions ... // // // START Actions ... // // // 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; } // // Send BUY LIMIT order ... bool BuyLimit( double volume, // order volume double price, // order price double sl = 0.0, // stop loss price double tp = 0.0, // take profit price ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime datetime expiration = 0, // order expiration time string comment = "" // comment ) { // bool result = false; // result = mTrader.BuyLimit( volume, price, mSymbol, sl, tp, typeTime, expiration, comment); // return result; } // // Send BUY STOP order ... bool BuyStop( double volume, // order volume double price, // order price double sl = 0.0, // stop loss price double tp = 0.0, // take profit price ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime datetime expiration = 0, // order expiration time string comment = "" // comment ) { // bool result = false; // result = mTrader.BuyStop( volume, price, mSymbol, sl, tp, typeTime, expiration, 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; } // // Send SELL LIMIT order ... bool SellLimit( double volume, // order volume double price, // order price double sl = 0.0, // stop loss price double tp = 0.0, // take profit price ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime datetime expiration = 0, // order expiration time string comment = "" // comment ) { // bool result = false; // result = mTrader.SellLimit( volume, price, mSymbol, sl, tp, typeTime, expiration, comment); // return result; } // // Send SELL STOP order ... bool SellStop( double volume, // order volume double price, // order price double sl = 0.0, // stop loss price double tp = 0.0, // take profit price ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime datetime expiration = 0, // order expiration time string comment = "" // comment ) { // bool result = false; // result = mTrader.SellStop( volume, price, mSymbol, sl, tp, typeTime, expiration, comment); // return result; } // // Modify Position ... bool Modify( const ulong ticket, // position ticket double sl = 0, // stop loss price double tp = 0, // take profit const string comment = "" // comment ) { // bool result = false; // // Validate Args ... if (tp <= 0 && sl <= 0) { result = false; return result; } // result = mTrader.PositionModify( ticket, sl, tp, comment); // 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, mSlippage, comment); if (result) { RemoveSignal(ticket); } // return result; } // // Close Partial By Ticket ... bool ClosePartial( ulong ticket, // Position Ticket double volume, // Volume Size for Partial Closing string comment = "" // Close Position By Specific Comment ) { // bool result = false; // if (!mPositionInfo.SelectByTicket(ticket)) { return result; } // result = mTrader.PositionClosePartial( ticket, volume, mSlippage, comment); // return result; } // // END Actions ... // // // START Account Related ... // // // Check Account Has Minimum Balance For Trade ... bool IsBalanceReadyForTrade() { // 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; } // // Check Equity Has Enough For Trade ... bool IsEquityReadyForTrade() { // bool result = false; // double equity = mAccountInfo.GetEquity(); // result = equity >= mMinAllowedFreeMarginForOpenTrades; // return result; } // // END Account Related ... // // // START Signal Related ... // // // Validate Signal ... bool IsValidSignal( XSignal &signal // Specified 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; } // // Get Signal InDirection (Reversal) Type ... ENUM_X_SIGNAL_TYPE GetSignalIndirectionType( XSignal &signal // Specified Signal ) { // ENUM_X_SIGNAL_TYPE result = X_SIGNAL_UNKNOWN; // switch (signal.type) { // case X_SIGNAL_LONG: result = X_SIGNAL_SHORT; break; // case X_SIGNAL_SHORT: result = X_SIGNAL_LONG; break; } // 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 // Specified 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; } // // 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 riskFreeStep = 0, // Risk Free Step Price double riskFreeRate = 0 // Risk Free Rate ) { // 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); // result.tp = tp; result.sl = sl; result.type = type; result.entry = entry; result.symbol = mSymbol; result.magicNumber = mMagicNumber; result.riskFreeStep = riskFreeStep; 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 = GenerateSignalComment(result); // return result; } // // Generate Comments for Specific Signal ... string GenerateSignalComment( ENUM_X_SIGNAL_TYPE type, // Specify Kind Signal Type double volume, // Signal Volume bool isCrossSignal = false // Specify Signal Cross ) { // string result = ""; // string typeStr = GetSignalType(type); if ( volume <= 0 || StringLen(typeStr) == 0) { return result; } // volume = NormalizeVolume(volume, mSymbol); // result = mTag + (!isCrossSignal ? "" : "_Cross_") + "_" + typeStr; // return result; } string GenerateSignalComment( XSignal &signal, // Specified Signal bool isCrossSignal = false // Specify Signal Cross ) { // string result = GenerateSignalComment( signal.type, signal.volume, isCrossSignal // ); // return result; } // // Generate Signal RF TP Comment ... string GenerateSignalRFComment( XSignal &signal, // Specified Signal int level // Which Step of RFS ) { // string result = ""; // // Validate Signal and it's Ticket ... if (!IsValidSignal(signal) || signal.ticket <= 0) { return result; } // double exit = GetExit(signal.symbol, signal.type); // result = // X_SIGNAL_RISKFREE_STEP + "(" + (string)signal.ticket + ")_" + (string)level + ": " + string(exit); // ; // return result; } // // Generate Signal TP Comment ... string GenerateSignalTPComment( XSignal &signal // Specified Signal ) { // string result = ""; // // Validate Signal and it's Ticket ... if (!IsValidSignal(signal) || signal.ticket <= 0) { return result; } // double exit = GetExit(signal.symbol, signal.type); // result = // X_SIGNAL_TP + "(" + (string)signal.ticket + "): " + string(exit); // ; // return result; } // // Generate Signal SL Comment ... string GenerateSignalSLComment( XSignal &signal // Specified Signal ) { // string result = ""; // // Validate Signal and it's Ticket ... if (!IsValidSignal(signal) || signal.ticket <= 0) { return result; } // double exit = GetExit(signal.symbol, signal.type); // result = // X_SIGNAL_SL + "(" + (string)signal.ticket + "): " + string(exit); // ; // return result; } // // Generate Signal Profit Comment ... string GenerateSignalProfitComment( XSignal &signal // Specified Signal ) { // string result = ""; // // Validate Signal and it's Ticket ... if (!IsValidSignal(signal) || signal.ticket <= 0) { return result; } // result = // "Profit(" + (string)signal.ticket + "): " + string(signal.profit); // ; // return result; } // // Generate Signal Force Close Comment ... string GenerateSignalForceCloseComment( XSignal &signal // Specified Signal ) { // string result = ""; // // Validate Signal and it's Ticket ... if (!IsValidSignal(signal) || signal.ticket <= 0) { return result; } // result = // "FC(" + (string)signal.ticket + "): " + string(signal.profit); // ; // return result; } // // Generate Signal Age Comment ... string GenerateSignalAgeComment( XSignal &signal // Specified Signal ) { // string result = ""; // // Validate Signal and it's Ticket ... if (!IsValidSignal(signal) || signal.ticket <= 0) { return result; } // int age = GetSignalAge(signal); // result = // "(" + (string)signal.ticket + ") A: " + (string)age + ", P:" + string(signal.profit); // ; // return result; } // // Generate a Signal Object name for Draw Events On Chart ... string GenerateSignalObjectName( 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 GenerateSignalObjectName( XSignal &signal // Specified Signal ) { // string result = ""; // // Validate Arg ... if (!IsValid(signal, mMagicNumber)) { return result; } // result = GenerateSignalObjectName(signal.ticket); // return result; } // // Genrate a Signal Event Object Name ... string GenerateSignalEventObjectName( ulong ticket // Specify Ticket ) { // string result = ""; // result = GenerateSignalObjectName(ticket) + "_Event"; // return result; } string GenerateSignalEventObjectName( XSignal &signal // Specified Signal ) { // string result = ""; // result = GenerateSignalEventObjectName(signal.ticket); // return result; } // // Convert a Signal to String Representation ... string ToString( XSignal &signal // Specified Signal ) { // string result = ""; // if (!IsValid(signal, mMagicNumber) || signal.ticket <= 0) { return result; } // // TICKET ... // it is very importants since they hold position info ... result += X_SIGNAL_TICKET + "(" + (string)signal.ticket + ")"; // // TYPE ... string typeStr = GetSignalType(signal.type); result += "_" + X_SIGNAL_TYPE + "(" + typeStr + ")"; // // TP ... result += "_" + X_SIGNAL_TP + "(" + (string)signal.tp + ")"; // // SL ... result += "_" + X_SIGNAL_SL + "(" + (string)signal.sl + ")"; // // RFS ... result += "_" + X_SIGNAL_RISKFREE_STEP + "(" + (string)signal.riskFreeStep + ")"; // // RFR ... result += "_" + X_SIGNAL_RISKFREE_RATE + "(" + (string)signal.riskFreeRate + ")"; // 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, X_SIGNAL_TICKET + "(", ")"); if (StringLen(ticketStr) > 0) { result.ticket = (ulong)ticketStr; } // // TYPE ... string typeStr = ExtractString( represent, "_" + X_SIGNAL_TYPE + "(", ")"); if (StringLen(typeStr) > 0) { // ENUM_X_SIGNAL_TYPE type = GetSignalType(typeStr); result.type = type; } // // TP ... string tpStr = ExtractString( represent, "_" + X_SIGNAL_TP + "(", ")"); if (StringLen(tpStr) > 0) { // double tp = (double)tpStr; result.tp = tp; } // // SL ... string slStr = ExtractString( represent, "_" + X_SIGNAL_SL + "(", ")"); if (StringLen(slStr) > 0) { // double sl = (double)slStr; result.sl = sl; } // // RFS ... string rfsStr = ExtractString( represent, "_" + X_SIGNAL_RISKFREE_STEP + "(", ")"); if (StringLen(rfsStr) > 0) { // double rfs = (double)rfsStr; result.riskFreeStep = rfs; } // // RFR ... string rfrStr = ExtractString( represent, "_" + X_SIGNAL_RISKFREE_RATE + "(", ")"); if (StringLen(rfrStr) > 0) { // double rfr = (double)rfrStr; result.riskFreeRate = rfr; } // return result; } void FromString( XSignal &result, // Holds Result string represent // String Represenation of a Signal ) { // // Validate Arg ... if (StringLen(represent) == 0) { return; } // XSignal fs = FromString(represent); // // Fillisg Result by Retrieved Values ... result.tp = fs.tp; result.sl = fs.sl; result.type = fs.type; result.ticket = fs.ticket; result.riskFreeStep = fs.riskFreeStep; result.riskFreeRate = fs.riskFreeRate; } // // END Signal Related ... // // // START Deals ... // // // Count Deals ... int DealsCount( datetime start = -1, // Start Date datetime end = -1 // End Date ) { // int result = 0; // XDeal deals[]; GetDeals( deals, start, end); result = ArraySize(deals); // return result; } // // Retrieve All Deals ... void GetDeals( XDeal &result[], // Hold's Result datetime start = -1, // Start Date datetime end = -1 // End Date ) { // CleanBuffer(result); // // Select History if Start and End date provided ... if (start > -1) { // // Normalize End date ... if (end == -1) { end = TimeCurrent(); } // bool isSelect = HistorySelect(start, end); if (!isSelect) { return; } } // int total = HistoryDealsTotal(); if (total <= 0) { return; } // // Loop ... for (int i = total - 1; i >= 0; i--) { // // Select by Index ... bool isSelect = mDealInfo.SelectByIndex(i); if (!isSelect) { continue; } // // Check Magic ... ulong magic = mDealInfo.Magic(); bool isMagicSame = magic == mMagicNumber; if (!isMagicSame) { continue; } // // Check Symbol ... string symbol = mDealInfo.Symbol(); bool isSymbolSame = symbol == mSymbol; if (!isSymbolSame) { continue; } // XDeal deal = ToXDealByIndex(i); // Add( deal, result); } } // // Retrieve Last Deal ... XDeal GetLastDeal() { // XDeal result = {}; // XDeal deals[]; GetDeals(deals); int dealsCount = ArraySize(deals); if (dealsCount <= 0) { return result; } // result = deals[0]; // return result; } // // END Deals ... // // // START Orders ... // // // Count Orders ... int OrdersCount( datetime start = -1, // Start Date datetime end = -1 // End Date ) { // int result = 0; // XOrder orders[]; GetOrders( orders, start, end); result = ArraySize(orders); // return result; } // // Retrieve Orders ... void GetOrders( XOrder &result[], // Hold's Result datetime start = -1, // Start Date datetime end = -1 // End Date ) { // CleanBuffer(result); // // Select History if Start and End date provided ... if (start > -1) { // // Normalize End date ... if (end == -1) { end = TimeCurrent(); } // bool isSelect = HistorySelect(start, end); if (!isSelect) { return; } } // int total = HistoryOrdersTotal(); if (total <= 0) { return; } // // Loop ... for (int i = total - 1; i >= 0; i--) { // // Select by Index ... bool isSelect = mOrderInfo.SelectByIndex(i); if (!isSelect) { continue; } // // Check Magic ... ulong magic = mOrderInfo.Magic(); bool isMagicSame = magic == mMagicNumber; if (!isMagicSame) { continue; } // // Check Symbol ... string symbol = mOrderInfo.Symbol(); bool isSymbolSame = symbol == mSymbol; if (!isSymbolSame) { continue; } // XOrder order = ToXOrderByIndex(i); // Add( order, result); } } // // Retrieve Last Order ... XOrder GetLastOrder() { // XOrder result = {}; // XOrder orders[]; GetOrders(orders); int ordersCount = ArraySize(orders); if (ordersCount <= 0) { return result; } // result = orders[0]; // return result; } // // END Orders ... // // // 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; // // Minimum Free Marging for Open Trades double mMinAllowedFreeMarginForOpenTrades; // // Minimum Balance for Open Trades double mMinBallanceForOpenTrades; // // using CTrade instance ... XSCTrade mTrader; // // Deals Info ... CDealInfo mDealInfo; // // Order Info ... COrderInfo mOrderInfo; // // An Instance Of XCAccount Info for Handling Account Related Actions ... XCAccountInfo mAccountInfo; // // using PositionInfo instance ... CPositionInfo mPositionInfo; // // Signal Manager ... XCSignalManager mSignalManager; // // START Signal Private ... // // // Add Or Update Signal ... void AddOrUpdateSignalInfo( XSignal &signal // Specified Signal ) { // // // bool isExists = mSignalManager.IsExists(signal); // if (!isExists) // { // // // color longColor = clrAqua; // color shortColor = clrFuchsia; // // // DrawSignalShape( // signal, // longColor, // shortColor); // } // // // bool isAddOrUpdated = mSignalManager.AddOrUpdate(signal); // string name = GenerateSignalEventObjectName(signal); // bool isExists = IsDrawExists(name); if (isExists) { RemoveSignal(signal.ticket); } // DrawSignalEvent(signal); } // // Retrieve Signal String From Chart Event ... string RetrieveSignalContent( ulong ticket, // Specify Position Ticket int chartId = -1, // Specify Chart ID int subWindow = -1 // Specify SubWindow ID ) { // string result = ""; // // Normalize Chart and SubWindow ID ... if (chartId == -1) { chartId = 0; } if (subWindow == -1) { subWindow = 0; } // // Validate Args ... if (ticket <= 0) { return result; } // // Get Signal Event Name ... string sObjName = GenerateSignalEventObjectName(ticket); if (StringLen(sObjName) == 0) { return result; } // // Check Signal Event Exists ... bool isExists = IsDrawExists(sObjName); if (!isExists) { 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, sObjName); 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; } XSignal RetrieveSignal( ulong ticket // Specify Position Ticket ) { // XSignal result = {}; // if (ticket <= 0) { return result; } // string signalContent = RetrieveSignalContent(ticket); result = FromString( signalContent); // // result = mSignalManager.Get(ticket); // return result; } void RetrieveSignal( XSignal &signal // Specified Signal ) { // // // XSignal tSignal = mSignalManager.Get(signal.ticket); // // // // Fill signal by tSignal Data ... // // since tese properties may change in signal manipulation times ... // signal.tp = tSignal.tp; // signal.sl = tSignal.sl; // signal.riskFreeStep = tSignal.riskFreeStep; // signal.riskFreeRate = tSignal.riskFreeRate; // string signalContent = RetrieveSignalContent(signal.ticket); // FromString( signal, signalContent); } // // 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 = GenerateSignalEventObjectName(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); } } // // 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 = GenerateSignalEventObjectName(ticket); // // Remove Object from Chart ... result = RemoveDraw(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; } // // Converts a Position to Signal ... // // Convert Position to Signal by Index ... XSignal PositionToSignal(int index) { // XSignal result = {}; // if (!mPositionInfo.SelectByIndex(index)) { return result; } // ulong ticket = mPositionInfo.Ticket(); result = PositionToSignal(ticket); // 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 = result.tp <= 0 && mPositionInfo.TakeProfit() > 0 ? mPositionInfo.TakeProfit() : result.tp; // // Stop Loss ... result.sl = result.sl <= 0 && mPositionInfo.StopLoss() > 0 ? mPositionInfo.StopLoss() : result.sl; // // Profit ... result.profit = mPositionInfo.Profit(); // // Time ... result.time = mPositionInfo.Time(); // // Volume ... result.volume = mPositionInfo.Volume(); // // Comment ... result.comment = mPositionInfo.Comment(); // return result; } // // Converts a Deal to XDeal by Index ... XDeal ToXDealByIndex(int index) { // XDeal result = {}; // bool isSelect = mDealInfo.SelectByIndex(index); if (!isSelect) { return result; } // // Read Deal Ticket ... ulong ticket = mDealInfo.Ticket(); result = ToXDealByTicket(ticket); // return result; } // // Converts a Deal to XDeal by Ticket ... XDeal ToXDealByTicket(ulong ticket) { // XDeal result = {}; // mDealInfo.Ticket(ticket); // result.time = mDealInfo.Time(); result.swap = mDealInfo.Swap(); result.magic = mDealInfo.Magic(); result.order = mDealInfo.Order(); result.entry = mDealInfo.Entry(); result.price = mDealInfo.Price(); result.ticket = mDealInfo.Ticket(); result.symbol = mDealInfo.Symbol(); result.type = mDealInfo.DealType(); result.profit = mDealInfo.Profit(); result.volume = mDealInfo.Volume(); result.comment = mDealInfo.Comment(); result.positionId = mDealInfo.PositionId(); result.commission = mDealInfo.Commission(); result.reason = (ENUM_DEAL_REASON)HistoryDealGetInteger( ticket, DEAL_REASON); // return result; } // // Convert an Order to XOrder by Index ... XOrder ToXOrderByIndex(int index) { // XOrder result = {}; // bool isSelect = mOrderInfo.SelectByIndex(index); if (!isSelect) { return result; } // ulong ticket = mOrderInfo.Ticket(); result = ToXOrderByTicket(ticket); // return result; } // // Convert an Order to XOrder by Ticket ... XOrder ToXOrderByTicket(ulong ticket) { // XOrder result = {}; // bool isSelect = mOrderInfo.Select(ticket); if (!isSelect) { return result; } // result.state = mOrderInfo.State(); result.magic = mOrderInfo.Magic(); result.ticket = mOrderInfo.Ticket(); result.symbol = mOrderInfo.Symbol(); result.type = mOrderInfo.OrderType(); result.comment = mOrderInfo.Comment(); result.stopLoss = mOrderInfo.StopLoss(); result.typeTime = mOrderInfo.TypeTime(); result.timeDone = mOrderInfo.TimeDone(); result.timeSetup = mOrderInfo.TimeSetup(); result.positionId = mOrderInfo.PositionId(); result.priceOpen = mOrderInfo.PriceOpen(); result.takeProfit = mOrderInfo.TakeProfit(); result.typeFilling = mOrderInfo.TypeFilling(); result.priceCurrent = mOrderInfo.PriceCurrent(); result.volumeInitial = mOrderInfo.VolumeInitial(); result.volumeCurrent = mOrderInfo.VolumeCurrent(); result.timeExpiration = mOrderInfo.TimeExpiration(); result.priceStopLimit = mOrderInfo.PriceStopLimit(); result.reason = (ENUM_ORDER_REASON)HistoryOrderGetInteger( ticket, ORDER_REASON); // return result; } // // END Signal Private ... // }; // // END Global Definitions: Variables, Properties and etc ... //