/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Seriallize Library // --------------------------------------- // Name: XTradeLib // Description: All models related to Trade ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // // Imports ... #include #include "../Libraries/x-saherelm.common.lib.mq5" #include "../Classes/x-saherelm.xdata-collector.class.mq5" // // Definitions ... // // a List of Used Tokens ... // // Common ... string XIDToken = "ID"; string XTicketToken = "TK"; string XModeToken = "MD"; string XTypeToken = "TY"; string XPeriodToken = "PR"; string XProviderToken = "PRV"; string XProfitToken = "PF"; // string XTPToken = "TP"; string XSLToken = "SL"; string XTimeToken = "TM"; string XEntryToken = "EN"; string XVolumeToken = "VL"; string XSymbolToken = "SMBL"; // string XSupportToken = "SP"; string XEQMSupportToken = "EQM"; // string XSLTrailToken = "SLT"; // string XActionToken = "A"; // // Available Order Modes ... enum ENUM_X_ORDER_MODES { X_ORDER_MODE_NOTHING, // Nothing X_ORDER_MODE_MARKET, // Market Order X_ORDER_MODE_STOP, // Pending Stop Order X_ORDER_MODE_LIMIT, // Pending Limit Order X_ORDER_MODE_STOP_LIMIT, // Pending Stop Limit Order }; // // Select Positions Type ... enum ENUM_X_POSITION_SELECT_METHODS { X_POSITION_SELECT_NONE, // None X_POSITION_SELECT_MAX, // Max X_POSITION_SELECT_MIN, // Min X_POSITION_SELECT_BOTH, // Min and Max X_POSITION_SELECT_ALL, // All }; // // Signal Execution Result ... // note that some of them must be handles in // EA's ... enum ENUM_X_SIGNAL_EXECUTION_RESULT { // X_SIGNAL_EXECUTION_UNKNOWN, // Unknown X_SIGNAL_EXECUTION_SUCCEED, // Succed X_SIGNAL_EXECUTION_FAILED_SPREAD, // Spread more than Max Allowed X_SIGNAL_EXECUTION_FAILED_NO_EQUITY, // No Equity for Trade X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR, // Price Error X_SIGNAL_EXECUTION_FAILED_MAX_REACHED, // Max Allowed Positions Reached X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS, // Invalid Params }; // // How to Manage Signal TP and SL ... enum ENUM_X_SIGNAL_MANAGING_ACTIONS { // X_SIGNAL_USE_NOTHING, // Use 0 index if exists and ignore if not X_SIGNAL_USE_MAX, // Use Max Value X_SIGNAL_USE_MIN, // Use Min Value X_SIGNAL_PARTIAL_CLOSE, // Use Max as Regular but Partial Close at each Step X_SIGNAL_TRAIL, // Use 0 index as SL and Trail Stop on TP Levels X_SIGNAL_PARTIAL_TRAIL, // Use 0 index as SL and Trail Stop on TP Levels and also Partial Close on TP Levels }; // // Available Guard Action ... enum ENUM_X_GUARD_ACTIONS { X_GUARD_ACTION_NOTHING, // Nothing X_GUARD_ACTION_HEDGE, // Hedge X_GUARD_PARTIAL_CLOSE, // Partial Close X_GUARD_ACTION_TRAIL_STOP, // Trail StopLoss X_GUARD_ACTION_FORCE_CLOSE, // Force Close X_GUARD_ACTION_ADD_SUPPORT_SIGNAL, // Add Support Signal X_GUARD_ACTION_CANCEL_PENDING_ORDERS, // Cancel Pending Orders }; // // Structs ... // // Model a Signal ... struct XSignal { // // Props ... // ulong positionId; // if Executed this filled ... double entry; // Exntry or Execution Price ... double volume; // Position Volume ... // datetime time; // Issue Time ... // ENUM_X_SIGNAL_MANAGING_ACTIONS action; // Signal Managing Action ... double tps[]; // a Collection of TP(s) ... double sls[]; // a Collection of SL(s) ... // string symbol; // Trading Symbol ... string provider; // Signaller ... string comment; // Comment ... // ENUM_TIMEFRAMES period; // Trading TimeFrame ... ENUM_POSITION_TYPE type; // Long (Buy) or Short (Sell) ... ENUM_X_ORDER_MODES mode; // Execution Mode ... // XSignal supports[]; // a Collecion of Support Signals ... XOHCLSupRes supportResistances; // Support and Resistances ... // // Constructor ... XSignal() { Clean(); } // // DO All Calculations and Normalizations ... bool Normalize() { // bool result = false; // // Normalizations ... symbol = NormalizeSymbol(symbol); period = NormalizePeriod(period); // entry = NormalizePrice(entry, symbol); volume = NormalizeVolume(volume, symbol); // time = NormalizeTime(time); // int slsCount = ArraySize(sls); if (slsCount > 0) { // for (int i = 0; i < slsCount; i++) { sls[i] = NormalizePrice(sls[i], symbol); } } // int tpsCount = ArraySize(tps); if (tpsCount > 0) { // for (int i = 0; i < tpsCount; i++) { tps[i] = NormalizePrice(tps[i], symbol); } } // result = IsValid(); // return result; } // bool Prepare( string mSymbol, // Trading Symbol string mProvider, // Signal Provider ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame ENUM_POSITION_TYPE mType, // Long (Buy) or Short (Sell) ENUM_X_ORDER_MODES mMode, // Execution Mode double mEntry, // Entry Price double mVolume, // Volume ENUM_X_SIGNAL_MANAGING_ACTIONS mAction = X_SIGNAL_USE_NOTHING, // Signal Management Action double sl = 0, // Stop Loss double tp = 0 // Take Profit ) { // bool result = false; // result = // IsValid(mMode) && IsValid(mSymbol) && IsValid(mPeriod) && NotEmpty(mEntry) && NotEmpty(mVolume) && IsValid(mProvider) // ; if (!result) { return result; } // if (tp < 0) { tp = 0; } // if (sl < 0) { sl = 0; } // if (tp == 0 && sl == 0) { action = X_SIGNAL_USE_NOTHING; } // type = mType; mode = mMode; symbol = mSymbol; period = mPeriod; provider = mProvider; // // Normalization Values ... sl = NormalizePrice(sl, mSymbol); tp = NormalizePrice(tp, mSymbol); mEntry = NormalizePrice(mEntry, mSymbol); mVolume = NormalizeVolume(mVolume, mSymbol); // entry = mEntry; volume = mVolume; // action = mAction; // Add( sl, sls // ); // Add( tp, tps // ); // result = Normalize(); // return result; } // bool PrepareLong( string mSymbol, // Trading Symbol string mProvider, // Signal Provider ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame ENUM_X_ORDER_MODES mMode, // Execution Mode double mEntry, // Entry Price double mVolume, // Volume ENUM_X_SIGNAL_MANAGING_ACTIONS mAction = X_SIGNAL_USE_NOTHING, // Signal Management Action double sl = 0, // Stop Loss double tp = 0 // Take Profit ) { // return Prepare( mSymbol, mProvider, mPeriod, POSITION_TYPE_BUY, mMode, mEntry, mVolume, mAction, sl, tp // ); } // bool PrepareShort( string mSymbol, // Trading Symbol string mProvider, // Signal Provider ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame ENUM_X_ORDER_MODES mMode, // Execution Mode double mEntry, // Entry Price double mVolume, // Volume ENUM_X_SIGNAL_MANAGING_ACTIONS mAction = X_SIGNAL_USE_NOTHING, // Signal Management Action double sl = 0, // Stop Loss double tp = 0 // Take Profit ) { // return Prepare( mSymbol, mProvider, mPeriod, POSITION_TYPE_SELL, mMode, mEntry, mVolume, mAction, sl, tp // ); } // // Market Mode ... // bool PrepareMarketLong( string mSymbol, // Trading Symbol string mProvider, // Signal Provider ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame double mEntry, // Entry Price double mVolume, // Volume ENUM_X_SIGNAL_MANAGING_ACTIONS mAction = X_SIGNAL_USE_NOTHING, // Signal Management Action double sl = 0, // Stop Loss double tp = 0 // Take Profit ) { // return PrepareLong( mSymbol, mProvider, mPeriod, X_ORDER_MODE_MARKET, mEntry, mVolume, mAction, sl, tp // ); } // bool PrepareMarketShort( string mSymbol, // Trading Symbol string mProvider, // Signal Provider ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame double mEntry, // Entry Price double mVolume, // Volume ENUM_X_SIGNAL_MANAGING_ACTIONS mAction = X_SIGNAL_USE_NOTHING, // Signal Management Action double sl = 0, // Stop Loss double tp = 0 // Take Profit ) { // return PrepareShort( mSymbol, mProvider, mPeriod, X_ORDER_MODE_MARKET, mEntry, mVolume, mAction, sl, tp // ); } // // Stop Mode ... // bool PrepareStopLong( string mSymbol, // Trading Symbol string mProvider, // Signal Provider ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame double mEntry, // Entry Price double mVolume, // Volume ENUM_X_SIGNAL_MANAGING_ACTIONS mAction = X_SIGNAL_USE_NOTHING, // Signal Management Action double sl = 0, // Stop Loss double tp = 0 // Take Profit ) { // return PrepareLong( mSymbol, mProvider, mPeriod, X_ORDER_MODE_STOP, mEntry, mVolume, mAction, sl, tp // ); } // bool PrepareStopShort( string mSymbol, // Trading Symbol string mProvider, // Signal Provider ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame double mEntry, // Entry Price double mVolume, // Volume ENUM_X_SIGNAL_MANAGING_ACTIONS mAction = X_SIGNAL_USE_NOTHING, // Signal Management Action double sl = 0, // Stop Loss double tp = 0 // Take Profit ) { // return PrepareShort( mSymbol, mProvider, mPeriod, X_ORDER_MODE_STOP, mEntry, mVolume, mAction, sl, tp // ); } // // Limit Mode ... // bool PrepareLimitLong( string mSymbol, // Trading Symbol string mProvider, // Signal Provider ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame double mEntry, // Entry Price double mVolume, // Volume ENUM_X_SIGNAL_MANAGING_ACTIONS mAction = X_SIGNAL_USE_NOTHING, // Signal Management Action double sl = 0, // Stop Loss double tp = 0 // Take Profit ) { // return PrepareLong( mSymbol, mProvider, mPeriod, X_ORDER_MODE_LIMIT, mEntry, mVolume, mAction, sl, tp // ); } // bool PrepareLimitShort( string mSymbol, // Trading Symbol string mProvider, // Signal Provider ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame double mEntry, // Entry Price double mVolume, // Volume ENUM_X_SIGNAL_MANAGING_ACTIONS mAction = X_SIGNAL_USE_NOTHING, // Signal Management Action double sl = 0, // Stop Loss double tp = 0 // Take Profit ) { // return PrepareShort( mSymbol, mProvider, mPeriod, X_ORDER_MODE_LIMIT, mEntry, mVolume, mAction, sl, tp // ); } // // here we Can Modify TP and SL and also Action ... bool Modify( ENUM_X_SIGNAL_MANAGING_ACTIONS mAction, double &mTps[], double &mSls[] // ) { // bool result = false; // result = IsValid(); if (!result) { return result; } // // Only Position Manager works on Market Execution Positions ... if (mAction != X_SIGNAL_USE_NOTHING && mode != X_ORDER_MODE_MARKET) { return result; } // int mTpsCount = ArraySize(mTps); int mSlsCount = ArraySize(mSls); // if (mAction != X_SIGNAL_USE_NOTHING) { // if (mAction == X_SIGNAL_USE_MAX || mAction == X_SIGNAL_USE_MIN || mAction == X_SIGNAL_PARTIAL_TRAIL) { result = mTpsCount > 0 || mSlsCount > 0; } else { result = mTpsCount > 0 && mSlsCount > 0; } } // if (result) { // double defaultValue = 0; // Copy( mTps, tps // ); if (ArraySize(tps) <= 0) { // Add( defaultValue, tps // ); } // Copy( mSls, sls // ); if (ArraySize(sls) <= 0) { // Add( defaultValue, sls // ); } // action = mAction; // result = IsValid(); } // return result; } // // Tools ... // // Cleanup ... void Clean() { // entry = 0; volume = 0; positionId = 0; // time = NULL; type = NULL; mode = NULL; symbol = NULL; period = NULL; comment = NULL; provider = NULL; // Clean(tps); Clean(sls); Clean(supports); supportResistances.Clean(); } // // Validate ... bool IsValid() { // bool result = false; // result = // IsValid(period) && IsValid(symbol) && NotEmpty(volume) && NotEmpty(entry) && (ArraySize(tps) > 0 || ArraySize(sls) > 0) // ; // if (!result) { return result; } // // Validate Actions ... // // Only Position Manager works on Market Execution Positions ... result = // !(action != X_SIGNAL_USE_NOTHING && mode != X_ORDER_MODE_MARKET) // ; if (!result) { return result; } // int tpsCount = ArraySize(tps); int slsCount = ArraySize(sls); // if (action != X_SIGNAL_USE_NOTHING) { // if (action == X_SIGNAL_USE_MAX || action == X_SIGNAL_USE_MIN || action == X_SIGNAL_PARTIAL_TRAIL) { result = tpsCount > 0 || slsCount > 0; } else { result = tpsCount > 0 && slsCount > 0; } } // return result; } // // Check Signal Executed or not ... bool IsExecuted() { // bool result = false; // result = // IsValid() && NotEmpty(positionId) // ; // return result; } // // Generate Comment for Signal ... string GenerateComment() { // string result = NULL; // if (!IsValid()) { return result; } // if (IsValid(provider)) { // // Generate Provider Tag ... result += GenerateProviderTag(provider); } // if (IsValid(period)) { // // Generate Period Tag ... result += GeneratePeriodTag(period); } // return result; } // // Check this instance is Same os Given instance or not ... bool IsSameAs( const XSignal &value // instance for Compare ) { // bool result = false; // result = // type == value.type && mode == value.mode && entry == value.entry && volume == value.volume && symbol == value.symbol && provider == value.provider && positionId == value.positionId && ArraySize(sls) == ArraySize(value.sls) && ArraySize(tps) == ArraySize(value.tps) // ; // return result; } // // Find index in a Collection ... int FindIndex( const XSignal &values[] // Collection to Find ) { // return FindIndex( this, values // ); } // // Check Items Passed Specific Filters or not ... bool IsFiltersPassed( string mSymbol = NULL, // Trading Symbol string mProvider = NULL, // Signal Provider ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe ENUM_POSITION_TYPE mType = NULL, // Long (Buy), Short (Sell) ENUM_X_ORDER_MODES mMode = NULL // Execution Mode ) { // bool result = false; // result = // // Symbol Filter ... IsSymbolFilterPassed( mSymbol, this // ) // && // // Provider Filter ... IsProviderFilterPassed( mProvider, this // ) // && // // Period Filter ... IsPeriodFilterPassed( mPeriod, this // ) // && // // Type Filter ... IsTypeFilterPassed( mType, this // ) // && // // Mode Filter ... IsModeFilterPassed( mMode, this // ) // ; // return result; } // string GetToken() { return GetToken(this); } // bool IsModelValid() { return IsValid(); } // // To String Representation ... string ToModelString() { // string result = NULL; // if (!IsValid()) { return result; } // // For Modeling a Signal we Only Used: // - Period; // - Provider; // - Type; // - Mode; // - Symbol; // - PositionID; // - Entry; // - Volume; // - TPS; // - SLS; // - Issue Time; // int iPeriodInt = (int)period; // string periodStr = Surround(XPeriodToken, iPeriodInt); string providerStr = Surround(XProviderToken, provider); string typeStr = Surround(XTypeToken, type); string modeStr = Surround(XModeToken, mode); string SymbolStr = Surround(XSymbolToken, symbol); string positionIdStr = Surround(XIDToken, positionId); string entryStr = Surround(XEntryToken, entry); string volumeStr = Surround(XVolumeToken, volume); string timeStr = Surround(XTimeToken, time); // string actionStr = Surround(XActionToken, action); // // TP ... string tpsContentStr = ToString(tps); string tpsStr = Surround(XTPToken, tpsContentStr); // // SL ... string slsContentStr = ToString(sls); string slsStr = Surround(XSLToken, slsContentStr); // result = // GetToken() + "[" + // periodStr + providerStr + typeStr + modeStr + SymbolStr + positionIdStr + entryStr + volumeStr + actionStr + tpsStr + slsStr + timeStr + // "]" // ; // return result; } // // Parse String Model and Fill Available // Items ... bool ParseModel(string value) { // bool result = false; // Clean(); // if (!IsValid(value)) { return false; } // // For Modeling a Signal we Only Used: // - Period; // - Provider; // - Type; // - Mode; // - Symbol; // - PositionID; // - Entry; // - Volume; // - TPS; // - SLS; // - Issue Time; // entry = ParseDoubleSurrounded(value, XEntryToken); volume = ParseDoubleSurrounded(value, XVolumeToken); positionId = ParseLongSurrounded(value, XIDToken); // time = ParseTimeSurrounded(value, XTimeToken); symbol = ParseStringSurrounded(value, XSymbolToken); provider = ParseStringSurrounded(value, XProviderToken); type = ((ENUM_POSITION_TYPE)ParseIntSurrounded(value, XTypeToken)); mode = ((ENUM_X_ORDER_MODES)ParseIntSurrounded(value, XModeToken)); period = ((ENUM_TIMEFRAMES)ParseIntSurrounded(value, XPeriodToken)); // action = ((ENUM_X_SIGNAL_MANAGING_ACTIONS)ParseIntSurrounded(value, XActionToken)); // // TPS ... ParseDoubleArraySurrounded( tps, value, XTPToken // ); // // SLS ... ParseDoubleArraySurrounded( sls, value, XSLToken // ); // // Validate ... result = IsValid(); ; // return result; } // // Select Regular SL ... bool RegularSL(double &sl) { // bool result = false; // sl = 0; int slsCount = ArraySize(sls); // result = IsValid() && slsCount > 0; if (!result) { return result; } // if ( action == X_SIGNAL_TRAIL || action == X_SIGNAL_USE_NOTHING || action == X_SIGNAL_PARTIAL_TRAIL) { sl = sls[0]; } else if (action == X_SIGNAL_USE_MAX || action == X_SIGNAL_PARTIAL_CLOSE) { sl = GetMin(sls); } else if (action == X_SIGNAL_USE_MIN) { sl = GetMax(sls); } // return result; } // // Select Regular TP ... bool RegularTP(double &tp) { // bool result = false; // tp = 0; int tpsCount = ArraySize(tps); // result = IsValid() && tpsCount > 0; if (!result) { return result; } // if ( action == X_SIGNAL_TRAIL || action == X_SIGNAL_USE_NOTHING || action == X_SIGNAL_PARTIAL_TRAIL) { tp = tps[0]; } else if (action == X_SIGNAL_USE_MAX || action == X_SIGNAL_PARTIAL_CLOSE) { tp = GetMax(tps); } else if (action == X_SIGNAL_USE_MIN) { tp = GetMin(tps); } // return result; } // // Retrieve Entry Price ... double GetEntry() { // double result = 0; // if (!IsValid()) { return result; } // result = GetEntry( symbol, type // ); // return result; } // // Retrieve Exit ... double GetExit() { // double result = 0; // if (!IsValid()) { return result; } // result = GetExit( symbol, type // ); // return result; } // // Get Spread by Point ... double GetSpread() { // double result = 0; // if (!IsValid()) { return result; } // result = PriceToPoint(GetSpread(symbol)); // return result; } }; // // Model an Open Position ... struct XPosition { // // Props ... // // Magic Number ... ulong magic; // // Ticket ID ... ulong ticket; // // Tradinng Symbol ... string symbol; // // Trading Period ... ENUM_TIMEFRAMES period; // // Position Type ... ENUM_POSITION_TYPE type; // // Take Profit ... double tp; // // Stop Loss ... double sl; // // Position Current Profit ... double profit; // // Position Open Price ... double entry; // // Current Symbol Price ... double price; // // Position Swap ... double swap; // // Position Commission ... double commission; // // Volume ... double volume; // // Position Open Time ... datetime openAt; // // Sifnal Provider ... string provider; // // Position Comment ... string comment; // // Constructor ... XPosition() { Clean(); } // // Initializers ... bool ByIndex(int index) { // bool result = false; // static CPositionInfo mPositionInfo; // result = mPositionInfo.SelectByIndex(index); if (!result) { return result; } // ulong mTicket = mPositionInfo.Ticket(); // result = ByTicket(mTicket); // return result; } bool ByTicket(ulong mTicket) { // bool result = false; // static CPositionInfo mPositionInfo; // result = mPositionInfo.SelectByTicket(mTicket); if (!result) { return result; } // swap = mPositionInfo.Swap(); magic = mPositionInfo.Magic(); openAt = mPositionInfo.Time(); sl = mPositionInfo.StopLoss(); ticket = mPositionInfo.Ticket(); symbol = mPositionInfo.Symbol(); tp = mPositionInfo.TakeProfit(); profit = mPositionInfo.Profit(); volume = mPositionInfo.Volume(); comment = mPositionInfo.Comment(); entry = mPositionInfo.PriceOpen(); type = mPositionInfo.PositionType(); price = mPositionInfo.PriceCurrent(); commission = mPositionInfo.Commission(); // period = ExtractPeriod(comment); provider = ExtractProvider(comment); // return result; } // // Tools ... // // Cleanup ... void Clean() { magic = 0; ticket = 0; tp = 0; sl = 0; swap = 0; entry = 0; price = 0; profit = 0; volume = 0; openAt = 0; commission = 0; // type = NULL; period = NULL; // symbol = NULL; comment = NULL; provider = NULL; } // // Validate ... bool IsValid() { // bool result = false; // result = // IsValid(symbol) && NotEmpty(ticket) // ; // return result; } // // Retrieve Entry Price ... double GetEntry() { // double result = 0; // if (!IsValid()) { return result; } // result = GetEntry( symbol, type // ); // return result; } // // Retrieve Exit ... double GetExit() { // double result = 0; // if (!IsValid()) { return result; } // result = GetExit( symbol, type // ); // return result; } // // Get Spread by Point ... double GetSpread() { // double result = 0; // if (!IsValid()) { return result; } // result = PriceToPoint(GetSpread(symbol)); // return result; } // // Calculate Age ... int GetAge( ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period ) { return GetAge(this, mPeriod); } // // Check this instance is Same os Given instance or not ... bool IsSameAs( const XPosition &value // instance for Compare ) { // bool result = false; // result = // type == value.type && magic == value.magic && entry == value.entry && ticket == value.ticket && volume == value.volume && symbol == value.symbol && provider == value.provider // ; // return result; } // // Find index in a Collection ... int FindIndex( const XPosition &values[] // Collection to Find ) { // return FindIndex( this, values // ); } // // Check Items Passed Specific Filters or not ... bool IsFiltersPassed( string mSymbol = NULL, // Trading Symbol string mProvider = NULL, // Signal Provider ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe ENUM_POSITION_TYPE mType = NULL, // Long (Buy), Short (Sell) ulong mMagic = NULL, // Magic Number bool mFilterByMagic = true // Get Only Self Open Positions ) { // bool result = false; // result = // // Magic Filter ... IsMagicFilterPassed( mMagic, mFilterByMagic, this // ) // && // // Symbol Filter ... IsSymbolFilterPassed( mSymbol, this // ) // && // // Provider Filter ... IsProviderFilterPassed( mProvider, this // ) // && // // Period Filter ... IsPeriodFilterPassed( mPeriod, this // ) // && // // Type Filter ... IsTypeFilterPassed( mType, this // ) // ; // return result; } }; // // Model an Order ... struct XOrder { // // Time of order placement ... datetime setupAt; // // Time of order expiration ... datetime expiredAt; // // Time of order execution or cancellation ... datetime executedAt; // // Order type ... ENUM_ORDER_TYPE type; // // Order state ... ENUM_ORDER_STATE state; // // Type of execution by remainder ... ENUM_ORDER_TYPE_FILLING filling; // // Order lifetime ... ENUM_ORDER_TYPE_TIME lifetime; // // Order ticket ... ulong ticket; // // Magic Number ... long magic; // // Position id, that is placed on order, // when it is executed. Each executed order invokes a // deal, that opens new or changes existing // position. Id of that position is placed on // executed order in this moment. long positionId; // // Initial volume on order placement ... double initialVolume; // // Unfilled volume ... double currentVolume; // // Price, specified in the order ... double openPrice; // // Current price by order symbol ... double currentPrice; // // Price of placing Limit order when StopLimit order is triggered ... double stopLimitPrice; // // Take Profit level ... double tp; // // Stop Loss level ... double sl; // // Trading Symbol ... string symbol; // // Signal Provider ... string provider; // // Order Comment ... string comment; // ENUM_TIMEFRAMES period; // // Constructor ... XOrder() { Clean(); } // // Initializers ... bool ByIndex( int index // Fill By Index ... ) { // bool result = false; // int ordersCount = OrdersTotal(); if (ordersCount <= 0) { return result; } // static COrderInfo mOrderInfo; // result = mOrderInfo.SelectByIndex(index); if (!result) { return result; } // // Reading Order Info ... magic = mOrderInfo.Magic(); sl = mOrderInfo.StopLoss(); tp = mOrderInfo.TakeProfit(); ticket = mOrderInfo.Ticket(); openPrice = mOrderInfo.PriceOpen(); positionId = mOrderInfo.PositionId(); currentPrice = mOrderInfo.PriceCurrent(); initialVolume = mOrderInfo.VolumeInitial(); currentVolume = mOrderInfo.VolumeCurrent(); stopLimitPrice = mOrderInfo.PriceStopLimit(); // symbol = mOrderInfo.Symbol(); comment = mOrderInfo.Comment(); // state = mOrderInfo.State(); type = mOrderInfo.OrderType(); lifetime = mOrderInfo.TypeTime(); filling = mOrderInfo.TypeFilling(); // setupAt = mOrderInfo.TimeSetup(); executedAt = mOrderInfo.TimeDone(); expiredAt = mOrderInfo.TimeExpiration(); // period = ExtractPeriod(comment); provider = ExtractProvider(comment); // result = IsValid(); // return result; } // // Retrieve Specific History Order ... bool HistoryByIndex( int index // Fill By Index ... ) { // bool result = false; // int ordersCount = HistoryOrdersTotal(); if (ordersCount <= 0) { return result; } // static CHistoryOrderInfo mOrderInfo; // result = mOrderInfo.SelectByIndex(index); if (!result) { return result; } // // Reading Order Info ... magic = mOrderInfo.Magic(); sl = mOrderInfo.StopLoss(); tp = mOrderInfo.TakeProfit(); ticket = mOrderInfo.Ticket(); openPrice = mOrderInfo.PriceOpen(); positionId = mOrderInfo.PositionId(); currentPrice = mOrderInfo.PriceCurrent(); initialVolume = mOrderInfo.VolumeInitial(); currentVolume = mOrderInfo.VolumeCurrent(); stopLimitPrice = mOrderInfo.PriceStopLimit(); // symbol = mOrderInfo.Symbol(); comment = mOrderInfo.Comment(); // state = mOrderInfo.State(); type = mOrderInfo.OrderType(); lifetime = mOrderInfo.TypeTime(); filling = mOrderInfo.TypeFilling(); // setupAt = mOrderInfo.TimeSetup(); executedAt = mOrderInfo.TimeDone(); expiredAt = mOrderInfo.TimeExpiration(); // period = ExtractPeriod(comment); provider = ExtractProvider(comment); // result = IsValid(); // return result; } // // Tools ... // // Cleanup ... void Clean() { // tp = 0; sl = 0; magic = 0; ticket = 0; positionId = 0; openPrice = 0; currentPrice = 0; initialVolume = 0; currentVolume = 0; stopLimitPrice = 0; // setupAt = NULL; expiredAt = NULL; executedAt = NULL; // symbol = NULL; comment = NULL; provider = NULL; // type = NULL; state = NULL; period = NULL; filling = NULL; lifetime = NULL; } // // Validate ... bool IsValid() { // bool result = false; // result = // IsValid(symbol) && NotEmpty(ticket) && NotEmpty(positionId) // ; // return result; } // // Calculate Age ... int GetAge( ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period ) { return GetAge(this, mPeriod); } // // Check this instance is Same os Given instance or not ... bool IsSameAs( const XOrder &value // instance for Compare ) { // bool result = false; // result = // type == value.type && state == value.state && magic == value.magic && ticket == value.ticket && symbol == value.symbol && provider == value.provider && positionId == value.positionId // ; // return result; } // // Find index in a Collection ... int FindIndex( const XOrder &values[] // Collection to Find ) { // return FindIndex( this, values // ); } // // Check Items Passed Specific Filters or not ... bool IsFiltersPassed( string mSymbol = NULL, // Trading Symbol string mProvider = NULL, // Signal Provider ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe ENUM_ORDER_TYPE mType = NULL, // Long (Buy), Short (Sell) ENUM_ORDER_STATE mState = NULL, // Order State ulong mMagic = NULL, // Magic Number bool mFilterByMagic = true // Get Only Self Open Positions ) { // bool result = false; // result = // // Magic Filter ... IsMagicFilterPassed( mMagic, mFilterByMagic, this // ) // && // // Symbol Filter ... IsSymbolFilterPassed( mSymbol, this // ) // && // // Provider Filter ... IsProviderFilterPassed( mProvider, this // ) // && // // Period Filter ... IsPeriodFilterPassed( mPeriod, this // ) // && // // Type Filter ... IsTypeFilterPassed( mType, this // ) // && // // State Filter ... IsStateFilterPassed( mState, this // ) // ; // return result; } }; // // Model a Deal ... struct XDeal { // // the ID of the Expert Advisor, that executed the deal ... ulong magic; // // the ID of position, in which the deal was involved ... ulong positionId; // // Ticket ... ulong ticket; // // the name of the deal symbol ... string symbol; // // order by which the deal is executed ... ulong order; // // the time of deal execution ... datetime time; // // Deal price ... double price; // // the financial result of the deal (in deposit currency) ... double profit; // // the amount of swap when position is closed ... double swap; // // the amount of commission of the deal ... double commission; // // the volume of deal ... double volume; // // the deal comment ... string comment; // string provider; // ENUM_TIMEFRAMES period; // // the deal type ... // ------------------------------------------------------------------ // DEAL_TYPE_BUY => Buy ... // DEAL_TYPE_SELL => Sell ... // DEAL_TYPE_BUY_CANCELED => Canceled buy deal ... // There can be a situation when a previously executed buy deal is canceled. In this case, // the type of the previously executed deal (DEAL_TYPE_BUY) is changed to DEAL_TYPE_BUY_CANCELED, // and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation ... // // DEAL_TYPE_SELL_CANCELED => Canceled sell deal ... // There can be a situation when a previously executed sell deal is canceled. In this case, // the type of the previously executed deal (DEAL_TYPE_SELL) is changed to DEAL_TYPE_SELL_CANCELED, // and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation // // DEAL_TYPE_BALANCE => Balance ... // DEAL_TYPE_CREDIT => Credit ... // DEAL_TYPE_CHARGE => Additional charge ... // DEAL_TYPE_CORRECTION => Correction ... // DEAL_TAX => Tax charges ... // DEAL_TYPE_BONUS => Bonus ... // DEAL_TYPE_INTEREST => Interest rate ... // DEAL_DIVIDEND => Dividend operations... // DEAL_DIVIDEND_FRANKED => Franked (non-taxable) dividend operations ... // DEAL_TYPE_COMMISSION => Additional commission ... // DEAL_TYPE_COMMISSION_DAILY => Daily commission ... // DEAL_TYPE_COMMISSION_MONTHLY => Monthly commission ... // DEAL_TYPE_COMMISSION_AGENT_DAILY => Daily agent commission ... // DEAL_TYPE_COMMISSION_AGENT_MONTHLY => Monthly agent commission ENUM_DEAL_TYPE type; // // the deal direction ... // ---------------------------------- // DEAL_ENTRY_IN => Entry in ... // DEAL_ENTRY_OUT => Entry out ... // DEAL_ENTRY_INOUT => Reverse ... // DEAL_ENTRY_OUT_BY => Close a position by an opposite one ... ENUM_DEAL_ENTRY entry; // // deal reson ... // --------------------- // DEAL_REASON_SL => The deal was executed as a result of Stop Loss activation ... // DEAL_REASON_TP => The deal was executed as a result of Take Profit activation ... // DEAL_REASON_SO => The deal was executed as a result of the Stop Out event ... // DEAL_REASON_WEB => The deal was executed as a result of activation of an order placed from the web platform ... // DEAL_REASON_SPLIT => The deal was executed after the split (price reduction) of an instrument, which had an open position during split announcement ... // DEAL_REASON_CLIENT => The deal was executed as a result of activation of an order placed from a desktop terminal ... // DEAL_REASON_MOBILE => The deal was executed as a result of activation of an order placed from a mobile application ... // DEAL_REASON_EXPERT => The deal was executed as a result of activation of an order placed from an MQL5 program, i.e. an Expert Advisor or a script ... // DEAL_REASON_VMARGIN => The deal was executed after charging the variation margin ... // DEAL_REASON_ROLLOVER => The deal was executed due to a rollover ... ENUM_DEAL_REASON reason; // // Constructor ... XDeal() { Clean(); } // // Initializers ... bool ByIndex( int index // Deal Index ) { // bool result = false; // int dealsCount = HistoryDealsTotal(); result = dealsCount > 0; if (!result) { return result; } // static CDealInfo mDealInfo; // result = mDealInfo.SelectByIndex(index); if (!result) { // return result; } // // Reading Order Info ... swap = mDealInfo.Swap(); magic = mDealInfo.Magic(); order = mDealInfo.Order(); ticket = mDealInfo.Ticket(); time = mDealInfo.Time(); price = mDealInfo.Price(); symbol = mDealInfo.Symbol(); profit = mDealInfo.Profit(); volume = mDealInfo.Volume(); comment = mDealInfo.Comment(); positionId = mDealInfo.PositionId(); entry = mDealInfo.Entry(); commission = mDealInfo.Commission(); type = mDealInfo.DealType(); reason = (ENUM_DEAL_REASON)HistoryDealGetInteger( ticket, DEAL_REASON); // period = ExtractPeriod(comment); provider = ExtractProvider(comment); // result = IsValid(); // return result; } // // Tools ... // // Cleanup ... void Clean() { // magic = 0; positionId = 0; ticket = 0; order = 0; time = 0; price = 0; profit = 0; swap = 0; commission = 0; volume = 0; // symbol = NULL; comment = NULL; provider = NULL; // type = NULL; entry = NULL; period = NULL; reason = NULL; } // // Validate ... bool IsValid() { // bool result = false; // result = // IsValid(symbol) && NotEmpty(ticket) && NotEmpty(positionId) // ; // return result; } // // Calculate Age ... int GetAge( ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period ) { return GetAge(this, mPeriod); } // // Check this instance is Same os Given instance or not ... bool IsSameAs( const XDeal &value // instance for Compare ) { // bool result = false; // result = // type == value.type && magic == value.magic && entry == value.entry && reason == value.reason && ticket == value.ticket && volume == value.volume && symbol == value.symbol && provider == value.provider && positionId == value.positionId // ; // return result; } // // Find index in a Collection ... int FindIndex( const XDeal &values[] // Collection to Find ) { // return FindIndex( this, values // ); } // // Check Items Passed Specific Filters or not ... bool IsFiltersPassed( string mSymbol = NULL, // Trading Symbol string mProvider = NULL, // Signal Provider ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe ENUM_DEAL_TYPE mType = NULL, // Deal Type ENUM_DEAL_ENTRY mEntry = NULL, // Deal Entry ENUM_DEAL_REASON mReason = NULL, // Deal Reason ulong mMagic = NULL, // Magic Number bool mFilterByMagic = true // Get Only Self Open Positions ) { // bool result = false; // result = // // Magic Filter ... IsMagicFilterPassed( mMagic, mFilterByMagic, this // ) // && // // Symbol Filter ... IsSymbolFilterPassed( mSymbol, this // ) // && // // Provider Filter ... IsProviderFilterPassed( mProvider, this // ) // && // // Period Filter ... IsPeriodFilterPassed( mPeriod, this // ) // && // // Type Filter ... IsTypeFilterPassed( mType, this // ) // && // // Entry Filter ... IsEntryFilterPassed( mEntry, this // ) // && // // Reason Filter ... IsReasonFilterPassed( mReason, this // ) // ; // return result; } }; // // Model OnTrade Event Handler Result on XCTrade Class ... struct XOnTradeHandlerState { // bool hasNewDeal; int newDeals; // bool hasNewOrder; int newOrders; // bool hasNewPosition; int newPositions; // bool hasNewHistoryOrder; int newHistoryOrders; // // Constructor ... XOnTradeHandlerState() { Clean(); } // // Tools ... // // Cleanup ... void Clean() { // hasNewDeal = false; hasNewOrder = false; hasNewPosition = false; hasNewHistoryOrder = false; // newDeals = 0; newOrders = 0; newPositions = 0; newHistoryOrders = 0; } // // Validate ... bool IsValid() { // bool result = false; // result = // ( // hasNewDeal ? newDeals > 0 : true // ) // && // ( // hasNewOrder ? newOrders > 0 : true // ) // && // ( // hasNewPosition ? newPositions > 0 : true // ) // && // ( // hasNewHistoryOrder ? newHistoryOrders > 0 : true // ) // ; // return result; } }; // // Model Guard Info ... struct XGuard { // string symbol; // Trading Symbol ... string provider; // Signal Provider ... ENUM_TIMEFRAMES period; // Trading Timeframe ... ENUM_POSITION_TYPE type; // Position Type ... ENUM_X_GUARD_ACTIONS action; // Which Action to Do ... // double dblPayLoad; string strPayload; // // Constructor ... XGuard() { Clean(); } // // Initialize ... // // Global Initializer ... bool Init( string mSymbol, // Trading Symbol ... ENUM_TIMEFRAMES mPeriod, // Trading Timeframe ... ENUM_X_GUARD_ACTIONS mAction, // Which Action to Do ... ENUM_POSITION_TYPE mType = NULL, // Position Type ... string mProvider = NULL, // Signal Provider ... double mDblPayLoad = NULL, string mStrPayload = NULL // ) { // type = mType; symbol = mSymbol; period = mPeriod; action = mAction; provider = mProvider; dblPayLoad = mDblPayLoad; strPayload = mStrPayload; // bool result = IsValid(); // return result; } // // Tools ... // // Cleanup ... void Clean() { // symbol = NULL; provider = NULL; period = NULL; action = X_GUARD_ACTION_NOTHING; // strPayload = NULL; dblPayLoad = EMPTY_VALUE; } // // Validate ... bool IsValid() { // bool result = false; // result = // action != X_GUARD_ACTION_NOTHING // ; // return result; } }; // // Model a Position with all of it's Supports ... struct XPositionPack { // ulong ticket; // Main Position's Ticket // XPosition position; // Main Position (if Exists) // int supportOrdersCount; // Supported Orders (Untriggered) int supportPositionsCount; // Supported Positions // XOrder supportOrders[]; // Supported Orders (Untriggered) XPosition supportPositions[]; // Supported Positions // // Constructor ... XPositionPack() { Clean(); } // // Tools ... // // Cleanup ... void Clean() { // ticket = 0; // position.Clean(); // supportOrdersCount = 0; supportPositionsCount = 0; // Clean(supportOrders); Clean(supportPositions); } // // Validate ... bool IsValid() { // bool result = false; // result = // NotEmpty(ticket) && ( // supportOrdersCount > 0 ? ArraySize(supportOrders) == supportOrdersCount : true // ) // && // ( // supportPositionsCount > 0 ? ArraySize(supportPositions) == supportPositionsCount : true // ) // ; // return result; } }; // // Check Position SL Trails Structure ... struct XTrail { // ulong ticket; // Position Ticket ... ENUM_POSITION_TYPE type; // Type ... datetime time; // Trail Time ... double before; // SL Value Before Trailing ... double after; // SL Value After Trailing ... int level; // Number of Trails SL ... double profit; // Profit in SL Time ... // // Constructor ... XTrail() { Clean(); } // // Tools ... // bool Init( ulong mTicket, // Ticket ENUM_POSITION_TYPE mType, // Type double mProfit, // Profit double mBefore, // Before double mAfter // After ) { // Clean(); // type = mType; after = mAfter; ticket = mTicket; before = mBefore; profit = mProfit; // level++; // time = TimeCurrent(); // return IsValid(); } // bool Update( double mSl, // new SL ... double mProfit // Profit ) { // bool result = false; // time = TimeCurrent(); // double cAfter = after; after = mSl; before = cAfter; profit = mProfit; // level++; // result = IsValid(); // return result; } // string GenerateTag() { // string result = NULL; // string ticketLevelStr = ToString(ticket) + "," + ToString(level); // result = Surround( XSLTrailToken, ticketLevelStr // ); // return result; } // // Cleanup ... void Clean() { // ticket = 0; time = 0; before = 0; after = 0; level = 0; } // // Validate ... bool IsValid() { // bool result = false; // result = // ticket > 0 && time > 0 && level > 0 // ; // return result; } }; // // TypeDefs ... // typedef void (*TOnDealsChanged)(int count); // typedef void (*TOnOrdersChanged)(int count); // typedef void (*TOnPositionsChanged)(int count); // typedef void (*TOnStopLoss)(const XDeal &deal); typedef void (*TOnTakeProfit)(const XDeal &deal); // typedef void (*TOnTradeStateChanged)(const XOnTradeHandlerState &state); // // Classes ... // // Create a Signal Specfic Data Collector ... class XSCSignalCollector { // // Public ... public: // // Props ... // // Constructor ... void XSCSignalCollector() { // XSCDataCollector mBase; mBase.Clear(); } // // Deconstructor ... // // Tools ... // // Inheritanced Functions ... // // Cleaning Store ... void Clear() { // XSCDataCollector mBase; // mBase.Clear(); } // // Collect All Store ... int Collect(XSignal &result[]) { // int mResult = 0; // XSCDataCollector mBase; // mResult = mBase.Collect(result); // return mResult; } // // Add Item To Store ... bool Add(XSignal &item) { // bool result = false; // XSCDataCollector mBase; // result = mBase.Add(item); // return result; } // // Add Item(s) To Store ... int Add(XSignal &items[]) { // int result = 0; // XSCDataCollector mBase; // result = mBase.Add(items); // return result; } // // Remove an Item from Store ... bool Remove(XSignal &item) { // bool result = false; // XSCDataCollector mBase; // result = mBase.Remove(item); // return result; } // // Custom Functions ... // int CollectSignals( XSignal &result[], // Hold Result string symbol = NULL, // Trading Symbol string provider = NULL, // Signal Provider ENUM_TIMEFRAMES period = NULL, // Trading Timeframe ENUM_POSITION_TYPE type = NULL, // Long (Buy), Short (Sell) ENUM_X_ORDER_MODES mode = NULL // Execution Mode ) { // int mResult = 0; // XSignal signals[]; int signalsCount = Collect(signals); if (signalsCount <= 0) { return mResult; } // mResult = ArraySize(result); // // Now we Have to Apply Filters ... for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // bool isFiltersPassed = iSignal.IsFiltersPassed( symbol, provider, period, type, mode // ); if (!isFiltersPassed) { continue; } // AddRef( iSignal, result // ); } // return mResult; } // // Protected ... protected: // // Tools ... // // Private ... private: // // Props ... // // Tools ... }; // // Tools ... // bool IsValid(ENUM_X_ORDER_MODES value) { return value != X_ORDER_MODE_NOTHING; } // // Ages ... // // Retrieve a Position Age ... int GetAge( XPosition &position, // Selected Position ... ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... ) { // int result = -1; // if (period == NULL) { period = _Period; } // result = iBarShift( position.symbol, period, position.openAt); // return result; } // // Retrieve an Order Age ... int GetAge( XOrder &order, // Selected Order ... ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... ) { // int result = -1; // if (period == NULL) { period = _Period; } // result = iBarShift( order.symbol, period, order.setupAt); // return result; } // // Retrieve a Deal Age ... int GetAge( XDeal &deal, // Selected Deal ... ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... ) { // int result = -1; // if (period == NULL) { period = _Period; } // result = iBarShift( deal.symbol, period, deal.time); // return result; } // // Get Oldest Deal ... int GetOldest( XDeal &item, // Hold Result ... XDeal &items[] // Source Array ... ) { // int result = -1; // int itemsCount = ArraySize(items); if (itemsCount <= 0) { return result; } // int tmpAge = 0; XDeal tmpItem; for (int i = 0; i < itemsCount; i++) { // XDeal iItem = items[i]; // int iAge = GetAge(iItem); if (iAge > 0 && (tmpAge == 0 || tmpAge < iAge)) { // tmpAge = iAge; tmpItem = iItem; } } // if (tmpAge > 0) { // result = tmpAge; item = tmpItem; } // return result; } // // Get Youngest Deal ... int GetYoungest( XDeal &item, // Hold Result ... XDeal &items[] // Source Array ... ) { // int result = -1; // int itemsCount = ArraySize(items); if (itemsCount <= 0) { return result; } // int tmpAge = 0; XDeal tmpItem; for (int i = 0; i < itemsCount; i++) { // XDeal iItem = items[i]; // int iAge = GetAge(iItem); if (iAge > 0 && (tmpAge == 0 || tmpAge > iAge)) { // tmpAge = iAge; tmpItem = iItem; } } // if (tmpAge > 0) { // result = tmpAge; item = tmpItem; } // return result; } // // Get Oldest Order ... int GetOldest( XOrder &item, // Hold Result ... XOrder &items[] // Source Array ... ) { // int result = -1; // int itemsCount = ArraySize(items); if (itemsCount <= 0) { return result; } // int tmpAge = 0; XOrder tmpItem; for (int i = 0; i < itemsCount; i++) { // XOrder iItem = items[i]; // int iAge = GetAge(iItem); if (iAge > 0 && (tmpAge == 0 || tmpAge < iAge)) { // tmpAge = iAge; tmpItem = iItem; } } // if (tmpAge > 0) { // result = tmpAge; item = tmpItem; } // return result; } // // Get Youngest Order ... int GetYoungest( XOrder &item, // Hold Result ... XOrder &items[] // Source Array ... ) { // int result = -1; // int itemsCount = ArraySize(items); if (itemsCount <= 0) { return result; } // int tmpAge = 0; XOrder tmpItem; for (int i = 0; i < itemsCount; i++) { // XOrder iItem = items[i]; // int iAge = GetAge(iItem); if (iAge > 0 && (tmpAge == 0 || tmpAge > iAge)) { // tmpAge = iAge; tmpItem = iItem; } } // if (tmpAge > 0) { // result = tmpAge; item = tmpItem; } // return result; } // // Get Oldes Position ... int GetOldest( XPosition &item, // Hold Result ... XPosition &items[] // Source Array ... ) { // int result = -1; // int itemsCount = ArraySize(items); if (itemsCount <= 0) { return result; } // int tmpAge = 0; XPosition tmpItem; for (int i = 0; i < itemsCount; i++) { // XPosition iItem = items[i]; // int iAge = GetAge(iItem); if (iAge > 0 && (tmpAge == 0 || tmpAge < iAge)) { // tmpAge = iAge; tmpItem = iItem; } } // if (tmpAge > 0) { // result = tmpAge; item = tmpItem; } // return result; } // // Get Youngest Position ... int GetYoungest( XPosition &item, // Hold Result ... XPosition &items[] // Source Array ... ) { // int result = -1; // int itemsCount = ArraySize(items); if (itemsCount <= 0) { return result; } // int tmpAge = 0; XPosition tmpItem; for (int i = 0; i < itemsCount; i++) { // XPosition iItem = items[i]; // int iAge = GetAge(iItem); if (iAge > 0 && (tmpAge == 0 || tmpAge > iAge)) { // tmpAge = iAge; tmpItem = iItem; } } // if (tmpAge > 0) { // result = tmpAge; item = tmpItem; } // return result; } // // Check Filters ... // // Magic Filter ... template bool IsMagicFilterPassed( ulong magic, bool filterByMagic, T &item // ) { // return !filterByMagic ? true : !NotEmpty(magic) ? false : magic == item.magic; } // // Symbol Filter ... template bool IsSymbolFilterPassed( string symbol, T &item // ) { // return !IsValid(symbol) ? true : symbol == item.symbol; } // // Provider Filter ... template bool IsProviderFilterPassed( string provider, T &item // ) { // return !IsValid(provider) ? true : provider == item.provider; } // // Period Filter ... template bool IsPeriodFilterPassed( ENUM_TIMEFRAMES period, T &item // ) { // return !IsValid(period) ? true : period == item.period; } // // Type Filter ... template bool IsTypeFilterPassed( ENUM_POSITION_TYPE type, T &item // ) { // return type == NULL ? true : type == item.type; } template bool IsTypeFilterPassed( ENUM_ORDER_TYPE type, T &item // ) { // return type == NULL ? true : type == item.type; } template bool IsTypeFilterPassed( ENUM_DEAL_TYPE type, T &item // ) { // return type == NULL ? true : type == item.type; } // // Mode Filter ... template bool IsModeFilterPassed( ENUM_X_ORDER_MODES mode, T &item // ) { // return mode == NULL ? true : mode == item.mode; } // // Entry Filter ... template bool IsEntryFilterPassed( ENUM_DEAL_ENTRY entry, T &item // ) { // return entry == NULL ? true : entry == item.entry; } // // Reason Filter ... template bool IsReasonFilterPassed( ENUM_DEAL_REASON reason, T &item // ) { // return reason == NULL ? true : reason == item.reason; } // // State Filter ... template bool IsStateFilterPassed( ENUM_ORDER_STATE state, T &item // ) { // return state == NULL ? true : state == item.state; } // // // Find Specific Item Index inside a Collection ... template int FindIndex( T &item, // Item to Find const T &items[] // Items for Search ) { // int result = -1; // // Check Item Validation ... if (!item.IsValid()) { return result; } // int itemsCount = ArraySize(items); if (itemsCount <= 0) { return result; } // for (int i = 0; i < itemsCount; i++) { // T iItem = items[i]; // // Validate Item ... if (!iItem.IsValid()) { continue; } // bool isSame = item.IsSameAs(iItem); if (isSame && result <= -1) { // result = i; break; } } // return result; } // // // Calculate Positions Profit Summary ... double SpecifiedCalculatePositionsProfit( XPosition &positions[] // Source ) { // double result = 0; // int positionsCount = ArraySize(positions); if (positionsCount <= 0) { return result; } // for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // result += iPosition.profit; } // return result; } // // Calculate Required Profit for Hedging ... double SpecifiedCalculateRequiredProfitForHedge( XPosition &positions[], // Source double mMinProfitPerTrade, double mMinProfitPerVolumeFactor // ) { // double result = 0; // int positionsCount = ArraySize(positions); if (positionsCount <= 0) { return result; } // bool isHedgingEnable = mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0; if (!isHedgingEnable) { return result; } // for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // if (mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0) { // result += ((iPosition.volume / mMinProfitPerVolumeFactor) * mMinProfitPerTrade) + (-1 * iPosition.swap); } } // return result; } // bool SpecifiedIsPositionsReadyForHedge( XPosition &positions[], // Source double mMinProfitPerTrade, double mMinProfitPerVolumeFactor // ) { // double profit = SpecifiedCalculatePositionsProfit(positions); double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( positions, mMinProfitPerTrade, mMinProfitPerVolumeFactor // ); // bool result = requiredProfit > 0 ? profit >= requiredProfit : profit > requiredProfit; // return result; } // // Retrieve String Representation ... string ToString(ENUM_X_SIGNAL_EXECUTION_RESULT value) { // string result = NULL; // switch (value) { // case X_SIGNAL_EXECUTION_UNKNOWN: result = "Unknown"; break; // case X_SIGNAL_EXECUTION_SUCCEED: result = "Succed"; break; // case X_SIGNAL_EXECUTION_FAILED_SPREAD: result = "Spread more than Max Allowed"; break; // case X_SIGNAL_EXECUTION_FAILED_NO_EQUITY: result = "No Equity for Trade"; break; // case X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR: result = "Price Error"; break; // case X_SIGNAL_EXECUTION_FAILED_MAX_REACHED: result = "Max Allowed Positions Reached"; break; // case X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS: result = "Invalid Params"; break; } // return result; } // // Converts Position Type to Order Type ... ENUM_ORDER_TYPE ToOrderType(ENUM_POSITION_TYPE value) { // bool isLong = IsLong(value); // ENUM_ORDER_TYPE result = isLong ? ORDER_TYPE_BUY : ORDER_TYPE_SELL; // return result; } // // Tagging ... // // Generate Specified Tag for Using in Comments ... string GeneratePeriodTag(ENUM_TIMEFRAMES period) { // string strPeriod = ToString(period); return Surround( XPeriodToken, strPeriod // ); } // // Extract Period from a Tagged string ... ENUM_TIMEFRAMES ExtractPeriod(string value) { // ENUM_TIMEFRAMES result = NULL; // string pStr = ParseStringSurrounded( value, XPeriodToken // ); if (!IsValid(pStr)) { return result; } // result = ToPeriod(pStr); // return result; } // Generate Specified Tag for Using in Comments ... string GenerateProviderTag(string provider) { // return Surround( XProviderToken, provider // ); } // // Extract Provider from a Tagged string ... string ExtractProvider(string value) { // return ParseStringSurrounded( value, XProviderToken // ); } // // Generate Support Comment Tag ... string GenerateSupportTag(ulong ticket) { // return Surround( XSupportToken, ticket // ); } // // Extract Support Positions from a Tagged string ... ulong ExtractSupportedTicket(string value) { // return ParseLongSurrounded( value, XSupportToken // ); } // // Generate EQM Support Comment Tag ... string GenerateEQMSupportTag(ulong ticket) { // return Surround( XEQMSupportToken, ticket // ); } // // Extract EQM Support Positions from a Tagged string ... ulong ExtractEQMSupportedTicket(string value) { // return ParseLongSurrounded( value, XEQMSupportToken // ); } // // SL Trails ... // // Extract SL Trail Level ... int ExtractSLTrailLevel(string comment) { // int result = 0; // if (!IsValid(comment)) { return result; } // result = ParseIntSurrounded( comment, XSLTrailToken // ); // return result; } // // Generate SL Trail Comment Tag ... string GenerateSLTrailTag(int level) { // string result = NULL; // if (level <= 0) { return result; } // result = Surround( XSLTrailToken, level // ); // return result; } // // Prepare SL Trail Comment ... string PrepareSLTrailTag( const string comment // Original Position Comment ... ) { // string result = NULL; // int level = 0; result = comment; // // Check Comment Contains SL Trailing or not ... int lastTrailLevel = ExtractSLTrailLevel(comment); if (lastTrailLevel <= 0) { level++; } else { // level = lastTrailLevel + 1; string lastLevelStr = GenerateSLTrailTag(lastTrailLevel); StringReplace( result, lastLevelStr, "" // ); } // // Generate level Comment ... string levelStr = GenerateSLTrailTag(level); result += levelStr; // return result; } // // EQM Support Orders ... // int GenerateEQMOrders( XSignal &orders[], // Result XPosition &position, // Supported Position XOHCLSupRes &supRes, // Data Source bool longs = true, bool shorts = true // ) { // int result = 0; // Clean(orders); // if (!supRes.IsValid() || !position.IsValid()) { return result; } // if (longs) { // double longLevels[]; // Copy( supRes.res, longLevels // ); // double minSup = GetMin( supRes.sup // ); if (minSup > 0) { // Add( minSup, longLevels // ); } // ArraySort(longLevels); // if (ArraySize(longLevels) > 2) { // for (int i = 0; i < ArraySize(longLevels) - 2; i++) { // double iSL = longLevels[i]; double iEntry = longLevels[i + 1]; double iTP = longLevels[i + 2]; // XSignal iSignal; bool isPrepared = iSignal.PrepareStopLong( position.symbol, XEQMSupportToken, position.period, iEntry, position.volume, X_SIGNAL_USE_NOTHING, iSL, iTP // ); if (isPrepared) { // string comment = GenerateSupportTag(position.ticket); iSignal.comment = comment; // AddRef( iSignal, orders // ); } } } } // if (shorts) { // double shortLevels[]; // Copy( supRes.sup, shortLevels // ); // double maxRes = GetMax( supRes.res // ); if (maxRes > 0) { // Add( maxRes, shortLevels // ); } // ArraySort(shortLevels); ArrayReverse(shortLevels); // if (ArraySize(shortLevels) > 2) { // for (int i = 0; i < ArraySize(shortLevels) - 2; i++) { // double iSL = shortLevels[i]; double iEntry = shortLevels[i + 1]; double iTP = shortLevels[i + 2]; // XSignal iSignal; bool isPrepared = iSignal.PrepareStopShort( position.symbol, XEQMSupportToken, position.period, iEntry, position.volume, X_SIGNAL_USE_NOTHING, iSL, iTP // ); if (isPrepared) { // string comment = GenerateSupportTag(position.ticket); iSignal.comment = comment; // AddRef( iSignal, orders // ); } } } } // result = ArraySize(orders); // return result; } // // Count Positions from a Collection ... void CountPositions( const XPosition &positions[], int &longs, double &longProfits, double &longVolumes, // // int &shorts, double &shortProfits, double &shortVolumes // ) { // longs = 0; longProfits = 0; longVolumes = 0; // shorts = 0; shortProfits = 0; shortVolumes = 0; // int positionsCount = ArraySize(positions); if (!IsValidSize(positionsCount)) { return; } // for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // bool isLong = IsLong(iPosition.type); if (isLong) { // longs++; longProfits += iPosition.profit; longVolumes = iPosition.volume; } else { // shorts++; shortProfits += iPosition.profit; shortVolumes = iPosition.volume; } } }