//////////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 XCHMA Signal Provider Library // -------------------------------------------------------- // Name: XCHMASignalProvider // Description: XCHMA 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 XCHMAProviderName "XCHMA" // // START Inputs ... // #include "x-saherelm.xchma.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 *xCHMATrader; XCAccountInfo xCHMAAccountInfo; // #include "x-saherelm.xchma.provider.indicators.lib.mq5" // double xCHMADeposit = 0; double xCHMABalance = 0; double xCHMAFreeMargin = 0; double xCHMAFreeMarginForOpenTrades = 0; double xCHMABalanceForOpenTrades = 0; // // END Global Definitions: Variables, Properties and etc ... // // // START Provided Functions ... // // // Initial Library if required ... bool XCHMAInitSignalProviderLibrary() { // bool result = false; // // Validate Inputs ... result = XCHMAValidateInputs(); if (!result) { return result; } // // Init Indicators ... result = XCHMAInitIndicators(); if (!result) { return result; } // // Calculate Account Deposit ... xCHMADeposit = xCHMAAccountInfo.GetInitialBalance(); // // Calculate Min Balance for Trades ... if (xCHMABalanceFactorForOpenTrades > 0) { xCHMABalanceForOpenTrades = xCHMABalanceFactorForOpenTrades * xCHMADeposit; } // // Claculate Min Free Marging for Trades ... if (xCHMAFreeMarginFactorForOpenTrades > 0) { xCHMAFreeMarginForOpenTrades = xCHMAFreeMarginFactorForOpenTrades * xCHMADeposit; } // // Make XCTrader instance ... xCHMATrader = new XCTrade( _Symbol, xCHMASlippage, xCHMAMagicNumber); // result = true; // // Logging State ... XCHMAIssueInitializationSucceedAlert(); // return result; } // // DeInitial Library if required ... void XCHMADeinitSignalProviderLibrary( const int reason) { // // Release Handlers ... XCHMAReleaseIndicators(); // // Logging State ... XCHMAIssueDeinitializationSucceedAlert(); } // // this is a Globally Function which do all of // checkings and positions handling ... void XCHMASignalProviderHandleTick() { // // Update account Balance ... xCHMABalance = xCHMAAccountInfo.GetBalance(); xCHMAFreeMargin = xCHMAAccountInfo.GetFreeMargin(); // // Reading Indicator Buffers ... XCHMAHandleReadingBuffers(); if (xCHMACalculatedBars < xCHMAMaxLengthOfInputs) { return; } // // Handle Open Trades ... XCHMAHandleOpenTrades(); // // Handle Close Trades ... XCHMAHandleCloseTrades(); } // // Handle Open Trades ... void XCHMAHandleOpenTrades() { // // Check Can Trade ... bool canTrade = xCHMAAllowLongTrades || xCHMAAllowShortTrades; if (!canTrade) { return; } // // First Check Signal Exists or NOt ... bool xCHMAHasLongSignal = XCHMACanOpenLongTrade(); bool xCHMAHasShortSignal = XCHMACanOpenShortTrade(); if (!xCHMAHasLongSignal && !xCHMAHasShortSignal) { return; } // // Count Max Open Trades ... if (xCHMAMaxAllowedTrades > 0) { // int count = xCHMATrader.Count(); bool canOpenTrade = count < xCHMAMaxAllowedTrades; if (!canOpenTrade) { // XCHMAIssueMaxAllowedTradesReachedAlert(); // return; } } // // Check Free Margin ... if (xCHMAFreeMargin <= xCHMAFreeMarginForOpenTrades) { // XCHMAIssueMaxAllowedFreeMarginReachedAlert(); // return; } // // Check Account Balance ... if (xCHMABalance <= xCHMABalanceForOpenTrades) { // XCHMAIssueMinAllowedBalanceReachedAlert(); // return; } // // Primary Long Trade ... if ( xCHMAHasLongSignal && xCHMAAllowLongTrades) { // bool isLongSignalExecuted = XCHMAOpenLongPosition(); if (isLongSignalExecuted) { } } // // Primary Short Trade ... if ( xCHMAHasShortSignal && xCHMAAllowShortTrades) { // bool isShortSignalExecuted = XCHMAOpenShortPosition(); if (isShortSignalExecuted) { } } } // // Handle Close Trades ... void XCHMAHandleCloseTrades() { // // Handle Long/Buy Close ... if (xCHMATrader.CountLongs() > 0 && XCHMACanCloseLongTrade()) { // XSignal closed[]; xCHMATrader.CloseLongPositions(closed); bool hasClosed = ArraySize(closed) > 0; if (hasClosed) { XCHMAIssueForceCloseTradesAlert(X_SIGNAL_LONG); } } // // Handle Short/Sell Close ... if (xCHMATrader.CountShorts() > 0 && XCHMACanCloseShortTrade()) { // XSignal closed[]; xCHMATrader.CloseShortPositions(closed); bool hasClosed = ArraySize(closed) > 0; if (hasClosed) { XCHMAIssueForceCloseTradesAlert(X_SIGNAL_SHORT); } } // // Handle Close In Profit Teades ... if (xCHMAMaxInProfitTradeAge > 0) { // XSignal closed[]; XSignal longTimeTrades[]; xCHMATrader.GetLongTimeTrades( xCHMAMaxInProfitTradeAge, _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 = xCHMATrader.Close(trade.ticket); if (isClosed) { Add( trade, closed); } } } // if (ArraySize(closed) > 0) { XCHMAIssueLongInProfitTradeClosed(); } } // // Handle Close In DrawDown Trades ... if (xCHMAMaxInDrawDownTradeAge > 0) { // XSignal closed[]; XSignal longTimeTrades[]; xCHMATrader.GetLongTimeTrades( xCHMAMaxInDrawDownTradeAge, _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 ... XCHMAOpenSuppurtTrade(trade); // // // bool isClosed = xCHMATrader.Close(trade.ticket); // if (isClosed) // { // // // Add( // trade, // closed); // } } } // if (ArraySize(closed) > 0) { XCHMAIssueLongInDrawdownTradeClosed(); } } } // // Open Long Position ... bool XCHMAOpenLongPosition() { // bool result = false; // // Generate Position Signal and Validate it ... XSignal position = XCHMAGeneratePositionSignal(X_SIGNAL_LONG); if (!IsValid( position, xCHMAMagicNumber)) { return result; } // // Try to Open Position ... result = xCHMATrader.ExecuteSignal(position); if (result) { XCHMAIssueSignalExecutionAlert(position); } // return result; } // // Open Short Position ... bool XCHMAOpenShortPosition() { // bool result = false; // // Generate Position Signal and Validate it ... XSignal position = XCHMAGeneratePositionSignal(X_SIGNAL_SHORT); if (!IsValid( position, xCHMAMagicNumber)) { return result; } // // Try to Open Position ... result = xCHMATrader.ExecuteSignal(position); if (result) { XCHMAIssueSignalExecutionAlert(position); } // return result; } // // Open a Support Signal ... bool XCHMAOpenSuppurtTrade( XSignal &signal // Parent Signal ) { // bool result = false; // if (!xCHMAEnableSupportTrades) { return result; } // // Validate Signal ... if (!IsValid(signal, xCHMAMagicNumber)) { return result; } // // Market Conditions ... bool hasLongSignal = XCHMACanOpenLongTrade(); bool hasShortSignal = XCHMACanOpenShortTrade(); // 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 (xCHMAVolumeMultiplier > 2) { volumeMultiplier = xCHMAVolumeMultiplier; } // // 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 = XCHMACalculateTPSL(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 = xCHMAMagicNumber; // // Validate Generated Support ... if (!IsValid(support, xCHMAMagicNumber)) { return result; } // result = xCHMATrader.ExecuteSignal(support); if (result) { XCHMAIssueSignalExecutionAlert(support); } // return result; } // // Generate Specific type of Signals for Trading ... XSignal XCHMAGeneratePositionSignal( 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 = XCHMACalculateVolume(); // datetime time = iTime( _Symbol, _Period, 0); // string typeString = GetSignalType(type); string comment = XCHMAProviderName + "_" + typeString + "_" + (string)volume + "_" + (string)time; // XTPSL tpSL = XCHMACalculateTPSL(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 = xCHMAMagicNumber; // return result; } // // END Provided Functions ... // // // START Private Functions ... // // // Calculating Volume for Tradings ... double XCHMACalculateVolume() { // // Assign default Value ... double result = xCHMAStaticVolume; // // we can count open trades and in draw down trades // then do check volume based on it for gridding ... int openTrades = xCHMATrader.Count(); if (openTrades == 0) { openTrades = 1; } // // Calculate Normalized Multiplier ... double multiplier = xCHMAVolumeMultiplier <= 0 ? 1 : xCHMAVolumeMultiplier; // result = multiplier * openTrades * xCHMAStaticVolume; // // Normalize Volume ... result = NormalizeVolume(result); // return result; } // // Calculate Signal TP and SL ... XTPSL XCHMACalculateTPSL( 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(xCHMAMinRewardPerTradeInPips) + 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 XCHMAIssueInitializationSucceedAlert() { // string message = "Initializion of (" + XCHMAProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ..."; XCHMAIssueAlert(message); } void XCHMAIssueDeinitializationSucceedAlert() { // string message = "De Initializion of (" + XCHMAProviderName + " Provider" + ") Succeeded ..."; XCHMAIssueAlert(message); } void XCHMAIssueForceCloseTradesAlert(ENUM_X_SIGNAL_TYPE type) { // string typeStr = GetSignalType(type); if (StringLen(typeStr) == 0) { return; } // string message = "Force Close " + typeStr + " Trades ..."; XCHMAIssueAlert(message); } void XCHMAIssueMaxAllowedTradesReachedAlert() { // string message = "reached Max Allowed Same Time Trades ..."; XCHMAIssueAlert(message); } void XCHMAIssueMaxAllowedFreeMarginReachedAlert() { // string message = "reached FreeMarigin For Open Trades ..."; XCHMAIssueAlert(message); } void XCHMAIssueMinAllowedBalanceReachedAlert() { // string message = "doesn't have Minimum Balance For Open Trades ..."; XCHMAIssueAlert(message); } void XCHMAIssueSignalExecutionAlert( XSignal &signal // Executed Signal ) { // XCHMAIssueAlert(signal); } void XCHMAIssueLongInProfitTradeClosed() { // string message = "Closed Long Time in Profit Trades ..."; XCHMAIssueAlert(message); } void XCHMAIssueLongInDrawdownTradeClosed() { // string message = "Closed Long Time in Profit Trades ..."; XCHMAIssueAlert(message); } void XCHMAIssueAlert(string message) { // if (xCHMAEnableAlerts) { SendAlert(message); } else { LogMessage(message); } } void XCHMAIssueAlert(XSignal &signal) { // if (xCHMAEnableAlerts) { SendAlert(signal); } else { LogSignal(signal); } } // // END Private Functions ... //