//////////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 XTM Signal Provider Library // -------------------------------------------------------- // Name: XTMSignalProvider // Description: XTM 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 XTMProviderName "XTM" // // START Inputs ... // #include "x-saherelm.xtm.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 *xTMTrader; XCAccountInfo xTMAccountInfo; // #include "x-saherelm.xtm.provider.indicators.lib.mq5" // double xTMDeposit = 0; double xTMBalance = 0; double xTMFreeMargin = 0; double xTMFreeMarginForOpenTrades = 0; double xTMBalanceForOpenTrades = 0; // // END Global Definitions: Variables, Properties and etc ... // // // START Provided Functions ... // // // Initial Library if required ... bool XTMInitSignalProviderLibrary() { // bool result = false; // // Validate Inputs ... result = XTMValidateInputs(); if (!result) { return result; } // // Init Indicators ... result = XTMInitIndicators(); if (!result) { return result; } // // Calculate Account Deposit ... xTMDeposit = xTMAccountInfo.GetInitialBalance(); // // Calculate Min Balance for Trades ... if (xTMBalanceFactorForOpenTrades > 0) { xTMBalanceForOpenTrades = xTMBalanceFactorForOpenTrades * xTMDeposit; } // // Claculate Min Free Marging for Trades ... if (xTMFreeMarginFactorForOpenTrades > 0) { xTMFreeMarginForOpenTrades = xTMFreeMarginFactorForOpenTrades * xTMDeposit; } // // Make XCTrader instance ... xTMTrader = new XCTrade( _Symbol, xTMSlippage, xTMMagicNumber); // result = true; // // Logging State ... XTMIssueInitializationSucceedAlert(); // return result; } // // DeInitial Library if required ... void XTMDeinitSignalProviderLibrary( const int reason) { // // Release Handlers ... XTMReleaseIndicators(); // // Logging State ... XTMIssueDeinitializationSucceedAlert(); } // // this is a Globally Function which do all of // checkings and positions handling ... void XTMSignalProviderHandleTick() { // // Update account Balance ... xTMBalance = xTMAccountInfo.GetBalance(); xTMFreeMargin = xTMAccountInfo.GetFreeMargin(); // // Reading Indicator Buffers ... XTMHandleReadingBuffers(); if (xTMCalculatedBars < xTMMaxLengthOfInputs) { return; } // // Handle Open Trades ... XTMHandleOpenTrades(); // // Handle Close Trades ... XTMHandleCloseTrades(); } // // Handle Open Trades ... void XTMHandleOpenTrades() { // // Check Can Trade ... bool canTrade = xTMAllowLongTrades || xTMAllowShortTrades; if (!canTrade) { return; } // // First Check Signal Exists or NOt ... bool xTMHasLongSignal = XTMCanOpenLongTrade(); bool xTMHasShortSignal = XTMCanOpenShortTrade(); if (!xTMHasLongSignal && !xTMHasShortSignal) { return; } // // Count Max Open Trades ... if (xTMMaxAllowedTrades > 0) { // int count = xTMTrader.Count(); bool canOpenTrade = count < xTMMaxAllowedTrades; if (!canOpenTrade) { // XTMIssueMaxAllowedTradesReachedAlert(); // return; } } // // Check Free Margin ... if (xTMFreeMargin <= xTMFreeMarginForOpenTrades) { // XTMIssueMaxAllowedFreeMarginReachedAlert(); // return; } // // Check Account Balance ... if (xTMBalance <= xTMBalanceForOpenTrades) { // XTMIssueMinAllowedBalanceReachedAlert(); // return; } // // Primary Long Trade ... if ( xTMHasLongSignal && xTMAllowLongTrades) { // bool isLongSignalExecuted = XTMOpenLongPosition(); if (isLongSignalExecuted) { } } // // Primary Short Trade ... if ( xTMHasShortSignal && xTMAllowShortTrades) { // bool isShortSignalExecuted = XTMOpenShortPosition(); if (isShortSignalExecuted) { } } } // // Handle Close Trades ... void XTMHandleCloseTrades() { // // Handle Long/Buy Close ... if (xTMTrader.CountLongs() > 0 && XTMCanCloseLongTrade()) { // XSignal closed[]; xTMTrader.CloseLongPositions(closed); bool hasClosed = ArraySize(closed) > 0; if (hasClosed) { XTMIssueForceCloseTradesAlert(X_SIGNAL_LONG); } } // // Handle Short/Sell Close ... if (xTMTrader.CountShorts() > 0 && XTMCanCloseShortTrade()) { // XSignal closed[]; xTMTrader.CloseShortPositions(closed); bool hasClosed = ArraySize(closed) > 0; if (hasClosed) { XTMIssueForceCloseTradesAlert(X_SIGNAL_SHORT); } } // // Handle Close In Profit Teades ... if (xTMMaxInProfitTradeAge > 0) { // XSignal closed[]; XSignal longTimeTrades[]; xTMTrader.GetLongTimeTrades( xTMMaxInProfitTradeAge, _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 = xTMTrader.Close(trade.ticket); if (isClosed) { Add( trade, closed); } } } // if (ArraySize(closed) > 0) { XTMIssueLongInProfitTradeClosed(); } } // // Handle Close In DrawDown Trades ... if (xTMMaxInDrawDownTradeAge > 0) { // XSignal closed[]; XSignal longTimeTrades[]; xTMTrader.GetLongTimeTrades( xTMMaxInDrawDownTradeAge, _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 ... XTMOpenSuppurtTrade(trade); // // // bool isClosed = xTMTrader.Close(trade.ticket); // if (isClosed) // { // // // Add( // trade, // closed); // } } } // if (ArraySize(closed) > 0) { XTMIssueLongInDrawdownTradeClosed(); } } } // // Open Long Position ... bool XTMOpenLongPosition() { // bool result = false; // // Generate Position Signal and Validate it ... XSignal position = XTMGeneratePositionSignal(X_SIGNAL_LONG); if (!IsValid( position, xTMMagicNumber)) { return result; } // // Try to Open Position ... result = xTMTrader.ExecuteSignal(position); if (result) { XTMIssueSignalExecutionAlert(position); } // return result; } // // Open Short Position ... bool XTMOpenShortPosition() { // bool result = false; // // Generate Position Signal and Validate it ... XSignal position = XTMGeneratePositionSignal(X_SIGNAL_SHORT); if (!IsValid( position, xTMMagicNumber)) { return result; } // // Try to Open Position ... result = xTMTrader.ExecuteSignal(position); if (result) { XTMIssueSignalExecutionAlert(position); } // return result; } // // Open a Support Signal ... bool XTMOpenSuppurtTrade( XSignal &signal // Parent Signal ) { // bool result = false; // if (!xTMEnableSupportTrades) { return result; } // // Validate Signal ... if (!IsValid(signal, xTMMagicNumber)) { return result; } // // Market Conditions ... bool hasLongSignal = XTMCanOpenLongTrade(); bool hasShortSignal = XTMCanOpenShortTrade(); // 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 (xTMVolumeMultiplier > 2) { volumeMultiplier = xTMVolumeMultiplier; } // // 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 = XTMCalculateTPSL(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 = xTMMagicNumber; // // Validate Generated Support ... if (!IsValid(support, xTMMagicNumber)) { return result; } // result = xTMTrader.ExecuteSignal(support); if (result) { XTMIssueSignalExecutionAlert(support); } // return result; } // // Generate Specific type of Signals for Trading ... XSignal XTMGeneratePositionSignal( 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 = XTMCalculateVolume(); // datetime time = iTime( _Symbol, _Period, 0); // string typeString = GetSignalType(type); string comment = XTMProviderName + "_" + typeString + "_" + (string)volume + "_" + (string)time; // XTPSL tpSL = XTMCalculateTPSL(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 = xTMMagicNumber; // return result; } // // END Provided Functions ... // // // START Private Functions ... // // // Calculating Volume for Tradings ... double XTMCalculateVolume() { // // Assign default Value ... double result = xTMStaticVolume; // // we can count open trades and in draw down trades // then do check volume based on it for gridding ... int openTrades = xTMTrader.Count(); if (openTrades == 0) { openTrades = 1; } // // Calculate Normalized Multiplier ... double multiplier = xTMVolumeMultiplier <= 0 ? 1 : xTMVolumeMultiplier; // result = multiplier * openTrades * xTMStaticVolume; // // Normalize Volume ... result = NormalizeVolume(result); // return result; } // // Calculate Signal TP and SL ... XTPSL XTMCalculateTPSL( 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(xTMMinRewardPerTradeInPips) + 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 XTMIssueInitializationSucceedAlert() { // string message = "Initializion of (" + XTMProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ..."; XTMIssueAlert(message); } void XTMIssueDeinitializationSucceedAlert() { // string message = "De Initializion of (" + XTMProviderName + " Provider" + ") Succeeded ..."; XTMIssueAlert(message); } void XTMIssueForceCloseTradesAlert(ENUM_X_SIGNAL_TYPE type) { // string typeStr = GetSignalType(type); if (StringLen(typeStr) == 0) { return; } // string message = "Force Close " + typeStr + " Trades ..."; XTMIssueAlert(message); } void XTMIssueMaxAllowedTradesReachedAlert() { // string message = "reached Max Allowed Same Time Trades ..."; XTMIssueAlert(message); } void XTMIssueMaxAllowedFreeMarginReachedAlert() { // string message = "reached FreeMarigin For Open Trades ..."; XTMIssueAlert(message); } void XTMIssueMinAllowedBalanceReachedAlert() { // string message = "doesn't have Minimum Balance For Open Trades ..."; XTMIssueAlert(message); } void XTMIssueSignalExecutionAlert( XSignal &signal // Executed Signal ) { // XTMIssueAlert(signal); } void XTMIssueLongInProfitTradeClosed() { // string message = "Closed Long Time in Profit Trades ..."; XTMIssueAlert(message); } void XTMIssueLongInDrawdownTradeClosed() { // string message = "Closed Long Time in Profit Trades ..."; XTMIssueAlert(message); } void XTMIssueAlert(string message) { // if (xTMEnableAlerts) { SendAlert(message); } else { LogMessage(message); } } void XTMIssueAlert(XSignal &signal) { // if (xTMEnableAlerts) { SendAlert(signal); } else { LogSignal(signal); } } // // END Private Functions ... //