//////////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 XTD Signal Provider Library // -------------------------------------------------------- // Name: XTDSignalProvider // Description: XTD based signal provider ... // // // 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 #define XTDProviderName "XTD" // // START Inputs ... // #include "x-saherelm.xtd.provider.inputs.lib.mq5"; // // END Inputs ... // // // Include Common Library ... #include "x-saherelm.common.lib.mq5" // // Include Logger Library ... #include "x-saherelm.log.lib.mq5" // // Include Alert Library ... #include "x-saherelm.alert.lib.mq5" // // Include Draw Library ... #include "x-saherelm.draw.lib.mq5" // // Include Class Libraries ... #include "x-saherelm.class.lib.mq5" // // START Global Definitions: Variables, Properties and etc ... // // XCTrade *xTDTrader; XCAccountInfo xTDAccountInfo; // #include "x-saherelm.xtd.provider.indicators.lib.mq5" // double xTDDeposit = 0; double xTDBalance = 0; double xTDFreeMargin = 0; double xTDFreeMarginForOpenTrades = 0; double xTDBalanceForOpenTrades = 0; // // END Global Definitions: Variables, Properties and etc ... // // // START Provided Functions ... // // // Initial Library if required ... bool XTDInitSignalProviderLibrary() { // bool result = false; // // Validate Inputs ... result = XTDValidateInputs(); if (!result) { return result; } // // Init Indicators ... result = XTDInitIndicators(); if (!result) { return result; } // // Calculate Account Deposit ... xTDDeposit = xTDAccountInfo.GetInitialBalance(); // // Calculate Min Balance for Trades ... if (xTDBalanceFactorForOpenTrades > 0) { xTDBalanceForOpenTrades = xTDBalanceFactorForOpenTrades * xTDDeposit; } // // Claculate Min Free Marging for Trades ... if (xTDFreeMarginFactorForOpenTrades > 0) { xTDFreeMarginForOpenTrades = xTDFreeMarginFactorForOpenTrades * xTDDeposit; } // // Make XCTrader instance ... xTDTrader = new XCTrade( _Symbol, xTDSlippage, xTDMagicNumber); // result = true; // // Logging State ... XTDIssueInitializationSucceedAlert(); // return result; } // // DeInitial Library if required ... void XTDDeinitSignalProviderLibrary( const int reason) { // // Release Handlers ... XTDReleaseIndicators(); // // Logging State ... XTDIssueDeinitializationSucceedAlert(); } // // this is a Globally Function which do all of // checkings and positions handling ... void XTDSignalProviderHandleTick() { // // Update account Balance ... xTDBalance = xTDAccountInfo.GetBalance(); xTDFreeMargin = xTDAccountInfo.GetFreeMargin(); // // Reading Indicator Buffers ... XTDHandleReadingBuffers(); if (xTDCalculatedBars < xTDMaxLengthOfInputs) { return; } // // Handle Open Trades ... XTDHandleOpenTrades(); // // Handle Close Trades ... XTDHandleCloseTrades(); } // // Handle Open Trades ... void XTDHandleOpenTrades() { // // Check Can Trade ... bool canTrade = xTDAllowLongTrades || xTDAllowShortTrades; if (!canTrade) { return; } // // First Check Signal Exists or NOt ... bool xTDHasLongSignal = XTDCanOpenLongTrade(); bool xTDHasShortSignal = XTDCanOpenShortTrade(); if (!xTDHasLongSignal && !xTDHasShortSignal) { return; } // // Count Max Open Trades ... if (xTDMaxAllowedTrades > 0) { // int count = xTDTrader.Count(); bool canOpenTrade = count < xTDMaxAllowedTrades; if (!canOpenTrade) { // XTDIssueMaxAllowedTradesReachedAlert(); // return; } } // // Check Free Margin ... if (xTDFreeMargin <= xTDFreeMarginForOpenTrades) { // XTDIssueMaxAllowedFreeMarginReachedAlert(); // return; } // // Check Account Balance ... if (xTDBalance <= xTDBalanceForOpenTrades) { // XTDIssueMinAllowedBalanceReachedAlert(); // return; } // // Primary Long Trade ... if ( xTDHasLongSignal && xTDAllowLongTrades) { // bool isLongSignalExecuted = XTDOpenLongPosition(); if (isLongSignalExecuted) { } } // // Primary Short Trade ... if ( xTDHasShortSignal && xTDAllowShortTrades) { // bool isShortSignalExecuted = XTDOpenShortPosition(); if (isShortSignalExecuted) { } } } // // Handle Close Trades ... void XTDHandleCloseTrades() { // // Handle Long/Buy Close ... if (xTDTrader.CountLongs() > 0 && XTDCanCloseLongTrade()) { // XSignal closed[]; xTDTrader.CloseLongPositions(closed); bool hasClosed = ArraySize(closed) > 0; if (hasClosed) { XTDIssueForceCloseTradesAlert(X_SIGNAL_LONG); } } // // Handle Short/Sell Close ... if (xTDTrader.CountShorts() > 0 && XTDCanCloseShortTrade()) { // XSignal closed[]; xTDTrader.CloseShortPositions(closed); bool hasClosed = ArraySize(closed) > 0; if (hasClosed) { XTDIssueForceCloseTradesAlert(X_SIGNAL_SHORT); } } // // Handle Close In Profit Teades ... if (xTDMaxInProfitTradeAge > 0) { // XSignal closed[]; XSignal longTimeTrades[]; xTDTrader.GetLongTimeTrades( xTDMaxInProfitTradeAge, _Period, longTimeTrades); int count = ArraySize(longTimeTrades); if (count > 0) { // // Loop ... for (int i = 0; i < count; i++) { // XSignal trade = longTimeTrades[i]; if (trade.profit < 0) { continue; } // bool isClosed = xTDTrader.Close(trade.ticket); if (isClosed) { Add( trade, closed); } } } // if (ArraySize(closed) > 0) { XTDIssueLongInProfitTradeClosed(); } } // // Handle Close In DrawDown Trades ... if (xTDMaxInDrawDownTradeAge > 0) { // XSignal closed[]; XSignal longTimeTrades[]; xTDTrader.GetLongTimeTrades( xTDMaxInDrawDownTradeAge, _Period, longTimeTrades); int count = ArraySize(longTimeTrades); if (count > 0) { // // Loop ... for (int i = 0; i < count; i++) { // XSignal trade = longTimeTrades[i]; if (trade.profit > 0) { continue; } // // Open Grid Trades ... XTDOpenSuppurtTrade(trade); // // // bool isClosed = xTDTrader.Close(trade.ticket); // if (isClosed) // { // // // Add( // trade, // closed); // } } } // if (ArraySize(closed) > 0) { XTDIssueLongInDrawdownTradeClosed(); } } } // // Open Long Position ... bool XTDOpenLongPosition() { // bool result = false; // // Generate Position Signal and Validate it ... XSignal position = XTDGeneratePositionSignal(X_SIGNAL_LONG); if (!IsValid( position, xTDMagicNumber)) { return result; } // // Try to Open Position ... result = xTDTrader.ExecuteSignal(position); if (result) { XTDIssueSignalExecutionAlert(position); } // return result; } // // Open Short Position ... bool XTDOpenShortPosition() { // bool result = false; // // Generate Position Signal and Validate it ... XSignal position = XTDGeneratePositionSignal(X_SIGNAL_SHORT); if (!IsValid( position, xTDMagicNumber)) { return result; } // // Try to Open Position ... result = xTDTrader.ExecuteSignal(position); if (result) { XTDIssueSignalExecutionAlert(position); } // return result; } // // Open a Support Signal ... bool XTDOpenSuppurtTrade( XSignal &signal // Parent Signal ) { // bool result = false; // if (!xTDEnableSupportTrades) { return result; } // // Validate Signal ... if (!IsValid(signal, xTDMagicNumber)) { return result; } // // Market Conditions ... bool hasLongSignal = XTDCanOpenLongTrade(); bool hasShortSignal = XTDCanOpenShortTrade(); // ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN; // // Detect Support Signal Direction ... XSignal support = {}; switch (signal.type) { // case X_SIGNAL_LONG: // // First Check Long Support ... // Then Look for Short Support ... if (hasLongSignal) { type = X_SIGNAL_LONG; } else if (hasShortSignal) { type = X_SIGNAL_SHORT; } else { type = signal.type; } break; // case X_SIGNAL_SHORT: // First Check Short Support ... // Then Look for Long Support ... if (hasShortSignal) { type = X_SIGNAL_SHORT; } else if (hasLongSignal) { type = X_SIGNAL_LONG; } else { type = signal.type; } break; } // if (type == X_SIGNAL_UNKNOWN) { return result; } bool isLong = type == X_SIGNAL_LONG; // // Find Common Used ... double entry = GetEntry(type); double volumeMultiplier = 2; if (xTDVolumeMultiplier > 2) { volumeMultiplier = xTDVolumeMultiplier; } // // Check Signal is Support ot nor ... int titlePosition = StringFind( signal.comment, "Support"); bool isSupport = titlePosition >= 0; double priceDistance = MathAbs(signal.entry - entry); // if (isSupport || priceDistance < PipsToPrice(5)) { return result; } // datetime time = iTime( _Symbol, _Period, 0); double volume = NormalizeVolume(isSupport ? signal.volume : signal.volume * volumeMultiplier); string comment = "Support_" + GetSignalType(type) + "_For_" + (string)signal.ticket + "_" + (string)volume + "_" + (string)time; // XTPSL tpSL = XTDCalculateTPSL(type); if (!IsValid(tpSL)) { return result; } // // Calculate reward of signal ... double reward = MathAbs(signal.entry - signal.tp) / 2; double tp = tpSL.sl; // isLong ? entry + reward : entry - reward; double sl = tpSL.sl; // // Filling Support Signal ... support.tp = tp; support.sl = sl; support.type = type; support.time = time; support.entry = entry; support.volume = volume; support.symbol = _Symbol; support.comment = comment; support.magicNumber = xTDMagicNumber; // // Validate Generated Support ... if (!IsValid(support, xTDMagicNumber)) { return result; } // result = xTDTrader.ExecuteSignal(support); if (result) { XTDIssueSignalExecutionAlert(support); } // return result; } // // Generate Specific type of Signals for Trading ... XSignal XTDGeneratePositionSignal( ENUM_X_SIGNAL_TYPE type // direction of position ) { // XSignal result = {}; // if (type != X_SIGNAL_LONG && type != X_SIGNAL_SHORT) { return result; } // double ask = GetAsk(); double bid = GetBid(); double entry = GetEntry(type); // double volume = XTDCalculateVolume(); // datetime time = iTime( _Symbol, _Period, 0); // string typeString = GetSignalType(type); string comment = XTDProviderName + "_" + typeString + "_" + (string)volume + "_" + (string)time; // XTPSL tpSL = XTDCalculateTPSL(type); if (IsValid(tpSL)) { // // Apply TP ... if (tpSL.tp > 0) { result.tp = tpSL.tp; } // // Apply SL ... if (tpSL.sl > 0) { result.sl = tpSL.sl; } } // result.type = type; result.time = time; result.entry = entry; result.volume = volume; result.symbol = _Symbol; result.comment = comment; result.magicNumber = xTDMagicNumber; // return result; } // // END Provided Functions ... // // // START Private Functions ... // // // Calculating Volume for Tradings ... double XTDCalculateVolume() { // // Assign default Value ... double result = xTDStaticVolume; // // we can count open trades and in draw down trades // then do check volume based on it for gridding ... int openTrades = xTDTrader.Count(); if (openTrades == 0) { openTrades = 1; } // // Calculate Normalized Multiplier ... double multiplier = xTDVolumeMultiplier <= 0 ? 1 : xTDVolumeMultiplier; // result = multiplier * openTrades * xTDStaticVolume; // // Normalize Volume ... result = NormalizeVolume(result); // return result; } // // Calculate Signal TP and SL ... XTPSL XTDCalculateTPSL( ENUM_X_SIGNAL_TYPE type // Position Type ) { // XTPSL result = {}; // // Validate Args ... if ( type != X_SIGNAL_LONG && type != X_SIGNAL_SHORT) { return result; } // bool isLong = type == X_SIGNAL_LONG; // double ask = GetAsk(); double bid = GetBid(); double spread = GetSpread(); double entry = isLong ? ask : bid; // // TODO: Find Risk .. double risk = 0; // // Calculate Reward ... double reward = PipsToPrice(xTDMinRewardPerTradeInPips) + spread; // // Calculate TP and SL ... double tp = isLong ? entry + reward : entry - reward; double sl = 0; // result.type = type; result.tp = tp; result.sl = sl; result.entry = entry; // // TODO: Calculate R2R ... result.r2r = 0; // return result; } void XTDIssueInitializationSucceedAlert() { // string message = "Initializion of (" + XTDProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ..."; XTDIssueAlert(message); } void XTDIssueDeinitializationSucceedAlert() { // string message = "De Initializion of (" + XTDProviderName + " Provider" + ") Succeeded ..."; XTDIssueAlert(message); } void XTDIssueForceCloseTradesAlert(ENUM_X_SIGNAL_TYPE type) { // string typeStr = GetSignalType(type); if (StringLen(typeStr) == 0) { return; } // string message = "Force Close " + typeStr + " Trades ..."; XTDIssueAlert(message); } void XTDIssueMaxAllowedTradesReachedAlert() { // string message = "reached Max Allowed Same Time Trades ..."; XTDIssueAlert(message); } void XTDIssueMaxAllowedFreeMarginReachedAlert() { // string message = "reached FreeMarigin For Open Trades ..."; XTDIssueAlert(message); } void XTDIssueMinAllowedBalanceReachedAlert() { // string message = "doesn't have Minimum Balance For Open Trades ..."; XTDIssueAlert(message); } void XTDIssueSignalExecutionAlert( XSignal &signal // Executed Signal ) { // XTDIssueAlert(signal); } void XTDIssueLongInProfitTradeClosed() { // string message = "Closed Long Time in Profit Trades ..."; XTDIssueAlert(message); } void XTDIssueLongInDrawdownTradeClosed() { // string message = "Closed Long Time in Profit Trades ..."; XTDIssueAlert(message); } void XTDIssueAlert(string message) { // if (xTDEnableAlerts) { SendAlert(message); } else { LogMessage(message); } } void XTDIssueAlert(XSignal &signal) { // if (xTDEnableAlerts) { SendAlert(signal); } else { LogSignal(signal); } } // // END Private Functions ... //