/////////////////////////////////////////////////////// // // 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 }; // 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, }; // bool IsValid(ENUM_X_POSITION_TYPES value) { return value != X_POSITION_TYPE_NONE; } // bool HasSpecifiedType(ENUM_X_POSITION_TYPES value) { // return value == X_POSITION_TYPE_LONG || value == X_POSITION_TYPE_SHORT; } // 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 IsShort(ENUM_X_POSITION_TYPES value) { return value == X_POSITION_TYPE_SHORT; } // 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; } // // All Awailable Trade Restrictions ... enum ENUM_XTRADE_RESTRICTION_PERIOD { XTRADE_RESTRICATION_NONE, // None XTRADE_RESTRICATION_HOURLY, // Per Hour XTRADE_RESTRICATION_DAILY, // Per Day XTRADE_RESTRICATION_WEEKLY, // Per Week XTRADE_RESTRICATION_MONTHLY, // Per Month }; // string ToXString(ENUM_XTRADE_RESTRICTION_PERIOD value) { // string result = NULL; // result = EnumToString(value); // return result; } // ENUM_XTRADE_RESTRICTION_PERIOD ToXRestrictionPeriod(string value) { // ENUM_XTRADE_RESTRICTION_PERIOD result = XTRADE_RESTRICATION_NONE; // if (!IsSpecifiedValid(value)) { return result; } // // None ... if (value == ToXString(XTRADE_RESTRICATION_NONE)) { result = XTRADE_RESTRICATION_NONE; } // // Per Hour ... else if (value == ToXString(XTRADE_RESTRICATION_HOURLY)) { result = XTRADE_RESTRICATION_HOURLY; } // // Per Day ... else if (value == ToXString(XTRADE_RESTRICATION_DAILY)) { result = XTRADE_RESTRICATION_DAILY; } // // Per Week ... else if (value == ToXString(XTRADE_RESTRICATION_WEEKLY)) { result = XTRADE_RESTRICATION_WEEKLY; } // // Per Month ... else if (value == ToXString(XTRADE_RESTRICATION_MONTHLY)) { result = XTRADE_RESTRICATION_MONTHLY; } // return result; } // int GetXRestrictionsPeriodSeconds(ENUM_XTRADE_RESTRICTION_PERIOD value) { // int result = 0; // if (!HasRestrictions(value)) { return result; } // switch (value) { // // None ... case XTRADE_RESTRICATION_NONE: result = 0; break; // // Hour ... case XTRADE_RESTRICATION_HOURLY: result = PeriodSeconds(PERIOD_H1); break; // // Dayly ... case XTRADE_RESTRICATION_DAILY: result = PeriodSeconds(PERIOD_D1); break; // // Weekly ... case XTRADE_RESTRICATION_WEEKLY: result = PeriodSeconds(PERIOD_W1); break; // // Monthly ... case XTRADE_RESTRICATION_MONTHLY: result = PeriodSeconds(PERIOD_M1); break; } // return result; } /** * Check a Value Has Trade Restrictions or not ... * * @param value: ENUM_XTRADE_RESTRICTION_PERIOD * ّ * @return ( bool ) */ bool HasRestrictions(ENUM_XTRADE_RESTRICTION_PERIOD value) { return value != XTRADE_RESTRICATION_NONE; } // // All Awailable Trade Finalizations ... enum ENUM_XTRADE_FINALIZATION { XTRADE_FINAL_NONE, // None XTRADE_FINAL_TP, // TP XTRADE_FINAL_SL, // SL XTRADE_FINAL_CLOSE_IN_PROFIT, // Profit XTRADE_FINAL_CLOSE_IN_LOSE, // Lost }; // string ToXString(ENUM_XTRADE_FINALIZATION value) { return EnumToString(value); } // // Position Selecting Methods ... enum ENUM_XPOSITION_SELECT_TYPES { XPOSITION_SELECT_NONE = 0, // None XPOSITION_SELECT_ALL = 1, // All XPOSITION_SELECT_IN_PROFITS = 2, // In Profit Positions XPOSITION_SELECT_IN_DRAWDOWNS = 3, // In Drawdown Positions XPOSITION_SELECT_OLDEST = 4, // Oldest Position XPOSITION_SELECT_YOUNGEST = 5, // Youngest Position XPOSITION_SELECT_IN_PROFITS_OLDEST = 6, // In Profit Positions Oldest one XPOSITION_SELECT_IN_PROFITS_YOUNGEST = 7, // In Profit Positions Youngest one XPOSITION_SELECT_IN_PROFITS_MIN = 8, // Minimum Profitable Position XPOSITION_SELECT_IN_PROFITS_MAX = 9, // Maximum Profitable Position XPOSITION_SELECT_IN_DRAWDOWN_OLDEST = 10, // In Drawdown Positions Oldest one XPOSITION_SELECT_IN_DRAWDOWN_YOUNGEST = 11, // In Drawdown Positions Youngest one XPOSITION_SELECT_IN_DRAWDOWN_MIN = 12, // Minimum in Drawdown Position XPOSITION_SELECT_IN_DRAWDOWN_MAX = 13, // Maximum in Drawdown Position XPOSITION_SELECT_SAMES = 14, // Same Type Positions XPOSITION_SELECT_SAMES_OLDEST = 15, // Same Type Positions Oldest one XPOSITION_SELECT_SAMES_YOUNGEST = 16, // Same Type Positions Youngest one XPOSITION_SELECT_OPPOSITS = 17, // Opposit Type Positions XPOSITION_SELECT_OPPOSIT_OLDEST = 18, // Opposit Type Positions Oldest one XPOSITION_SELECT_OPPOSIT_YOUNGEST = 19, // Opposit Type Positions Youngest one XPOSITION_SELECT_SAME_IN_PROFITS = 20, // Same Type In Profit Positions XPOSITION_SELECT_SAME_IN_PROFITS_OLDEST = 21, // Same Type In Profit Positions Oldest one XPOSITION_SELECT_SAME_IN_PROFITS_YOUNGEST = 22, // Same Type In Profit Positions Youngest one XPOSITION_SELECT_SAME_IN_PROFITS_MIN = 23, // Minimum Profitable of Same Type Positions XPOSITION_SELECT_SAME_IN_PROFITS_MAX = 24, // Maximum Profitable of Same Type Positions XPOSITION_SELECT_OPPOSIT_IN_PROFITS = 25, // Opposit Type In Profit Positions XPOSITION_SELECT_OPPOSIT_IN_PROFITS_OLDEST = 26, // Opposit Type In Profit Positions Oldest one XPOSITION_SELECT_OPPOSIT_IN_PROFITS_YOUNGEST = 27, // Opposit Type In Profit Positions Youngest one XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MIN = 28, // Minimum Profitable of Opposit Type Positions XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MAX = 29, // Maximum Profitable of Opposit Type Positions XPOSITION_SELECT_SAME_IN_DRAWDOWNS = 30, // Same Type In Deawdown Positions XPOSITION_SELECT_SAME_IN_DRAWDOWN_OLDEST = 31, // Same Type In Deawdown Positions Oldest one XPOSITION_SELECT_SAME_IN_DRAWDOWN_YOUNGEST = 32, // Same Type In Deawdown Positions Youngest one XPOSITION_SELECT_SAME_IN_DRAWDOWN_MIN = 33, // Minimum In Drawdown of Same Type Positions XPOSITION_SELECT_SAME_IN_DRAWDOWN_MAX = 34, // Maximum In Drawdown of Same Type Positions XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWNS = 35, // Opposit Type In Deawdown Positions XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_OLDEST = 36, // Opposit Type In Deawdown Positions Oldest one XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_YOUNGEST = 37, // Opposit Type In Deawdown Positions Youngest one XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MIN = 38, // Minimum In Drawdown of Opposit Type Positions XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MAX = 39, // Maximum In Drawdown of Opposit Type Positions }; /** * Validate Position Select Type ... * * @param value: ENUM_XPOSITION_SELECT_TYPES * * @return ( bool ) */ bool IsXValid(ENUM_XPOSITION_SELECT_TYPES value) { return value != XPOSITION_SELECT_NONE; } // string ToXString(ENUM_XPOSITION_SELECT_TYPES value) { return EnumToString(value); } // // 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; // SpecifiedClean(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 && IsSpecifiedValid(_symbol) && IsSpecifiedValid(_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 && IsSpecifiedValid(time) && IsSpecifiedValid(symbol) && IsSpecifiedValid(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 + (IsSpecifiedValid(prefix) ? prefix + sep : "") + symbol + sep + ToXString(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 = // IsSpecifiedValid(symbol) && NotEmpty(ticket) // ; // return result; } // // Retrieve Entry Price ... double GetEntry() { // double result = 0; // if (!IsValid()) { return result; } // result = GetXEntry( symbol, type // ); // return result; } // // Retrieve Exit ... double GetExit() { // double result = 0; // if (!IsValid()) { return result; } // result = GetXExit( symbol, type // ); // return result; } // // Get Spread by Point ... double GetSpread() { // double result = 0; // if (!IsValid()) { return result; } // result = PriceToPoint(GetXSpread(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; // SpecifiedClean(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 GetXAge(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( XPosition &values[] // Collection to Find ) { // return FindXIndex( 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; // SpecifiedClean(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; // SpecifiedClean(targets); appliedTargetIDX = -1; ignoreEAVolume = false; isTargetApplied = false; } // // Validate ... bool IsValid() { // bool result = false; // result = // IsSpecifiedValid(period) && IsSpecifiedValid(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 (IsSpecifiedValid(provider)) { // // Generate Provider Tag ... result += GenerateProviderTag(provider); } // if (IsSpecifiedValid(period)) { // // Generate Period Tag ... result += GeneratePeriodTag(period); } // return result; } // int GetAge() { // return GetXAge( 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 + "_" + ToXString(period) + "_" + ToXString(type) + "_" + ToXString(sl) + "_" + ToXString(tp) + "_" + ToXString(entry); // return result; } // // Retrieve String Representation of Signal ... string ToString() { // string result = NULL; // result = // ToXString("Symbol", symbol) + ToXString("Period", period) + ToXString("Provider", provider) + ToXString("Type", type) + ToXString("Mode", mode) + ToXString("Volume", volume) + ToXString("Entry", entry) + ToXString("TP", tp) + ToXString("SL", sl) + ToXString("Time", time) + ToXString("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 = ToXString(type) + " Signal" + (!IsSpecifiedValid(action) ? "" : " " + action) + " by: " + provider + " on (" + symbol + ")" + " in: " + ToXString(period); // return result; } // string GetFileName() { // string result = NULL; // if (!IsValid()) { return result; } // result = // symbol + "\\" + ToXString(type) + "\\" + ToXString(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 = // IsSpecifiedValid(symbol) && NotEmpty(ticket) && NotEmpty(positionId) // ; // return result; } // // Calculate Age ... int GetAge( ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period ) { return GetXAge(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( XOrder &values[] // Collection to Find ) { // return FindXIndex( 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 = // IsSpecifiedValid(symbol) && NotEmpty(ticket) && NotEmpty(positionId) // ; // return result; } // // Calculate Age ... int GetAge( ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period ) { return GetXAge(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( XDeal &values[] // Collection to Find ) { // return FindXIndex( 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; } }; // // an Structure for Describe aTrading Session ... struct XTradeSession { // // Properties ... string start; // Session Start Time (hh:mm) string end; // Session End Time (hh:mm) string name; // Session Name // // Constructor ... XTradeSession() { Clean(); } // // Tools ... // // Cleanup ... void Clean() { // end = NULL; name = NULL; start = NULL; // ZeroMemory(this); } // // Validate ... bool IsValid() { // bool result = false; // result = IsSpecifiedValid(start) && IsSpecifiedValid(end); if (!result) { return result; } // return result; } // // Check Session is Active or Not ... bool IsActive(datetime time = NULL) { // bool result = false; // time = NormalizeTime(time); // result = IsValid(); if (!result) { return result; } // result = IsTimeInRange( time, start, end // ); // return result; } }; // // an Structure for Describe an Specified Symbols // Trading Sessions ... struct XSymbolTradeConfig { // // Propeties ... // int longs; // All Long Trades int shorts; // All Short Trades int trades; // All Trades int losses; // All Loosing Trades int profits; // All Winning Trades string symbol; // Trading Symbol int managedSLs; // Managed SL(s) int managedTPs; // Managed TP(s) int managedTrades; // Managed Trades int maxAllowedTPs; // Max Allowed TP(s) in Restrictions Period int maxAllowedSLs; // Max Allowed SL(s) in Restrictions Period int maxAllowedTrades; // Max Allowed Trades in Restrictions Period datetime managedStart; // Managed Start Time double managedBalance; // Managed Start Balance double managedProfits; // Managed Profit(s) ENUM_TIMEFRAMES period; // Trading Period int maxAllowedPositions; // Max Allowed Same Time Trades double maxAllowedSpread; // Max Allowed Spread For Trade bool isForceCloseAtTime; // a Flag for Determines Force Closed or not XTradeSession sessions[]; // Trading Sessions string closeAllOpenTradesAt; // Close All Open Trades per Day At Specified Time int restrictionsPeriodMultiplier; // Specified Restrictions Period Multiplier ENUM_XTRADE_RESTRICTION_PERIOD restrictionsPeriod; // Trade Restrictions Period // // Constructor ... XSymbolTradeConfig() { Clean(); } // // Tools ... // // Cleanup ... void Clean() { // symbol = NULL; period = NULL; SpecifiedClean(sessions); // longs = 0; shorts = 0; trades = 0; losses = 0; profits = 0; // managedStart = NULL; // managedSLs = 0; managedTPs = 0; managedTrades = 0; // managedBalance = 0; managedProfits = 0; // maxAllowedTPs = 0; maxAllowedSLs = 0; maxAllowedTrades = 0; maxAllowedSpread = 25; maxAllowedPositions = 5; closeAllOpenTradesAt = ""; isForceCloseAtTime = false; restrictionsPeriod = XTRADE_RESTRICATION_NONE; // ZeroMemory(this); } /** * Initial ... * * @param _symbol: Trading Symbol * @param _period: Trading Period * @param _sessionsDescriptor: Sessions Description * @param _maxAllowedSpread: Max Allowed Spread for Open Trade * @param _maxAllowedPositions: Max Allowed Same Time Position * @param _restrictionsDescriptor: Restrictions Descriptor * * @return ( bool ) */ bool Init( string _symbol = NULL, ENUM_TIMEFRAMES _period = NULL, string _sessionsDescriptor = NULL, double _maxAllowedSpread = 25, int _maxAllowedPositions = 5, string _restrictionsDescriptor = NULL // ) { // bool result = false; // // Normalize Symbol ... _symbol = NormalizeSymbol(_symbol); _period = NormalizePeriod(_period); // symbol = _symbol; period = _period; maxAllowedSpread = _maxAllowedSpread; maxAllowedPositions = _maxAllowedPositions; // // Parse Sessions ... ParseSessions(_sessionsDescriptor); // // Parse Restrictions ... ParseRestrictions(_restrictionsDescriptor); // // Check Validation ... result = IsValid(); // return result; } // // Check Same ... bool IsSame(XSymbolTradeConfig &dest) { // bool result = false; // // Validate ... result = IsValid() && dest.IsValid() && symbol == dest.symbol && period == dest.period; // return result; } // // Validate ... bool IsValid() { // bool result = false; // result = IsSpecifiedValid(symbol) && IsSpecifiedValid(period); // return result; } // // Check Allow Trade in Active Sessions ... bool CanTrade(datetime time = NULL) { // bool result = false; // // Normalize Args ... time = NormalizeTime(time); // // Validating ... result = IsValid(); if (!result) { return result; } // // if there is not any defined sessions for Symbol ... // it's allow Trading in all times ... result = !HasChild(sessions); if (result) { return result; } // // Detect an Active Session ... int count = ArraySize(sessions); for (int i = 0; i < count; i++) { // result = sessions[i].IsActive(time); if (result) { break; } } // return result; } // // Checking Restrictions ... bool IsRestricted(datetime time = NULL) { // bool result = false; // // Normalize Time ... time = NormalizeTime(time); // // Check Has Restrictions ... bool has = HasRestrictions(restrictionsPeriod); result = !has; if (result) { return result; } // // Check Restrictions Time ... has = IsSpecifiedValid(managedStart) && time <= managedStart; result = !has; if (result) { return result; } // // Validate Restrictions Timing ... // Check Restrictions ... // bool isTPAllowed = maxAllowedTPs == 0 ? true : managedTPs < maxAllowedTPs; bool isSLAllowed = maxAllowedSLs == 0 ? true : managedSLs < maxAllowedSLs; bool isTradeAllowed = maxAllowedTrades == 0 ? true : managedTrades < maxAllowedTrades; // result = isTPAllowed && isSLAllowed && isTradeAllowed; if (result) { return result; } // // Check Restrictions Reset ... HandleRestrictions(); // return result; } // // Parse Sessions ... void ParseSessions(string descriptor) { // // Validate ... if (!IsSpecifiedValid(descriptor)) { return; } // bool has = false; string _sessions[]; int sessionsCount = 0; // // Extract Per Symbol Sessions ... sessionsCount = SplitContent( _sessions, descriptor, "," // ); // // Try to Extract Start and End Times Series ... has = IsValidSize(sessionsCount); if (!has) { return; } // // Iterate Sessions ... for (int i = 0; i < sessionsCount; i++) { // // Ignore unused Cases and Extracts only Content ... string iSessionDescriptorStr = ExtractString(_sessions[i]); has = IsSpecifiedValid(iSessionDescriptorStr); if (has) { // // Extract Session Descriptor Data ... string parts[]; int partsCount = SplitContent( parts, iSessionDescriptorStr, "_" // ); has = IsValidSize(partsCount) && partsCount == 3; if (has) { // string iName = parts[0]; string iStart = parts[1]; string iEnd = parts[2]; has = IsSpecifiedValid(iName) && IsSpecifiedValid(iStart) && IsSpecifiedValid(iEnd); if (has) { // // Set Active Session Per Symbols ... XTradeSession session; // session.end = iEnd; session.name = iName; session.start = iStart; // AddRef( session, sessions // ); // session.Clean(); } } // SpecifiedClean(parts); } } // SpecifiedClean(_sessions); } // // Parse Restrictions ... void ParseRestrictions(string descriptor) { // // Validate ... if (!IsSpecifiedValid(descriptor)) { return; } // // Extract Content ... descriptor = ExtractString(descriptor); if (!IsSpecifiedValid(descriptor)) { return; } // int count = 0; bool has = false; string iRestrictionsParts[]; // // Extract Parts ... count = SplitContent( iRestrictionsParts, descriptor, "," // ); has = IsValidSize(count); if (!has) { // // Default Restrictions ... ApplyDefaultRestrictions(); return; } // // Try To Extract Required Parts ... bool hasRestrictionsPeriod = count >= 1; bool hasRestrictionsPeriodMultiplier = count >= 2; bool hasMaxAllowedTPs = count >= 3; bool hasMaxAllowedSLs = count >= 4; bool hasMaxAllowedTrades = count >= 5; bool hasCloseAllOpenTradesAt = count >= 6; // // Restrictions Period ... restrictionsPeriod = hasRestrictionsPeriod ? ToXRestrictionPeriod(Trim(iRestrictionsParts[0])) : XTRADE_RESTRICATION_NONE; // // Restrictions Period Multiplier ... restrictionsPeriodMultiplier = hasRestrictionsPeriodMultiplier ? (int)(Trim(iRestrictionsParts[1])) : 1; // // Max Allowed TPs ... maxAllowedTPs = hasMaxAllowedTPs ? (int)(Trim(iRestrictionsParts[2])) : 0; // // Max Allowed SLs ... maxAllowedSLs = hasMaxAllowedSLs ? (int)(Trim(iRestrictionsParts[3])) : 0; // // Max Allowed Trades ... maxAllowedTrades = hasMaxAllowedTrades ? (int)(Trim(iRestrictionsParts[4])) : 0; // // Close All Open Trades At ... closeAllOpenTradesAt = hasCloseAllOpenTradesAt ? Trim(iRestrictionsParts[5]) : NULL; } // // Apply Default Restrictions ... void ApplyDefaultRestrictions() { // maxAllowedTPs = 0; maxAllowedSLs = 0; maxAllowedTrades = 0; closeAllOpenTradesAt = NULL; restrictionsPeriod = XTRADE_RESTRICATION_NONE; } // // Handle Restrictions ... void HandleRestrictions(datetime time = NULL) { // // Normalize Time ... time = NormalizeTime(time); // // Check Restrictions Requirements ... bool has = HasRestrictions(restrictionsPeriod) && restrictionsPeriodMultiplier >= 1; if (!has) { return; } // // Check Restrictions Start ... has = IsSpecifiedValid(managedStart); if (!has) { managedStart = time; } // // Calculating Expiration Date based on Config ... int expiredDelay = restrictionsPeriodMultiplier * GetXRestrictionsPeriodSeconds(restrictionsPeriod); datetime expiredDate = (datetime)(TimeToSeconds(managedStart) + expiredDelay); // // Check Expiration ... has = time >= expiredDate; if (!has) { return; } // ResetRestrictions(); } // // Reset Restrictions ... void ResetRestrictions() { // managedSLs = 0; managedTPs = 0; managedTrades = 0; managedBalance = 0; managedProfits = 0; managedStart = TimeCurrent(); } // }; // // an Structure to Describe a Trade ... struct XTradeInfo { // // Props ... double swap; double profit; XSignal signal; ulong positionID; double commission; string conditions; double bullishScore; double bearishScore; ENUM_XTRADE_FINALIZATION finalize; // datetime signaledAt; datetime executedAt; datetime finalizedAt; // // Constructor ... XTradeInfo() { Clean(); } // // Tools ... /** * Cleanup Model ... */ void Clean() { // swap = 0; profit = 0; signal.Clean(); commission = 0; positionID = 0; conditions = NULL; bullishScore = 0; bearishScore = 0; finalize = XTRADE_FINAL_NONE; // signaledAt = NULL; executedAt = NULL; finalizedAt = NULL; // ZeroMemory(this); } /** * Check Has Signal ... * * @return ( bool ) */ bool HasSignal() { // bool result = false; // result = signal.IsValid(); // return result; } /** * Check Signal Executed or Not ... * * @return ( bool ) */ bool IsExecuted() { // bool result = false; // result = positionID > 0; // return result; } /** * Check a Trade is Finalized or not ... * * @return ( bool ) */ bool IsFinalized() { // bool result = false; // result = HasSignal() && IsExecuted() && finalize != XTRADE_FINAL_NONE; // return result; } /** * Generate Summary Info ... * * @return ( string ) */ string Summary() { // string result = NULL; // result = // ToXString("Swap", swap) + ToXString("Profit", profit) + ToXString("Commission", commission) + ToXString("Finalize", ToXString(finalize)) + ToXString("PositionID", positionID) + ToXString("----------------") + "\n" + ToXString("Signaled At", ToFormatString(signaledAt)) + ToXString("Executed At", ToFormatString(executedAt)) + ToXString("Finalized At", ToFormatString(finalizedAt)) // ; // return result; } /** * Get Data Collection File Name ... * * @return ( string ) */ string GetFileName() { // string result = NULL; // bool hasSignal = HasSignal(); bool isExecuted = IsExecuted(); bool isFinalized = IsFinalized(); if (!hasSignal && !isExecuted && !isFinalized) { return result; } // result = // signal.symbol + "\\" + ToString(signal.type) + "\\" + (profit >= 0 ? "Profit" : "Loss") + "\\" + ToString(positionID) + "_" + ToString(signal.period) + "_" + ToFormatString(signaledAt) // ; // return result; } /** * Converts Model to String Representation ... * * @param onlySignals: Boolean, Specified Represent Only Signal or not ... * * @return ( string ) */ string ToString( bool includeSummary = true, bool includeSignal = true, bool includeConditions = true // ) { // string result = NULL; // // Generating Model Summary ... string summary = Summary(); // // Generating Signal Summary ... string signalSummary = signal.ToString(); // if (includeSummary) { // result += ToXString("----------------") + "\n" + ToXString("Summary: ") + "\n" + ToXString("----------------") + "\n" + summary + "\n"; } // if (includeSignal) { // result += ToXString("----------------") + "\n" + ToXString("Signal: ") + "\n" + ToXString("----------------") + "\n" + signalSummary + "\n"; } // if (includeConditions) { // result += ToXString("----------------") + "\n" + ToXString("Conditions: ") + "\n" + ToXString("----------------") + "\n" + conditions + "\n"; } // return result; } string GetConditionsString() { // string result = NULL; // string conditionsStr = conditions; string condParts[]; int condPartsCount = SplitContent( condParts, conditionsStr, "\n" // ); if (IsValidSize(condPartsCount)) { // conditionsStr = NULL; while (HasChild(condParts)) { // string iStr = condParts[0]; ArrayRemove( condParts, 0, 1 // ); // bool isLast = !HasChild(condParts); // bool isCond = Contains( "is", iStr, false // ); if (isCond) { // string iParts[]; int iPartsCount = SplitContent( iParts, iStr, ":" // ); if (iPartsCount == 2) { // string iVal = iParts[1]; StringTrimLeft(iVal); StringTrimRight(iVal); bool isPassed = ToBoolean(iVal); conditionsStr += (isPassed ? "" : "!") + "conditions." + iParts[0] + (!isLast ? " &&" : "") + "\n"; } } } SpecifiedClean(condParts); } else { conditionsStr = NULL; } // result = "(" + "\n" + "\\" + "\\" + " " + ToXString("Type", ToXString(signal.type)) + "\\" + "\\" + " " + ToXString("Profit", profit) + "\\" + "\\" + " " + ToXString("Finalize", ToXString(finalize)) + "\\" + "\\" + " " + ToXString("PositionID", positionID) + "\\" + "\\" + " " + ToXString("----------------") + "\n" + "\\" + "\\" + " " + ToXString("Signaled At", ToFormatString(signaledAt)) + "\\" + "\\" + " " + ToXString("Executed At", ToFormatString(executedAt)) + "\\" + "\\" + " " + ToXString("Finalized At", ToFormatString(finalizedAt)) + "\\" + "\\" + " " + ToXString("----------------") + "\n" + "\\" + "\\" + " " + ToXString("Scores:") + "\n" + "\\" + "\\" + " " + ToXString("Bullish", bullishScore) + "\\" + "\\" + " " + ToXString("Bearish", bearishScore) + "\\" + "\\" + " " + ToXString("----------------") + "\n" + conditionsStr + (IsValid(conditionsStr) ? "" : "") + ") && "; // return result; } }; // // TypeDefs ... // typedef void (*TOnSignal)(XSignal &signal); // typedef bool (*TCanAnalyse)( string _symbol, ENUM_TIMEFRAMES _period, datetime _time // ); // 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; } int GetXAge( XSignal &signal, // Selected Signal ... ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... ) { return GetAge(signal, period); } // // 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; } int GetXAge( XPosition &position, // Selected Position ... ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... ) { return GetAge(position, period); } // // 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; } int GetXAge( XOrder &order, // Selected Order ... ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... ) { return GetAge(order, period); } // // 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; } int GetXAge( XDeal &deal, // Selected Deal ... ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... ) { return GetAge(deal, period); } // // 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; } int GetXOldest( XDeal &item, // Hold Result ... XDeal &items[] // Source Array ... ) { return GetOldest(item, items); } // // 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; } int GetXYoungest( XDeal &item, // Hold Result ... XDeal &items[] // Source Array ... ) { return GetYoungest(item, items); } // // 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; } int GetXOldest( XOrder &item, // Hold Result ... XOrder &items[] // Source Array ... ) { return GetOldest(item, items); } // // 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; } int GetXYoungest( XOrder &item, // Hold Result ... XOrder &items[] // Source Array ... ) { return GetYoungest(item, items); } // // 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; } int GetXOldest( XPosition &item, // Hold Result ... XPosition &items[] // Source Array ... ) { return GetOldest(item, items); } // // 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 GetXYoungest( XPosition &item, // Hold Result ... XPosition &items[] // Source Array ... ) { return GetYoungest(item, items); } // 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 FindMaxDrawdownIndex( 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 FindMinDrawdownIndex( 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 = ToXString(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 // ); } } } // // 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 // ); } /** * Select Specified Position's Related Position(s) * for Protecting ... * * @param selecteds: XPosition instance reference Collection, for Holding Selected Positions ... * @param positions: XPosition instance reference Collection, All available source Positions ... * @param forType: ENUM_X_POSITION_TYPES member, Spcified Position Type to Select for it ... * @param selectType: ENUM_XPOSITION_SELECT_TYPES member, Specified Positions Selecting Senario ... * * @return ( bool ) */ bool SelectPosition( XPosition &selecteds[], XPosition &positions[], ENUM_X_POSITION_TYPES forType, ENUM_XPOSITION_SELECT_TYPES selectType // ) { // bool result = false; // // Normalize Args ... Clean(selecteds); // // Validate Args ... result = IsValid(forType) && HasChild(positions) && IsXValid(selectType); if (!result) { return result; } // // Extract Separate Type of Positions ... // int idx = -1; bool has = false; XPosition iPosition; // bool isLong = IsLong(forType); bool isShort = IsShort(forType); int count = ArraySize(positions); // XPosition samePositions[]; XPosition oppositPositions[]; XPosition inProfitPositions[]; XPosition inDrawdownPositions[]; XPosition sameInProfitPositions[]; XPosition sameInDrawdownPositions[]; XPosition oppositInProfitPositions[]; XPosition oppositInDrawdownPositions[]; // for (int i = 0; i < count; i++) { // // Select Indexed Position ... iPosition = positions[i]; // bool isIPosLong = IsLong(iPosition.type); bool isIPosShort = IsShort(iPosition.type); // // Select if Same Type ... bool isSame = (isLong && isIPosLong) || (isShort && isIPosShort); if (isSame) { // AddRef( iPosition, samePositions // ); } // // Select if Opposit Type ... bool isOpposit = (isLong && isIPosShort) || (isShort && isIPosLong); if (isOpposit) { // AddRef( iPosition, oppositPositions // ); } // iPosition.Clean(); } // // Filling Other Requirement Collections ... // ExtractInProfitPositions( positions, inProfitPositions // ); // ExtractInProfitPositions( samePositions, sameInProfitPositions // ); // ExtractInProfitPositions( oppositPositions, oppositInProfitPositions // ); // ExtractInDrawdownPositions( positions, inDrawdownPositions // ); // ExtractInDrawdownPositions( samePositions, sameInDrawdownPositions // ); // ExtractInDrawdownPositions( oppositPositions, oppositInDrawdownPositions // ); // // Implement Selection Senario ... switch (selectType) { // case XPOSITION_SELECT_ALL: // Copy( positions, selecteds // ); break; // case XPOSITION_SELECT_IN_PROFITS: // Copy( inProfitPositions, selecteds // ); break; // case XPOSITION_SELECT_IN_DRAWDOWNS: // Copy( inDrawdownPositions, selecteds // ); break; // case XPOSITION_SELECT_OLDEST: // GetOldest( iPosition, positions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_YOUNGEST: // GetYoungest( iPosition, positions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_IN_PROFITS_OLDEST: // GetOldest( iPosition, inProfitPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_IN_PROFITS_YOUNGEST: // GetYoungest( iPosition, inProfitPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_IN_PROFITS_MIN: // idx = FindMinProfitIndex(inProfitPositions); if (IsValidIndex(idx)) { // iPosition = inProfitPositions[idx]; // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_IN_PROFITS_MAX: // idx = FindMaxProfitIndex(inProfitPositions); if (IsValidIndex(idx)) { // iPosition = inProfitPositions[idx]; // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_IN_DRAWDOWN_OLDEST: // GetOldest( iPosition, inDrawdownPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_IN_DRAWDOWN_YOUNGEST: // GetYoungest( iPosition, inDrawdownPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_IN_DRAWDOWN_MIN: // idx = FindMinDrawdownIndex(inDrawdownPositions); if (IsValidIndex(idx)) { // iPosition = inDrawdownPositions[idx]; // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_IN_DRAWDOWN_MAX: // idx = FindMaxDrawdownIndex(inDrawdownPositions); if (IsValidIndex(idx)) { // iPosition = inDrawdownPositions[idx]; // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_SAMES: // Copy( samePositions, selecteds // ); break; // case XPOSITION_SELECT_SAMES_OLDEST: // GetOldest( iPosition, samePositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_SAMES_YOUNGEST: // GetYoungest( iPosition, samePositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_OPPOSITS: // Copy( oppositPositions, selecteds // ); break; // case XPOSITION_SELECT_OPPOSIT_OLDEST: // GetOldest( iPosition, oppositPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_OPPOSIT_YOUNGEST: // GetYoungest( iPosition, oppositPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_SAME_IN_PROFITS: // Copy( sameInProfitPositions, selecteds // ); break; // case XPOSITION_SELECT_SAME_IN_PROFITS_OLDEST: // GetOldest( iPosition, sameInProfitPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_SAME_IN_PROFITS_YOUNGEST: // GetYoungest( iPosition, sameInProfitPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_SAME_IN_PROFITS_MIN: // idx = FindMinProfitIndex(sameInProfitPositions); if (IsValidIndex(idx)) { // iPosition = sameInProfitPositions[idx]; // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_SAME_IN_PROFITS_MAX: // idx = FindMaxProfitIndex(sameInProfitPositions); if (IsValidIndex(idx)) { // iPosition = sameInProfitPositions[idx]; // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_OPPOSIT_IN_PROFITS: // Copy( oppositInProfitPositions, selecteds // ); break; // case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_OLDEST: // GetOldest( iPosition, oppositInProfitPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_YOUNGEST: // GetYoungest( iPosition, oppositInProfitPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MIN: // idx = FindMinProfitIndex(oppositInProfitPositions); if (IsValidIndex(idx)) { // iPosition = oppositInProfitPositions[idx]; // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MAX: // idx = FindMaxProfitIndex(oppositInProfitPositions); if (IsValidIndex(idx)) { // iPosition = oppositInProfitPositions[idx]; // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_SAME_IN_DRAWDOWNS: // Copy( sameInDrawdownPositions, selecteds // ); break; // case XPOSITION_SELECT_SAME_IN_DRAWDOWN_OLDEST: // GetOldest( iPosition, sameInDrawdownPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_SAME_IN_DRAWDOWN_YOUNGEST: // GetYoungest( iPosition, sameInDrawdownPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_SAME_IN_DRAWDOWN_MIN: // idx = FindMinDrawdownIndex(sameInDrawdownPositions); if (IsValidIndex(idx)) { // iPosition = sameInDrawdownPositions[idx]; // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_SAME_IN_DRAWDOWN_MAX: // idx = FindMaxDrawdownIndex(sameInDrawdownPositions); if (IsValidIndex(idx)) { // iPosition = sameInDrawdownPositions[idx]; // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWNS: // Copy( oppositInDrawdownPositions, selecteds // ); break; // case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_OLDEST: // GetOldest( iPosition, oppositInDrawdownPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_YOUNGEST: // GetYoungest( iPosition, oppositInDrawdownPositions // ); if (iPosition.IsValid()) { // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MIN: // idx = FindMinDrawdownIndex(oppositInDrawdownPositions); if (IsValidIndex(idx)) { // iPosition = oppositInDrawdownPositions[idx]; // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MAX: // idx = FindMaxDrawdownIndex(oppositInDrawdownPositions); if (IsValidIndex(idx)) { // iPosition = oppositInDrawdownPositions[idx]; // AddRef( iPosition, selecteds // ); } iPosition.Clean(); break; // } // // Validate Result ... result = HasChild(selecteds); // // Cleanup Resources ... // if (!result) { Clean(selecteds); } // Clean(samePositions); Clean(oppositPositions); Clean(inProfitPositions); Clean(inDrawdownPositions); Clean(sameInProfitPositions); Clean(sameInDrawdownPositions); Clean(oppositInProfitPositions); Clean(oppositInDrawdownPositions); // return result; } //