/////////////////////////////////////////////////////// // // 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 "../Libraries/x-saherelm.common.lib.mq5" #include // // 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 XEQPToken = "EQP"; // string XSLTrailToken = "SLT"; // string XActionToken = "A"; // string XDirectionalToken = "D"; string XINDirectionalToken = "IND"; // string XRecoveryToken = "XRCV"; // // 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 }; // string ToString(ENUM_X_ORDER_MODES value) { // string result = NULL; // switch (value) { // case X_ORDER_MODE_MARKET: result = "Market"; break; // case X_ORDER_MODE_LIMIT: result = "Limit"; break; // case X_ORDER_MODE_STOP: result = "Stop"; break; // case X_ORDER_MODE_STOP_LIMIT: result = "StopLimit"; break; } // return result; } // // 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_NOT_ALLOWED, // Not Allowed Trade Type X_SIGNAL_EXECUTION_FAILED_NO_EQUITY, // No Equity for Trade X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR, // Price Error X_SIGNAL_EXECUTION_FAILED_PREV_PROFIT_ERROR, // Prev Profit Error X_SIGNAL_EXECUTION_FAILED_MAX_REACHED, // Max Allowed Positions Reached X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED, // Same Positions Delay Not Passed X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS, // Invalid Params }; // // 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 }; // enum ENUM_X_POSITION_TYPES { X_POSITION_TYPE_NONE = 0, X_POSITION_TYPE_ALL = 1, X_POSITION_TYPE_LONG = 2, X_POSITION_TYPE_SHORT = 3, }; // string ToString(ENUM_X_POSITION_TYPES value) { // string result = NULL; // switch (value) { // case X_POSITION_TYPE_ALL: result = "All"; break; // case X_POSITION_TYPE_NONE: result = "NONE"; break; // case X_POSITION_TYPE_SHORT: result = "Short"; break; // case X_POSITION_TYPE_LONG: result = "Long"; break; } // return result; } // bool IsLong(ENUM_X_POSITION_TYPES value) { return value == X_POSITION_TYPE_LONG; } // bool ToPositionType( ENUM_POSITION_TYPE &dest, ENUM_X_POSITION_TYPES source // ) { // bool result = false; // result = source == X_POSITION_TYPE_LONG || source == X_POSITION_TYPE_SHORT; if (!result) { return result; } // dest = source == X_POSITION_TYPE_LONG ? POSITION_TYPE_BUY : POSITION_TYPE_SELL; // return result; } // ENUM_X_POSITION_TYPES ToPositionType(ENUM_POSITION_TYPE value) { return IsLong(value) ? X_POSITION_TYPE_LONG : X_POSITION_TYPE_SHORT; } // ENUM_X_POSITION_TYPES OppositPositionType(ENUM_POSITION_TYPE type) { // ENUM_X_POSITION_TYPES result = X_POSITION_TYPE_NONE; // bool isLong = IsLong(type); bool isShort = IsShort(type); // result = // isLong ? X_POSITION_TYPE_SHORT : isShort ? X_POSITION_TYPE_LONG : X_POSITION_TYPE_NONE // ; // return result; } // ENUM_X_DIRECTION ToDirection(ENUM_POSITION_TYPE value) { // ENUM_X_DIRECTION result = X_DIRECTION_NONE; // result = IsLong(value) ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // return result; } // ENUM_X_DIRECTION ToDirection(ENUM_X_POSITION_TYPES value) { // ENUM_X_DIRECTION result = X_DIRECTION_NONE; // result = value == X_POSITION_TYPE_ALL ? X_DIRECTION_ALL : value == X_POSITION_TYPE_LONG ? X_DIRECTION_BULLISH : value == X_POSITION_TYPE_SHORT ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; // return result; } // // Structs ... // struct XRR { // double tps[]; // double sl; double entry; // string prefix; string symbol; datetime time; ENUM_TIMEFRAMES period; // ENUM_X_POSITION_TYPES type; // // Constructor ... XRR() { Clean(); } // // Tools ... // void Clean() { // sl = 0; entry = 0; // time = NULL; prefix = NULL; period = NULL; symbol = NULL; // type = X_POSITION_TYPE_NONE; // Clean(tps); // ZeroMemory(this); } // bool Init( string _symbol, ENUM_TIMEFRAMES _period, double _sl, double _entry, ENUM_X_POSITION_TYPES _type, string _prefix = NULL // ) { // bool result = false; // result = _sl > 0 && _entry > 0 && IsValid(_symbol) && IsValid(_period) && _type != X_POSITION_TYPE_ALL && _type != X_POSITION_TYPE_NONE && (_type == X_POSITION_TYPE_LONG ? _entry > _sl : _entry < _sl); if (!result) { return result; } // Default(); // sl = _sl; type = _type; entry = _entry; symbol = _symbol; period = _period; prefix = _prefix; // time = TimeCurrent(); // result = IsValid(); // return result; } // void Default() { // Add( 1.0, tps // ); Add( 1.5, tps // ); Add( 2.0, tps // ); Add( 3.0, tps // ); Add( 4.0, tps // ); Add( 5.0, tps // ); Add( 6.0, tps // ); } // bool IsValid() { // bool result = false; // result = sl > 0 && entry > 0 && IsValid(time) && IsValid(symbol) && IsValid(period) && IsValidSize(ArraySize(tps)) && type != X_POSITION_TYPE_ALL && type != X_POSITION_TYPE_NONE && (type == X_POSITION_TYPE_LONG ? entry > 0 : entry < sl); // return result; } // string GetTag() { // string result = NULL; // if (!IsValid()) { // result = GetTypeName(this); return result; } // string sep = "_"; // result = GetTypeName(this) + sep + (IsValid(prefix) ? prefix + sep : "") + symbol + sep + ToString(period) + sep + ToFormatString(time) + sep + ToString(type); // return result; } }; // // Model a Target ... struct XTarget { // // Props ... bool doRF; // Do RF on Target double target; // Target Price for Actions double volumeMultiplier; // Volume Multiplier for Partial Close // // Constructor ... XTarget() { Clean(); } // // Tools ... // // Cleanup ... void Clean() { // target = 0; doRF = false; volumeMultiplier = 0; } // // Validate ... bool IsValid() { // bool result = false; // result = target > 0; // return result; } }; // // Get Lowest Target index ... int GetLowest(XTarget &targets[]) { // int result = -1; // if (!HasChild(targets)) { return result; } // XTarget iTarget; int count = ArraySize(targets); for (int i = 0; i < count; i++) { // bool canSet = !iTarget.IsValid() ? true : iTarget.target > targets[i].target; if (canSet) { // result = i; iTarget = targets[i]; } } // iTarget.Clean(); // return result; } // // Get Highest Target index ... int GetHighest(XTarget &targets[]) { // int result = -1; // if (!HasChild(targets)) { return result; } // XTarget iTarget; int count = ArraySize(targets); for (int i = 0; i < count; i++) { // bool canSet = !iTarget.IsValid() ? true : iTarget.target < targets[i].target; if (canSet) { // result = i; iTarget = targets[i]; } } // iTarget.Clean(); // return result; } // // Apply Sorting on Targets ... void ApplySortOnTargets( ENUM_X_DIRECTION forDir, // Target Sorting Direction ... XTarget &targets[] // Targets to Apply Sorting ... ) { // bool has = HasChild(targets) && HasDirection(forDir); if (!has) { return; } // bool isBullish = IsBullish(forDir); bool isBearish = IsBearish(forDir); // XTarget tmp[]; Copy( targets, tmp // ); Clean(targets); while (HasChild(tmp)) { // int idx = -1; if (isBullish) { idx = GetLowest(tmp); } else if (isBearish) { idx = GetHighest(tmp); } // has = IsValidIndex(idx); if (!has) { break; } // XTarget iTarget = tmp[idx]; ArrayRemove( tmp, idx, 1 // ); AddRef( iTarget, targets // ); } // Clean(tmp); } // // 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; // ZeroMemory(this); } // // 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; } // double GetPointsValue() { // double result = 0; // if (!IsValid()) { return result; } // result = GetPoints(symbol); // return result; } // double GetProfitInPoint() { // double result = 0; // if (!IsValid()) { return result; } // double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE); // Tick size double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE); // Tick value double pointSize = SymbolInfoDouble(symbol, SYMBOL_POINT); // Point size double pointValue = tickValue * pointSize / tickSize; // Point value // result = profit / (volume * tickValue); // return result; } // // Find Risk ... double GetRisk() { // double result = 0; // if (!IsValid()) { return 0; } // result = MathAbs(entry - sl); // return result; } // // Find Reward ... double GetReward() { // double result = 0; // if (!IsValid()) { return result; } // result = MathAbs(tp - entry); // return result; } // double GetRewardInPoint() { // double result = 0; // result = GetReward() / GetPoints(); // return result; } // // Find Risk Reward Ratio ... double GetRiskRewardRatio() { // double result = 0; // if (!IsValid()) { return result; } // result = GetReward() / GetRisk(); // return result; } // // Calculate TP Levels ... int CalculateTPLevels(double &tps[]) { // int result = 0; // Clean(tps); // bool isValid = IsValid(); if (!isValid) { return result; } // double risk = GetRisk(); int r2r = (int)GetRiskRewardRatio(); bool isLong = IsLong(type); for (int i = 0; i < r2r; i++) { // double iValue = isLong ? entry + risk + (i * risk) : entry - risk - (i * risk); // Add( iValue, tps // ); } // result = ArraySize(tps); // return result; } // // Calculate Reached TP Levels ... void CalculateReahedTP( double &reachedLevel, double &reachedPrice // ) { // reachedLevel = -1; reachedPrice = 0; double tps[]; bool isLong = IsLong(type); double exitPrice = GetExit(); int tpLevels = CalculateTPLevels(tps); if (!IsValidSize(tpLevels) || exitPrice <= 0) { return; } // for (int i = 0; i < tpLevels - 1; i++) { // double cTP = tps[i]; double nTP = tps[i + 1]; // bool isReached = isLong ? exitPrice > cTP && exitPrice < nTP : exitPrice < cTP && exitPrice > nTP; if (isReached) { // reachedLevel = i + 1; reachedPrice = cTP; } } } // // Calculate Touched Reward ... double CalculateTouchedReward() { // double result = 0.0; // bool has = IsValid() && profit > 0; if (!has) { return result; } // double risk = MathAbs(entry - sl); double currentReward = MathAbs(price - entry); // result = currentReward / risk; // 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_X_POSITION_TYPES 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 a Signal ... struct XSignal { // // Props ... // ulong positionId; // if Executed this filled ... // datetime time; // Issue Time ... // double tp; // Take Profit ... double sl; // Stop Loss ... double entry; // Exntry or Execution Price ... double volume; // Position Volume ... // string symbol; // Trading Symbol ... string comment; // Comment ... string provider; // Signaller ... // ENUM_TIMEFRAMES period; // Trading TimeFrame ... ENUM_POSITION_TYPE type; // Long (Buy) or Short (Sell) ... ENUM_X_ORDER_MODES mode; // Execution Mode ... // string conditions; // Signal Conditions ... // // Additional ... // // Traget ... XTarget targets[]; // Provided Targets ... int appliedTargetIDX; // Last Applied Target Index ... bool ignoreEAVolume; // Ignore EA Volume ... bool isTargetApplied; // Check if Target Applied or not ... // // Constructor ... XSignal() { Default(); } // // Tools ... // // Cleanup ... void Clean() { // entry = 0; volume = 0; positionId = 0; // time = NULL; type = NULL; mode = NULL; symbol = NULL; period = NULL; comment = NULL; provider = NULL; conditions = NULL; // Clean(targets); appliedTargetIDX = -1; ignoreEAVolume = false; isTargetApplied = false; // ZeroMemory(this); } // // Default Values ... void Default() { // entry = 0; volume = 0; positionId = 0; // time = NULL; type = NULL; mode = NULL; symbol = NULL; period = NULL; comment = NULL; provider = NULL; conditions = NULL; // Clean(targets); appliedTargetIDX = -1; ignoreEAVolume = false; isTargetApplied = false; } // // Validate ... bool IsValid() { // bool result = false; // result = // IsValid(period) && IsValid(symbol) && NotEmpty(volume) && NotEmpty(entry) // ; // if (!result) { return result; } // return result; } // // DO All Calculations and Normalizations ... bool Normalize() { // bool result = false; // // Normalizations ... symbol = NormalizeSymbol(symbol); period = NormalizePeriod(period); // time = NormalizeTime(time); // sl = NormalizePrice(sl, symbol); tp = NormalizePrice(tp, symbol); entry = NormalizePrice(entry, symbol); volume = NormalizeVolume(volume, symbol); // result = IsValid(); // 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; } // int GetAge() { // return GetAge( this, this.period // ); } // // Find Risk ... double GetRisk() { // double result = 0; // if (!IsValid()) { return 0; } // result = MathAbs(entry - sl); // return result; } // // Find Reward ... double GetReward() { // double result = 0; // if (!IsValid()) { return result; } // result = MathAbs(tp - entry); // return result; } // // Find Risk Reward Ratio ... double GetRiskRewardRatio() { // double result = 0; // if (!IsValid()) { return result; } // result = GetReward() / GetRisk(); // return result; } // string GetTag() { // string result = NULL; // result = "XSignal_" + symbol + "_" + ToString(period) + "_" + ToString(type) + "_" + ToString(sl) + "_" + ToString(tp) + "_" + ToString(entry); // return result; } // // Retrieve String Representation of Signal ... string ToString() { // string result = NULL; // result = // ToString("Symbol", symbol) + ToString("Period", period) + ToString("Provider", provider) + ToString("Type", type) + ToString("Mode", mode) + ToString("Volume", volume) + ToString("Entry", entry) + ToString("TP", tp) + ToString("SL", sl) + ToString("Time", time) + ToString("Comment", comment) + // "" // ; // return result; } // bool IsSameAs(XSignal &item) { // bool result = false; // result = // IsValid() && item.IsValid() && // tp == item.tp && sl == item.sl && mode == item.mode && time == item.time && type == item.type && entry == item.entry && symbol == item.symbol && period == item.period && provider == item.provider // ; // return result; } // string GetMessage(string action = NULL) { // string result = NULL; // if (!IsValid()) { return result; } // result = ToString(type) + " Signal" + (!IsValid(action) ? "" : " " + action) + " by: " + provider + " on (" + symbol + ")" + " in: " + ToString(period); // return result; } // string GetFileName() { // string result = NULL; // if (!IsValid()) { return result; } // result = // symbol + "\\" + ToString(type) + "\\" + ToString(period) + "_" + ToFormatString(time) // ; // 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; // ZeroMemory(this); } // // 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_X_POSITION_TYPES 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; // ZeroMemory(this); } // // 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; // ZeroMemory(this); } // // 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_X_POSITION_TYPES 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_X_POSITION_TYPES 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; // ZeroMemory(this); } // // 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); // ZeroMemory(this); } // // 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; // ZeroMemory(this); } // // Validate ... bool IsValid() { // bool result = false; // result = // ticket > 0 && time > 0 && level > 0 // ; // return result; } }; // struct XSymbolPositions { // string symbol; // double profit; double volume; // double longsProfit; double longSupportsProfit; // double shortsProfit; double shortSupportsProfit; // double longsVolume; double longSupportsVolume; // double shortsVolume; double shortSupportsVolume; // double requiredProfitForHedge; // XPosition longs[]; XPosition shorts[]; XPosition supports[]; XPosition positions[]; XPosition longSupports[]; XPosition shortSupports[]; // bool forceHedge; // XSymbolPositions() { Clean(); } // bool Update( double mMinProfitPerTrade, double mMinProfitPerVolumeFactor // ) { // bool result = false; // bool hasChild = HasChild(); if (!hasChild) { return result; } // XPosition _supports[]; XPosition _positions[]; // XPosition _tmp[]; // Copy( positions, _tmp // ); // Clean(positions); // int tmpsCount = ArraySize(_tmp); for (int i = 0; i < tmpsCount; i++) { // XPosition iPosition = _tmp[i]; // bool isSupport = IsSupport(iPosition.comment); if (!isSupport) { // AddRef( iPosition, _positions // ); } else { // AddRef( iPosition, _supports // ); } } // Clean(_tmp); // Copy( _positions, positions // ); Clean(_positions); // // Extract Types ... ExtractPositions( positions, longs, shorts // ); // Copy( _supports, supports // ); Clean(_supports); // // Extract Types ... ExtractPositions( supports, longSupports, shortSupports // ); // int numOfLongs = 0; int numOfShorts = 0; CountPositions( positions, numOfLongs, longsProfit, longsVolume, numOfShorts, shortsProfit, shortsVolume // ); // numOfLongs = 0; numOfShorts = 0; CountPositions( supports, numOfLongs, longSupportsProfit, longSupportsVolume, numOfShorts, shortSupportsProfit, shortSupportsVolume // ); // XPosition _allPositions[]; Copy( positions, _allPositions, false // ); Copy( supports, _allPositions, false // ); // profit = longsProfit + shortsProfit + longSupportsProfit + shortSupportsProfit; volume = longsVolume + shortsVolume + longSupportsVolume + shortSupportsVolume; requiredProfitForHedge = SpecifiedCalculateRequiredProfitForHedge( _allPositions, mMinProfitPerTrade, mMinProfitPerVolumeFactor // ); // Clean(_allPositions); // result = true; // return result; } // // Tools ... // // Cleanup ... void Clean() { // symbol = NULL; forceHedge = false; // profit = 0; longsProfit = 0; shortsProfit = 0; // volume = 0; longsVolume = 0; shortsVolume = 0; // requiredProfitForHedge = 0; // Clean(longs); Clean(shorts); Clean(positions); // ZeroMemory(this); } // // Validate ... bool IsValid() { // bool result = false; // result = IsValid(symbol); // return result; } // // Has Child ... bool HasChild() { // bool result = false; // result = IsValid(); if (!result) { return result; } // int count = Count(); result = IsValidSize(count); // return result; } // // Count ... int Count() { return ArraySize(positions); } // int CountSupports() { return ArraySize(supports); } // int CountLongs() { return ArraySize(longs); } // int CountShorts() { return ArraySize(shorts); } // int CountLongSupports() { return ArraySize(longSupports); } // int CountShortSupports() { return ArraySize(shortSupports); } // int GetOldest( XPosition &_oldest, // ENUM_POSITION_TYPE _type // ) { // int result = -1; // bool isLong = IsLong(_type); // int count = isLong ? CountLongs() : CountShorts(); if (!IsValidSize(count)) { return result; } // if (isLong) { // result = GetOldest( _oldest, longs // ); } else { // result = GetOldest( _oldest, shorts // ); } // return result; } // int GetYoungest( XPosition &_youngest, // ENUM_POSITION_TYPE _type // ) { // int result = -1; // bool isLong = IsLong(_type); // int count = isLong ? CountLongs() : CountShorts(); if (!IsValidSize(count)) { return result; } // if (isLong) { // result = GetYoungest( _youngest, longs // ); } else { // result = GetYoungest( _youngest, shorts // ); } // return result; } // int GetMaxInProfit( XPosition &_position, ENUM_POSITION_TYPE _type // ) { // int result = -1; // bool isLong = IsLong(_type); // int count = isLong ? CountLongs() : CountShorts(); if (!IsValidSize(count)) { return result; } // if (isLong) { // result = FindMaxProfitIndex( longs // ); // if (IsValidIndex(result)) { _position = longs[result]; } } else { // result = FindMaxProfitIndex( shorts // ); // if (IsValidIndex(result)) { _position = shorts[result]; } } // return result; } // int GetMinInProfit( XPosition &_position, ENUM_POSITION_TYPE _type // ) { // int result = -1; // bool isLong = IsLong(_type); // int count = isLong ? CountLongs() : CountShorts(); if (!IsValidSize(count)) { return result; } // if (isLong) { // result = FindMinProfitIndex( longs // ); // if (IsValidIndex(result)) { _position = longs[result]; } } else { // result = FindMinProfitIndex( shorts // ); // if (IsValidIndex(result)) { _position = shorts[result]; } } // return result; } // int GetMaxInDrawdown( XPosition &_position, ENUM_POSITION_TYPE _type // ) { // int result = -1; // bool isLong = IsLong(_type); // int count = isLong ? CountLongs() : CountShorts(); if (!IsValidSize(count)) { return result; } // if (isLong) { // result = FindMaxInDrawdownIndex( longs // ); // if (IsValidIndex(result)) { _position = longs[result]; } } else { // result = FindMaxInDrawdownIndex( shorts // ); // if (IsValidIndex(result)) { _position = shorts[result]; } } // return result; } // int GetMinInDrawdown( XPosition &_position, ENUM_POSITION_TYPE _type // ) { // int result = -1; // bool isLong = IsLong(_type); // int count = isLong ? CountLongs() : CountShorts(); if (!IsValidSize(count)) { return result; } // if (isLong) { // result = FindMinInDrawdownIndex( longs // ); // if (IsValidIndex(result)) { _position = longs[result]; } } else { // result = FindMinInDrawdownIndex( shorts // ); // if (IsValidIndex(result)) { _position = shorts[result]; } } // return result; } // }; // struct XSymbolLastPosition { // string symbol; string provider; datetime time; // XSymbolLastPosition() { Clean(); } // // Tools ... void Clean() { // time = NULL; symbol = NULL; provider = NULL; // ZeroMemory(this); } }; // // an Structure for Holding Positions Data ... struct XTradeData { // datetime time; // Issue Time (Open Position) string symbol; // Trading Symbol double entry; // Entry Price double volume; // Volume string provider; // Signaller ENUM_TIMEFRAMES period; // Trading Timeframe ENUM_X_POSITION_TYPES type; // Position Type // ulong ticket; // Position Ticket double swap; // Swap double profit; // Profit on Close double commission; // Commission double maxDrawdown; // Max Position Drawdown string message; // Close Reason datetime endTime; // End Time // XSignal signal; // Signal Object int pushers; // Signal Pushers string conditions; // Signal Conditions // // Constructor ... void XTradeInfo() { Clean(); } // // Filling Trade Handler ... bool Fill(XSignal &_signal) { // bool result = false; // Clean(); // // Check Signal Validation ... result = _signal.IsValid(); if (!result) { return result; } // signal = _signal; time = _signal.time; entry = _signal.entry; symbol = _signal.symbol; volume = _signal.volume; period = _signal.period; provider = _signal.provider; conditions = _signal.conditions; type = ToPositionType(_signal.type); // if (_signal.IsExecuted()) { ticket = _signal.positionId; } // return result; } // // Filling Trade Handler ... bool Fill(XPosition &_position) { // bool result = false; // Clean(); // // Check Signal Validation ... result = _position.IsValid(); if (!result) { return result; } // time = _position.openAt; symbol = _position.symbol; entry = _position.entry; volume = _position.volume; provider = _position.provider; period = _position.period; type = ToPositionType(_position.type); // ticket = _position.ticket; // return result; } // // Update Data ... bool Update(XPosition &_position) { // bool result = false; // result = _position.IsValid(); if (!result) { return result; } // profit = _position.profit; swap = _position.swap; // if (profit < 0 && (maxDrawdown == 0 || MathAbs(profit) > MathAbs(maxDrawdown))) { maxDrawdown = profit; } // return result; } // // Tools ... // // Cleanup ... void Clean() { // time = NULL; type = NULL; symbol = NULL; period = NULL; endTime = NULL; message = NULL; provider = NULL; // swap = 0; entry = 0; ticket = 0; profit = 0; volume = 0; commission = 0; maxDrawdown = 0; // signal.Clean(); // ResetTrail(); ResetRecovery(); // ZeroMemory(this); } // // Validation ... bool IsValid() { // bool result = false; // result = // ticket > 0 && IsValid(time) && IsValid(symbol) && IsValid(period) // ; // return result; } // // Retrieve Trade Data Age ... int GetAge() { // int result = -1; // if (!IsValid(symbol) || !IsValid(time) || !IsValid(endTime) || !IsValid(period)) { return result; } // int startIndex = iBarShift( symbol, period, time, false // ); // int endIndex = iBarShift( symbol, period, endTime, false // ); // result = MathAbs(startIndex - endIndex); // return result; } // // Check Own of Trade Data ... // based on Ticket ... bool IsOwn( ulong _ticket // ) { // bool result = false; // result = _ticket == ticket; // return result; } // // Check Own of Trade Data ... // based on Symbol/Provider and Period ... bool IsOwn( string _symbol, string _provider, ENUM_TIMEFRAMES _period, ENUM_X_POSITION_TYPES _type // ) { // bool result = false; // result = // IsValid(_symbol) && IsValid(_period) && IsValid(_provider) && type != X_POSITION_TYPE_ALL && type != X_POSITION_TYPE_NONE && // type == _type && period == _period && symbol == _symbol && provider == _provider // ; // return result; } // // Data Collector ... // // Get Data File Name ... string GetFileName() { // string result = NULL; // if (!IsValid()) { return result; } // result = // symbol + "\\" + ToString(type) + "\\" + (profit >= 0 ? "Profit" : "Loss") + "\\" + ToString(ticket) + "_" + ToString(period) + "_" + ToFormatString(time) // ; // return result; } // // Get Signal File Name ... string GetSignalFileName() { // string result = NULL; // result = // symbol + "\\" + ToString(type) + "\\" + provider + "_" + ToFormatString(time) // ; // return result; } // // Convert(s) To String Representation(s) ... string ToString( bool onlySignals = false // ) { // string result = NULL; // int age = GetAge(); // result = // (onlySignals ? "" : ToString("Ticket", ticket)) + ToString("Symbol", symbol) + ToString("Period", period) + ToString("Entry", entry) + ToString("Provider", provider) + ToString("Type", ToString(type)) + ToString("Time", time) + // // Attach Trade Info ... (onlySignals ? "" : // "-------------" + "\n" + ToString("Volume", volume) + ToString("Profit", profit) + ToString("Commission", commission) + ToString("Swap", swap) + ToString("Max Drawdown", maxDrawdown) + ToString("End Time", endTime) + ToString("Age", age) + ToString("Message", message) + "" // ) + // // Attach Conditions to Signals ... (!onlySignals ? "" : // "-------------" + "\n" + ToString("Pushers", pushers) + "Conditions:" + "\n" + "-------------" + "\n" + conditions + "" // ) + // "" // ; // return result; } // // There are some Controlling Situations for each Trade // which implemented here ... // // Trailing Stop .... // bool allowTrailStop; // Specified Position Can Trail Stop or not bool ignoreTPOnTrail; // Ignore TP when SL Trailed bool trailBasedOnProfit; // Do Trail Based on Profit Points int trailLevel; // Last Trail Level double trailStartInPoint; // Trail Starts When Profits Growing in Point double trailStepInPoint; // Profit Must Grows Point to do Trailling // // Reset all Trailing Configurations .... void ResetTrail() { // trailLevel = 0; trailStepInPoint = 0; trailStartInPoint = 0; allowTrailStop = false; ignoreTPOnTrail = false; trailBasedOnProfit = false; } // // Recovery ... // bool allowRecover; // Allow Recover Specified Position double recoveryTPPoint; // Recovery TP Point double recoverySLPoint; // Recovery SL Point int maxAllowedRecover; // Max Allowed Recovery int recoveryLevel; // Number of Recovery Signals double recoveryVolumeMultiplier; // Recovery Volume Multiplier double recoveryVolume; // Next Recovery Positioin Volume ENUM_X_POSITION_TYPES recoveryLookingType; // Looking for Next Recovery Type // void ResetRecovery() { // allowRecover = false; recoveryLevel = 0; recoveryVolume = 0; recoveryTPPoint = 0; recoverySLPoint = 0; recoveryVolumeMultiplier = 0; recoveryLookingType = X_POSITION_TYPE_NONE; } // }; // // TypeDefs ... // typedef void (*TOnSignal)(XSignal &signal); // 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); // typedef void (*TOnForceClose)( const ulong ticket, const XPosition &position, const string comment // ); // typedef void (*TOnPartialClose)( const ulong ticket, const double profit, const string comment // ); // typedef void (*TOnModify)( const ulong ticket, const double profit, const string comment // ); // // Classes ... // // Tools ... // bool IsValid(ENUM_X_ORDER_MODES value) { return value != X_ORDER_MODE_NOTHING; } // // Ages ... // // Retrieve a Position Age ... int GetAge( XSignal &signal, // Selected Signal ... ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... ) { // int result = -1; // if (period == NULL) { period = _Period; } // result = iBarShift( signal.symbol, period, signal.time); // return result; } // // 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; } // int FindMaxProfitIndex( XPosition &positions[] // Position Collection ) { // int result = -1; // int positionsCount = ArraySize(positions); if (!IsValidSize(positionsCount)) { return result; } // double max = 0; for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; if (iPosition.profit <= 0) { continue; } // if (max == 0 || max < iPosition.profit) { // result = i; max = iPosition.profit; } } // return result; } // int FindMinProfitIndex( XPosition &positions[] // Position Collection ) { // int result = -1; // int positionsCount = ArraySize(positions); if (!IsValidSize(positionsCount)) { return result; } // double min = 0; for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; if (iPosition.profit <= 0) { continue; } // if (min == 0 || min > iPosition.profit) { // result = i; min = iPosition.profit; } } // return result; } // int ExtractInProfitPositions( XPosition &positions[], // Position Collection XPosition &inProfits[] // Result ) { // int result = 0; // Clean(inProfits); // int positionsCount = ArraySize(positions); if (!IsValidSize(positionsCount)) { return result; } // for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // if (iPosition.profit > 0) { // AddRef( iPosition, inProfits // ); } } // result = ArraySize(inProfits); // return result; } // int FindMaxInDrawdownIndex( XPosition &positions[] // Position Collection ) { // int result = -1; // int positionsCount = ArraySize(positions); if (!IsValidSize(positionsCount)) { return result; } // double max = 0; for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; if (iPosition.profit >= 0) { continue; } // if (max == 0 || MathAbs(max) < MathAbs(iPosition.profit)) { // result = i; max = iPosition.profit; } } // return result; } // int FindMinInDrawdownIndex( XPosition &positions[] // Position Collection ) { // int result = -1; // int positionsCount = ArraySize(positions); if (!IsValidSize(positionsCount)) { return result; } // double min = 0; for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; if (iPosition.profit >= 0) { continue; } // if (min == 0 || min > iPosition.profit) { // result = i; min = iPosition.profit; } } // return result; } // int ExtractInDrawdownPositions( XPosition &positions[], // Position Collection XPosition &inDradowns[] // Result ) { // int result = 0; // Clean(inDradowns); // int positionsCount = ArraySize(positions); if (!IsValidSize(positionsCount)) { return result; } // for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // if (iPosition.profit < 0) { // AddRef( iPosition, inDradowns // ); } } // result = ArraySize(inDradowns); // 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 // ) { // bool result = type == item.type; // return result; } template bool IsTypeFilterPassed( ENUM_X_POSITION_TYPES type, T &item // ) { // bool result = type == NULL || type == X_POSITION_TYPE_ALL ? true : ((type == X_POSITION_TYPE_LONG && ((int)item.type == (int)POSITION_TYPE_BUY || (int)item.type == (int)ORDER_TYPE_BUY)) || (type == X_POSITION_TYPE_SHORT && ((int)item.type == (int)POSITION_TYPE_SELL || (int)item.type == (int)ORDER_TYPE_SELL))); // return result; } 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; } // // // // 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; } // int FindCoverageDrawdownPosition( XPosition &position, // In Drawdown Position XPosition &inProfits[], // In Profit Positions XPosition &coverage[], // Coverage Positons double mMinProfitPerTrade, double mMinProfitPerVolumeFactor // ) { // int result = 0; // Clean(coverage); // if (!position.IsValid() || position.profit >= 0) { return result; } // int inProfitsCount = ArraySize(inProfits); if (!IsValidSize(inProfitsCount)) { return result; } // // Copy in Profits to TMP ... XPosition tmp[]; Copy( inProfits, tmp // ); // bool isCoverPassed = false; while (!isCoverPassed || ArraySize(tmp) > 0) { // XPosition max; int idx = FindMaxProfitIndex(tmp); if (idx >= 0) { // if (tmp[idx].profit > 0) { AddRef( tmp[idx], coverage // ); // ArrayRemove( tmp, idx, 1 // ); } } // // Check Cover Passed ... XPosition tmpPositions[]; Copy( coverage, tmpPositions // ); AddRef( position, tmpPositions // ); // double profits = SpecifiedCalculatePositionsProfit(tmpPositions); double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( tmpPositions, mMinProfitPerTrade, mMinProfitPerVolumeFactor // ); isCoverPassed = profits >= requiredProfit; if (isCoverPassed) { break; } // if (!isCoverPassed && ArraySize(tmp) == 0) { break; } } // result = ArraySize(coverage); // return result; } // // Extract a Collection of Positions SL ... int ExtractSLs( XPosition &positions[], double &sls[] // ) { // int result = 0; // Clean(sls); // int positionsCount = ArraySize(positions); if (!IsValidSize(positionsCount)) { return result; } // for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // if (iPosition.sl > 0) { // Add( iPosition.sl, sls // ); } } // result = ArraySize(sls); // return result; } // // Extract a Colletion of Positions TP ... int ExtractTPs( XPosition &positions[], double &tps[] // ) { // int result = 0; // Clean(tps); // int positionsCount = ArraySize(positions); if (!IsValidSize(positionsCount)) { return result; } // for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // if (iPosition.tp > 0) { // Add( iPosition.tp, tps // ); } } // result = ArraySize(tps); // 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_NOT_ALLOWED: result = "not 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_PREV_PROFIT_ERROR: result = "Previous Position Profit not Passed for Accept Next"; break; // case X_SIGNAL_EXECUTION_FAILED_MAX_REACHED: result = "Max Allowed Positions Reached"; break; // case X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED: result = "Min Delay Between to Signal not Passed"; 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; } ENUM_ORDER_TYPE ToOrderType(ENUM_X_POSITION_TYPES value) { // ENUM_POSITION_TYPE mType = value == X_POSITION_TYPE_SHORT ? POSITION_TYPE_SELL : POSITION_TYPE_BUY; // bool isLong = IsLong(mType); // 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 // ); } // // Extract Support ... template int ExtractSupports( T &source[], T &dest[] // Result ... ) { // int result = 0; // Clean(dest); // int sourceCount = ArraySize(source); if (!IsValidSize(sourceCount)) { return result; } // for (int i = 0; i < sourceCount; i++) { // T iSource = source[i]; // ulong isSupport = ExtractSupportedTicket(iSource.comment) > 0; ulong iEQMSupport = ExtractEQMSupportedTicket(iSource.comment) > 0; if (isSupport || iEQMSupport) { // AddRef( iSource, dest // ); } } // result = ArraySize(dest); // return result; } // // 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 // ); } // bool IsSupport(string value) { // bool result = false; // bool isSupport = ExtractSupportedTicket(value) > 0; bool isEQMSupport = ExtractEQMSupportedTicket(value) > 0; // result = // isSupport // || // isEQMSupport // ; // return result; } // ulong ExtractParentTicket(string value) { // ulong result = 0; // if (!IsSupport(value)) { return result; } // result = ExtractSupportedTicket(value); if (result > 0) { return result; } // result = ExtractEQMSupportedTicket(value); // return result; } // // XRecovery ... // string GenerateRecoveryTag(ulong ticket) { // return Surround( XRecoveryToken, ticket // ); } // ulong ExtractRecoveredTicket(string value) { // return ParseLongSurrounded( value, XRecoveryToken // ); } // // Extract Recoveries ... template int ExtractRecoveries( T &source[], T &dest[] // Result ... ) { // int result = 0; // Clean(dest); // int sourceCount = ArraySize(source); if (!IsValidSize(sourceCount)) { return result; } // for (int i = 0; i < sourceCount; i++) { // T iSource = source[i]; // ulong isRecovery = ExtractRecoveredTicket(iSource.comment) > 0; if (isRecovery) { // AddRef( iSource, dest // ); } } // result = ArraySize(dest); // return result; } // // Extract Specified Position's Recoveries ... int ExtractRecoveries( ulong ticket, XPosition &source[], XPosition &dest[] // Result ... ) { // int result = 0; // Clean(dest); // int sourceCount = ArraySize(source); if (!IsValidSize(sourceCount)) { return result; } // for (int i = 0; i < sourceCount; i++) { // XPosition iSource = source[i]; // ulong parentTicket = ExtractRecoveredTicket(iSource.comment); bool isRecovery = parentTicket > 0; if (isRecovery && parentTicket == ticket) { // AddRef( iSource, dest // ); } } // result = ArraySize(dest); // return result; } // // 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; } // // 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; } } } // // Extract Positions based On Type ... void ExtractPositions( XPosition &positions[], XPosition &longs[], XPosition &shorts[] // ) { // int count = ArraySize(positions); if (!IsValidSize(count)) { return; } // Clean(longs); Clean(shorts); // for (int i = 0; i < count; i++) { // XPosition iPosition = positions[i]; // bool isLong = IsLong(iPosition.type); if (isLong) { AddRef( iPosition, longs // ); } else { AddRef( iPosition, shorts // ); } } } // int FindSymbolIndex( string mSymbol, XSymbolPositions &mItems[] // ) { // int result = -1; // if (!IsValid(mSymbol)) { return result; } // int count = ArraySize(mItems); if (!IsValidSize(count)) { return result; } // for (int i = 0; i < count; i++) { // XSymbolPositions iItem = mItems[i]; // if (iItem.symbol == mSymbol) { // result = i; break; } } // return result; } // int ExtractSymbolPositions( XPosition &positions[], XSymbolPositions &items[], // Holds Result double mMinProfitPerTrade, double mMinProfitPerVolumeFactor // ) { // int result = 0; // int positionsCount = ArraySize(positions); if (!IsValidSize(positionsCount)) { return result; } // Clean(items); // for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // if (!iPosition.IsValid()) { continue; } // int itemIDX = FindSymbolIndex( iPosition.symbol, items // ); if (!IsValidIndex(itemIDX)) { // // Add New One ... XSymbolPositions item; item.symbol = iPosition.symbol; // AddRef( item, items // ); itemIDX = FindSymbolIndex(iPosition.symbol, items); } // AddRef( iPosition, items[itemIDX].positions // ); } // result = ArraySize(items); if (IsValidSize(result)) { // for (int i = 0; i < result; i++) { // items[i].Update( mMinProfitPerTrade, mMinProfitPerVolumeFactor // ); } } // return result; } // // Apply a Collection of Targets // on Specified Signal ... void ApplyTargetsOnSignal( ENUM_X_DIRECTION sortingDir, // Target Sorting Direction ... XTarget &targets[], // Required Targets ... XSignal &signal // Destination Signal ... ) { // bool has = HasChild(targets) && HasDirection(sortingDir); if (!has) { return; } // // Sort Targets ... ApplySortOnTargets( sortingDir, targets // ); // Copy( targets, signal.targets // ); } //