/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Seriallize Library // --------------------------------------- // Name: XSeriallizer // Description: provides Seriallizing EA abilities ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // #include "../Libraries/x-saherelm.models.lib.mq5" #include "../Libraries/x-saherelm.common.lib.mq5" #include "../Classes/x-saherelm.xtrade.class.mq5" #include "../Classes/x-saherelm.x121.provider.class.mq5" // string XProviderToken = "PRV"; string XSupportToken = "SP"; string XSLTrailToken = "SLT"; string XPeriodToken = "PR"; // string XConfigToken = "XPV"; string XItemSeparator = "|"; string XItemContentSeparator = ","; // string XFirstGenToken = "0"; // // PERIOD ... // // Detect a Comment has period or not ... bool HasPeriod(string comment) { // bool result = false; // if (StringLen(comment) == 0) { return result; } // int tokenPos = StringFind( comment, XPeriodToken); result = tokenPos >= 0; // return result; } // // Extract Period String ... string ExtractPeriodString(string comment) { // string result = ""; // bool hasPeriod = HasPeriod(comment); if (!hasPeriod) { return result; } // result = ExtractString( comment, XPeriodToken + "(", ")"); // return result; } // // Extract Time Frame From Comment ... ENUM_TIMEFRAMES ExtractPeriod(string comment) { // ENUM_TIMEFRAMES result = NULL; // if (StringLen(comment) <= 0) { return result; } // string periodStr = ExtractPeriodString(comment); if (StringLen(periodStr) <= 0) { return result; } // result = ToPeriod(periodStr); // return result; } // // PROVIDER ... // // Extract a Provider name if exists from a Comment ... string ExtractProvider(string comment) { // string result = ""; if (StringLen(comment) <= 0) { return result; } // result = ExtractString( comment, XProviderToken + "(", ")"); // return result; } // // Generate Provider String for Using in Positions Comment ... // NOTE: if there is more than One Provider, it takes first // provider as main and the others used to increase volume ... string GenerateProvidersString(XSignal &signal) { // string result = ""; // int providersCount = ArraySize(signal.providers); if (providersCount <= 0) { return result; } // result = XProviderToken + "(" + signal.providers[0] + ")"; // return result; } // // SLTRAIL ... // string GenerateSLTrailComment(int level) { // string result = ""; // if (level <= 0) { return result; } // result = XSLTrailToken + "(" + ToString(level) + ")"; // return result; } // int ExtractSLTrailLevel(string comment) { // int result = 0; // if (StringLen(comment) == 0) { return result; } // string levelStr = ExtractString( comment, XSLTrailToken + "(", ")"); if (StringLen(levelStr) == 0) { return result; } // result = (int)levelStr; // return result; } // string PrepareSLTrailComment( const string comment // Original Position Comment ... ) { // string result = ""; // if (StringLen(comment) == 0) { return result; } // 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 = GenerateSLTrailComment(lastTrailLevel); StringReplace( result, lastLevelStr, ""); } // // Generate level Comment ... string levelStr = GenerateSLTrailComment(level); result += levelStr; // return result; } // // SUPPORT ... // // Generate Specific Position's Support Comment // index is number of Supports ... string GenerateSupportSignalComment( ulong ticket, // Position/Order Ticket int index // Support Index ... ) { // string result = ""; // result = XSupportToken + "(" + (string)ticket + "," + ToString(index) + ")"; // return result; } // // Extract Support Parameters String from specified Comment ... string ExtractSupportParam(string comment) { // string result = ""; if (StringLen(comment) <= 0) { return result; } // result = ExtractString( comment, XSupportToken + "(", ")"); // return result; } // // Extract Support Info as String array for Specific Comment ... bool ExtractSupportParams( string comment, // Specified Comment ... string ¶ms[] // Hold Result ... ) { // bool result = false; // string supParam = ExtractSupportParam(comment); if (StringLen(supParam) == 0) { return result; } // SplitContent( params, supParam); int paramsCount = ArraySize(params); // result = paramsCount == 2; // return result; } // // Extract Support Parent Ticket ... ulong ExtractParentTicket(string comment) { // ulong result = 0; // string params[]; bool isSupport = ExtractSupportParams( comment, params); if (!isSupport) { return result; } // result = (ulong)params[0]; // return result; } // // Extract Support Index ... int ExtractSupportIndex(string comment) { // int result = -1; // string params[]; bool isSupport = ExtractSupportParams( comment, params); if (!isSupport) { return result; } // result = (int)params[1]; // return result; } // // XCONFIG X121Provider Struct ... // // Extract Signallers from User Input ... int ExtractSignallers( string &result[], // Hold Result const string source // Source Content ) { // int mResult = 0; // Clean(result); // SplitContent( result, source); // mResult = ArraySize(result); // return mResult; } // // Validate Specified Provider Descriptor Model ... bool IsValid(X121SignalProvider &item) { // bool result = false; // result = // StringLen(item.symbol) > 0 && item.period != NULL && item.riskAmount > 0 // ; // return result; } // // Compare Source item with Dest item to check their Same or not ... bool IsSame( X121SignalProvider &source, // Source Item X121SignalProvider &dest // Dest Item ) { // bool result = false; // bool isValidDest = IsValid(dest); bool isValidSource = IsValid(source); if (!isValidDest || !isValidSource) { return result; } // result = // source.symbol == dest.symbol && source.period == dest.period && source.riskAmount == dest.riskAmount && source.useRiskAmountAsStaticVolume == dest.useRiskAmountAsStaticVolume // ; // return result; } // // Check Specified Provider Exists in a Collection or not ... bool Contains( X121SignalProvider &item, // Specified Item X121SignalProvider &items[] // Given Collection ) { // bool result = false; // int itemsCount = ArraySize(items); if (itemsCount <= 0) { return result; } // for (int i = 0; i < itemsCount; i++) { // X121SignalProvider iProvider = items[i]; // result = IsSame(item, iProvider); if (result) { // break; } } // return result; } // // Extract Provider Descriptor Parts from given Source Input ... int ExtractProviderDescriptorItems( string &result[], // Hold Result const string source // Source Descriptor ) { // int mResult = 0; // Clean(result); // SplitContent( result, source, XItemSeparator); // mResult = ArraySize(result); // return mResult; } // // Extract Provider Descriptor Items Content from given Source Input ... int ExtractProviderDescriptorItemsContent( string &result[], // Hold Result const string source // Source Descriptor ) { // int mResult = 0; // Clean(result); // SplitContent( result, source, XItemContentSeparator); // mResult = ArraySize(result); // return mResult; } // // Validate and add provider to providers if not exists ... bool AddProviderDescriptor( X121SignalProvider &item, X121SignalProvider &items[]) { // bool result = false; // // Validate and add ... result = IsValid(item); if (!result) { return result; } // bool isExists = Contains( item, items); if (isExists) { return result; } // result = true; // Add( item, items); // return result; } // // Extract Provider Descriptors from given Source Input ... int ExtractProviderConfigurations( X121SignalProvider &result[], // Hold Result const string source, // Source String const string defaultSignallers, // Default Available Signallers for Each Providers const double defaultRiskAmount, // Default Risk Amount per Trade for Each Provider const bool useRiskAmountAsStaticVolume = true // Use Provided Risk Amount as Static Volume ) { // int mResult = 0; // Clean(result); // // if there is no Pairs ... // Check as One Model ... string descriptors[]; mResult = ExtractStrings( descriptors, source, XConfigToken + "(", ")"); // // Retrieve Signallers ... string defaultSignallersArr[]; ExtractSignallers( defaultSignallersArr, defaultSignallers); // if (mResult == 0) { // // Here we Check given source String Length ... // if it is bigger than zero we assuem it is one line descriptor ... if (StringLen(source) > 0) { // // One Model ... Add( source, descriptors); } } // // Each Provider Must Contains at least two things : // - Asset; int descriptorsCount = ArraySize(descriptors); if (descriptorsCount > 0) { // // Loop through descriptors to parse models ... for (int i = 0; i < descriptorsCount; i++) { // string iDescriptor = descriptors[i]; // X121SignalProvider iProviderDescriptor; iProviderDescriptor.symbol = ""; iProviderDescriptor.period = NULL; iProviderDescriptor.riskAmount = 0; Clean(iProviderDescriptor.providers); // string iParts[]; int iPartsCount = ExtractProviderDescriptorItems( iParts, iDescriptor); // // Check Parts Count ... // Now we have to Decide How to Config Signal Providers using Parts ... // // asset => default; // period => default; // risk amount => default; // signallers => default; // use as static volume => default; if (iPartsCount == 0) { // // Here we Instance as Current Config Descriptor ... iProviderDescriptor.symbol = _Symbol; iProviderDescriptor.period = _Period; iProviderDescriptor.riskAmount = defaultRiskAmount; iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume; // // Add Default Signallers ... Copy( defaultSignallersArr, iProviderDescriptor.providers); // AddProviderDescriptor( iProviderDescriptor, result); // continue; } // // asset => provided; // period => default; // risk amount => default; // signallers => default; // use as static volume => default; if (iPartsCount == 1) { // iProviderDescriptor.period = _Period; iProviderDescriptor.riskAmount = defaultRiskAmount; iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume; // // Add Default Signallers ... Copy( defaultSignallersArr, iProviderDescriptor.providers); // // Extract Provided Assets ... string symbols[]; int symbolsCount = ExtractProviderDescriptorItemsContent( symbols, iParts[0]); for (int j = 0; j < symbolsCount; j++) { // string jSymbol = symbols[j]; // iProviderDescriptor.symbol = jSymbol; // AddProviderDescriptor( iProviderDescriptor, result); } // continue; } // // asset => provided; // period => provided; // risk amount => default; // signallers => default; // use as static volume => default; if (iPartsCount == 2) { // iProviderDescriptor.riskAmount = defaultRiskAmount; iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume; // // Add Default Signallers ... Copy( defaultSignallersArr, iProviderDescriptor.providers); // // Extract Provided Assets ... string symbols[]; int symbolsCount = ExtractProviderDescriptorItemsContent( symbols, iParts[0]); for (int j = 0; j < symbolsCount; j++) { // string jSymbol = symbols[j]; // iProviderDescriptor.symbol = jSymbol; // // Extract Periods ... string periods[]; int periodsCount = ExtractProviderDescriptorItemsContent( periods, iParts[1]); for (int k = 0; k < periodsCount; k++) { // string kPeriodStr = periods[k]; ENUM_TIMEFRAMES kPeriod = ToPeriod(kPeriodStr); // iProviderDescriptor.period = kPeriod; // AddProviderDescriptor( iProviderDescriptor, result); } } // continue; } // // asset => provided; // period => provided; // risk amount => provided; // signallers => default; // use as static volume => default; if (iPartsCount == 3) { // iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume; // // Add Default Signallers ... Copy( defaultSignallersArr, iProviderDescriptor.providers); // // Extract Provided Assets ... string symbols[]; int symbolsCount = ExtractProviderDescriptorItemsContent( symbols, iParts[0]); // string riskAmounts[]; int riskAmountsCount = ExtractProviderDescriptorItemsContent( riskAmounts, iParts[2]); // for (int j = 0; j < symbolsCount; j++) { // string jSymbol = symbols[j]; // iProviderDescriptor.symbol = jSymbol; // // Extract Periods ... string periods[]; int periodsCount = ExtractProviderDescriptorItemsContent( periods, iParts[1]); for (int k = 0; k < periodsCount; k++) { // string kPeriodStr = periods[k]; ENUM_TIMEFRAMES kPeriod = ToPeriod(kPeriodStr); // iProviderDescriptor.period = kPeriod; // string selectedRiskAmount = riskAmountsCount == 0 ? ToString(defaultRiskAmount) : riskAmountsCount == periodsCount ? riskAmounts[k] : riskAmounts[0]; double riskAmount = (double)selectedRiskAmount; iProviderDescriptor.riskAmount = riskAmount; // AddProviderDescriptor( iProviderDescriptor, result); } } // continue; } // // asset => provided; // period => provided; // risk amount => provided; // signallers => provided; // use as static volume => default; if (iPartsCount == 4) { // iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume; // // Extract Signallers ... string signallers[]; int signallersCount = ExtractSignallers( signallers, iParts[3]); if (signallersCount <= 0) { // Copy( defaultSignallersArr, signallers); } // // Set Extracted Signallers in Provider Descriptor ... Copy( signallers, iProviderDescriptor.providers); // // // Extract Provided Assets ... string symbols[]; int symbolsCount = ExtractProviderDescriptorItemsContent( symbols, iParts[0]); // string riskAmounts[]; int riskAmountsCount = ExtractProviderDescriptorItemsContent( riskAmounts, iParts[2]); // for (int j = 0; j < symbolsCount; j++) { // string jSymbol = symbols[j]; // iProviderDescriptor.symbol = jSymbol; // // Extract Periods ... string periods[]; int periodsCount = ExtractProviderDescriptorItemsContent( periods, iParts[1]); for (int k = 0; k < periodsCount; k++) { // string kPeriodStr = periods[k]; ENUM_TIMEFRAMES kPeriod = ToPeriod(kPeriodStr); // iProviderDescriptor.period = kPeriod; // string selectedRiskAmount = riskAmountsCount == 0 ? ToString(defaultRiskAmount) : riskAmountsCount == periodsCount ? riskAmounts[k] : riskAmounts[0]; double riskAmount = (double)selectedRiskAmount; iProviderDescriptor.riskAmount = riskAmount; // AddProviderDescriptor( iProviderDescriptor, result); } } // continue; } // // asset => provided; // period => provided; // risk amount => provided; // signallers => provided; // use as static volume => provided; if (iPartsCount == 5) { // // Extract Signallers ... string signallers[]; int signallersCount = ExtractSignallers( signallers, iParts[3]); if (signallersCount <= 0) { // Copy( defaultSignallersArr, signallers); } // // Set Extracted Signallers in Provider Descriptor ... Copy( signallers, iProviderDescriptor.providers); // // // Extract Provided Assets ... string symbols[]; int symbolsCount = ExtractProviderDescriptorItemsContent( symbols, iParts[0]); // string riskAmounts[]; int riskAmountsCount = ExtractProviderDescriptorItemsContent( riskAmounts, iParts[2]); // string useRiskAmountAsStaticVolumes[]; int useRiskAmountAsStaticVolumesCount = ExtractProviderDescriptorItemsContent( useRiskAmountAsStaticVolumes, iParts[4]); // for (int j = 0; j < symbolsCount; j++) { // string jSymbol = symbols[j]; // iProviderDescriptor.symbol = jSymbol; // // Extract Periods ... string periods[]; int periodsCount = ExtractProviderDescriptorItemsContent( periods, iParts[1]); for (int k = 0; k < periodsCount; k++) { // string kPeriodStr = periods[k]; ENUM_TIMEFRAMES kPeriod = ToPeriod(kPeriodStr); // iProviderDescriptor.period = kPeriod; // string selectedRiskAmount = riskAmountsCount == 0 ? ToString(defaultRiskAmount) : riskAmountsCount == periodsCount ? riskAmounts[k] : riskAmounts[0]; double riskAmount = (double)selectedRiskAmount; iProviderDescriptor.riskAmount = riskAmount; // string selectedUseRiskAmountAsStaticVolume = useRiskAmountAsStaticVolumesCount == 0 ? ToString(useRiskAmountAsStaticVolume) : useRiskAmountAsStaticVolumesCount == periodsCount ? useRiskAmountAsStaticVolumes[k] : useRiskAmountAsStaticVolumes[0]; bool useRiskAmountAsStaticVolume = ToBoolean(selectedUseRiskAmountAsStaticVolume); iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume; // AddProviderDescriptor( iProviderDescriptor, result); } } // continue; } } } else { // // Use All Defaults to Create One Instance ... X121SignalProvider iProviderDescriptor; iProviderDescriptor.symbol = ""; iProviderDescriptor.period = NULL; iProviderDescriptor.riskAmount = 0; Clean(iProviderDescriptor.providers); // iProviderDescriptor.symbol = _Symbol; iProviderDescriptor.period = _Period; iProviderDescriptor.riskAmount = defaultRiskAmount; iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume; // // Add Default Signallers ... Copy( defaultSignallersArr, iProviderDescriptor.providers); // AddProviderDescriptor( iProviderDescriptor, result); } // mResult = ArraySize(result); // return mResult; } // // START XEQM Support ... // // string XEQMSupportToken = "XEQM"; // // Generate String Tag for EQM Support Signals ... string GenerateXEQMSupportComment() { // string result = XEQMSupportToken; // return result; } // // Check a Comment belongs to a EQM Support or not ... bool IsEQMSupport(string comment) { // bool result = false; // if (StringLen(comment) <= 0) { return result; } // int tokenPosition = StringFind( comment, XEQMSupportToken); result = tokenPosition >= 0; // return result; } // // Select EQM Support Orders ... int GetEQMSupportOrders( XOrder &supports[], // Hold Result ... XOrder &orders[], // List of All Orders ... ENUM_TIMEFRAMES period = NULL // Specified Period ... ) { // int result = 0; // // Cleanup Array ... Clean(supports); // // Count Orders ... int ordersCount = ArraySize(orders); if (ordersCount <= 0) { return result; } // // Loop through Orders ... for (int i = 0; i < ordersCount; i++) { // // Select Indexed Order ... XOrder iOrder = orders[i]; // // Check Order is Support or not ... bool isSupport = IsEQMSupport(iOrder.comment); if (!isSupport) { continue; } // // Check Order is not Triggered ... if (iOrder.state != ORDER_STATE_PLACED) { continue; } // // Check Period ... if (period != NULL && iOrder.period != period) { continue; } // // we now sure this order is EQM Support ... Add( iOrder, supports); } // // Count Result ... result = ArraySize(supports); // return result; } // // Select EQM Support Positions ... int GetEQMSupportPositions( XPosition &supports[], // Hold Result ... XPosition &positions[], // List of All Positions ... ENUM_TIMEFRAMES period = NULL // Specified Period ... ) { // int result = 0; // // Cleanup Array ... Clean(supports); // // Count Positions ... int positionsCount = ArraySize(positions); if (positionsCount <= 0) { return result; } // // Loop through Positions ... for (int i = 0; i < positionsCount; i++) { // // Select Indexed Position ... XPosition iPosition = positions[i]; // // Check Position is Support or not ... bool isSupport = IsEQMSupport(iPosition.comment); if (!isSupport) { continue; } // // Check Period ... if (period != NULL && iPosition.period != period) { continue; } // // we now sure this order is EQM Support ... Add( iPosition, supports); } // // Count Result ... result = ArraySize(supports); // return result; } // // END XEQM Support ... // // // START FirstGen ... // // string GenerateFirstGenIdentifier(const string signaller) { // string result = ""; // if (StringLen(signaller) <= 0) { return result; } // return signaller + XFirstGenToken; // return result; } // bool IsFirstGenOf( const string signaller, // Specified Signaller const string comment // Comment ) { // bool result = false; // string id = GenerateFirstGenIdentifier(signaller); // int idPos = StringFind( comment, id ); result = idPos >= 0; // return result; } // // END FirstGen ... //