//////////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 XCHLH Signal Provider Library // -------------------------------------------------------- // Name: XCHLHSignalProvider // Description: XCHLH 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 XCHLHProviderName "XCHLH" // // START Inputs ... // #include "x-saherelm.xchlh.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 *xCHLHTrader; XCAccountInfo xCHLHAccountInfo; // #include "x-saherelm.xchlh.provider.indicators.lib.mq5" // double xCHLHDeposit = 0; double xCHLHBalance = 0; double xCHLHFreeMargin = 0; double xCHLHMinRewardPerTrade = 0; double xCHLHFreeMarginForOpenTrades = 0; double xCHLHBalanceForOpenTrades = 0; // // END Global Definitions: Variables, Properties and etc ... // // // START Provided Functions ... // // // Initial Library if required ... bool XCHLHInitSignalProviderLibrary() { // bool result = false; // // Validate Inputs ... result = XCHLHValidateInputs(); if (!result) { return result; } // // Init Indicators ... result = XCHLHInitIndicators(); if (!result) { return result; } // // Calculate Account Deposit ... xCHLHDeposit = xCHLHAccountInfo.GetInitialBalance(); // // Calculate xCHLHMinRewardPerTrade ... if (xCHLHMinRewardPerTradeInPips > 0) { xCHLHMinRewardPerTrade = PipsToPrice(xCHLHMinRewardPerTradeInPips); } // // Calculate Min Balance for Trades ... if (xCHLHBalanceFactorForOpenTrades > 0) { xCHLHBalanceForOpenTrades = xCHLHBalanceFactorForOpenTrades * xCHLHDeposit; } // // Claculate Min Free Marging for Trades ... if (xCHLHFreeMarginFactorForOpenTrades > 0) { xCHLHFreeMarginForOpenTrades = xCHLHFreeMarginFactorForOpenTrades * xCHLHDeposit; } // // Make XCTrader instance ... xCHLHTrader = new XCTrade( _Symbol, xCHLHSlippage, xCHLHMagicNumber); // result = true; // // Logging State ... XCHLHIssueInitializationSucceedAlert(); // return result; } // // DeInitial Library if required ... void XCHLHDeinitSignalProviderLibrary( const int reason) { // // Release Handlers ... XCHLHReleaseIndicators(); // // Logging State ... XCHLHIssueDeinitializationSucceedAlert(); } // // this is a Globally Function which do all of // checkings and positions handling ... void XCHLHSignalProviderHandleTick() { // // Update account Balance ... xCHLHBalance = xCHLHAccountInfo.GetBalance(); xCHLHFreeMargin = xCHLHAccountInfo.GetFreeMargin(); // // Check Provider is Enable or Not ... if (!xCHLHEnableProvider) { return; } // // Reading Indicator Buffers ... XCHLHHandleReadingBuffers(); if (xCHLHCalculatedBars < xCHLHMaxLengthOfInputs) { return; } // // Handle Open Trades ... XCHLHHandleOpenTrades(); // // Handle Close Trades ... XCHLHHandleCloseTrades(); // // Handle Support Trades ... XCHLHHandleSupportTrades(); } // // Handle Open Trades ... void XCHLHHandleOpenTrades() { // // Check Can Trade ... bool canTrade = xCHLHAllowLongTrades || xCHLHAllowShortTrades; if (!canTrade) { return; } // // First Check Signal Exists or NOt ... bool xCHLHHasLongSignal = XCHLHCanOpenLongTrade(); bool xCHLHHasShortSignal = XCHLHCanOpenShortTrade(); if (!xCHLHHasLongSignal && !xCHLHHasShortSignal) { return; } // // Count Max Open Trades ... if (xCHLHMaxAllowedTrades > 0) { // int count = xCHLHTrader.Count(); bool canOpenTrade = count < xCHLHMaxAllowedTrades; if (!canOpenTrade) { // XCHLHIssueMaxAllowedTradesReachedAlert(); // return; } } // // Check Free Margin ... if (xCHLHFreeMargin <= xCHLHFreeMarginForOpenTrades) { // XCHLHIssueMaxAllowedFreeMarginReachedAlert(); // return; } // // Check Account Balance ... if (xCHLHBalance <= xCHLHBalanceForOpenTrades) { // XCHLHIssueMinAllowedBalanceReachedAlert(); // return; } // // Primary Long Trade ... if ( xCHLHHasLongSignal && xCHLHAllowLongTrades) { // bool isLongSignalExecuted = XCHLHOpenLongPosition(); if (isLongSignalExecuted) { } } // // Primary Short Trade ... if ( xCHLHHasShortSignal && xCHLHAllowShortTrades) { // bool isShortSignalExecuted = XCHLHOpenShortPosition(); if (isShortSignalExecuted) { } } } // // Handle Close Trades ... void XCHLHHandleCloseTrades() { // // Handle Long/Buy Close ... if (xCHLHTrader.CountLongs() > 0 && XCHLHCanCloseLongTrade()) { // XSignal closed[]; xCHLHTrader.CloseLongPositions(closed); bool hasClosed = ArraySize(closed) > 0; if (hasClosed) { XCHLHIssueForceCloseTradesAlert(X_SIGNAL_LONG); } } // // Handle Short/Sell Close ... if (xCHLHTrader.CountShorts() > 0 && XCHLHCanCloseShortTrade()) { // XSignal closed[]; xCHLHTrader.CloseShortPositions(closed); bool hasClosed = ArraySize(closed) > 0; if (hasClosed) { XCHLHIssueForceCloseTradesAlert(X_SIGNAL_SHORT); } } // // Handle Close In Profit Teades ... if (xCHLHMaxInProfitTradeAge > 0) { // XSignal closed[]; XSignal longTimeTrades[]; xCHLHTrader.GetLongTimeTrades( xCHLHMaxInProfitTradeAge, _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 = xCHLHTrader.Close(trade.ticket); if (isClosed) { Add( trade, closed); } } } // if (ArraySize(closed) > 0) { XCHLHIssueLongInProfitTradeClosed(); } } // // Handle Close In DrawDown Trades ... if (xCHLHMaxInDrawDownTradeAge > 0) { // // XSignal closed[]; // XSignal longTimeTrades[]; // xCHLHTrader.GetLongTimeTrades( // xCHLHMaxInDrawDownTradeAge, // _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 ... // // XCHLHOpenSuppurtTrade(trade); // // // // // bool isClosed = xCHLHTrader.Close(trade.ticket); // // if (isClosed) // // { // // // // // Add( // // trade, // // closed); // // } // } // } // // // if (ArraySize(closed) > 0) // { // XCHLHIssueLongInDrawdownTradeClosed(); // } } } // // Open Long Position ... bool XCHLHOpenLongPosition() { // bool result = false; // // Generate Position Signal and Validate it ... XSignal position = XCHLHGeneratePositionSignal(X_SIGNAL_LONG); if (!IsValid( position, xCHLHMagicNumber)) { return result; } // // Try to Open Position ... result = xCHLHTrader.ExecuteSignal(position); if (result) { XCHLHIssueSignalExecutionAlert(position); } // return result; } // // Open Short Position ... bool XCHLHOpenShortPosition() { // bool result = false; // // Generate Position Signal and Validate it ... XSignal position = XCHLHGeneratePositionSignal(X_SIGNAL_SHORT); if (!IsValid( position, xCHLHMagicNumber)) { return result; } // // Try to Open Position ... result = xCHLHTrader.ExecuteSignal(position); if (result) { XCHLHIssueSignalExecutionAlert(position); } // return result; } // // Handle Support Trades ... void XCHLHHandleSupportTrades() { // // Check Provider Enable ... if ( // !xCHLHEnableProvider // || // ( // !xCHLHAllowLongTrades && !xCHLHAllowShortTrades // ) // ) { return; } // double supportTradeDistance = NormalizePrice(xCHLHMinRewardPerTrade * 3); // // Check Long Support Trades ... XSignal inDDLongs[]; if (xCHLHAllowLongTrades) { xCHLHTrader.GetInDrawDownTrades( supportTradeDistance, X_SIGNAL_LONG, inDDLongs); } int inDDLongsCount = ArraySize(inDDLongs); // // Check Short Support Trades ... XSignal inDDShorts[]; if (xCHLHAllowShortTrades) { xCHLHTrader.GetInDrawDownTrades( supportTradeDistance, X_SIGNAL_SHORT, inDDShorts); } int inDDShortsCount = ArraySize(inDDShorts); // // Check Can Going Forward or not ... if (inDDLongsCount == 0 && inDDShortsCount == 0) { return; } // // Check Free Margin ... if (xCHLHFreeMargin <= xCHLHFreeMarginForOpenTrades) { // XCHLHIssueMaxAllowedFreeMarginReachedAlert(); // return; } // // Check Account Balance ... if (xCHLHBalance <= xCHLHBalanceForOpenTrades) { // XCHLHIssueMinAllowedBalanceReachedAlert(); // return; } // // Handle Long Trades Supports ... if (xCHLHAllowLongTrades && inDDLongsCount > 0) { // // Loop Through In DrawDown Trades ... for (int i = 0; i < inDDLongsCount; i++) { // XSignal inDDTrade = inDDLongs[i]; bool isExecuted = XCHLHOpenSupportTrade(inDDTrade); if (isExecuted) { } } } // // Handle Short Trades Supports ... if (xCHLHAllowShortTrades && inDDShortsCount > 0) { // // Loop Through In DrawDown Trades ... for (int i = 0; i < inDDShortsCount; i++) { // XSignal inDDTrade = inDDShorts[i]; bool isExecuted = XCHLHOpenSupportTrade(inDDTrade); if (isExecuted) { } } } } // // Open a Support Signal ... bool XCHLHOpenSupportTrade( XSignal &signal // Parent Signal ) { // bool result = false; // if (xCHLHMaxAllowedSupportTrades <= 0) { return result; } // // Validate Signal ... if (!IsValid(signal, xCHLHMagicNumber)) { return result; } // // Market Conditions ... bool hasLongSignal = XCHLHCanOpenLongTrade(); bool hasShortSignal = XCHLHCanOpenShortTrade(); // 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 (xCHLHVolumeMultiplier > 2) { volumeMultiplier = xCHLHVolumeMultiplier; } // // Check Signal is Support ot nor ... int titlePosition = StringFind( signal.comment, "Support"); bool isSupport = titlePosition >= 0; // // double priceDistance = MathAbs(signal.entry - entry); // || priceDistance < PipsToPrice(5) ... if (isSupport) { return result; } // // Check Signal Support Trades ... XSignal allTrades[]; if (signal.type == X_SIGNAL_LONG) { xCHLHTrader.GetLongPositions(allTrades); } else if (signal.type == X_SIGNAL_SHORT) { xCHLHTrader.GetShortPositions(allTrades); } // 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 = XCHLHCalculateTPSL(type); if (!IsValid(tpSL)) { return result; } // // Calculate reward of signal ... double reward = MathAbs(signal.entry - signal.tp) / 2; double tp = tpSL.tp; // 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 = xCHLHMagicNumber; // // Validate Generated Support ... if (!IsValid(support, xCHLHMagicNumber)) { return result; } // result = xCHLHTrader.ExecuteSignal(support); if (result) { XCHLHIssueSignalExecutionAlert(support); } // return result; } // // Generate Specific type of Signals for Trading ... XSignal XCHLHGeneratePositionSignal( 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 = XCHLHCalculateVolume(); // datetime time = iTime( _Symbol, _Period, 0); // string typeString = GetSignalType(type); string comment = XCHLHProviderName + "_" + typeString + "_" + (string)volume + "_" + (string)time; // XTPSL tpSL = XCHLHCalculateTPSL(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 = xCHLHMagicNumber; // return result; } // // END Provided Functions ... // // // START Private Functions ... // // // Calculating Volume for Tradings ... double XCHLHCalculateVolume() { // // Assign default Value ... double result = xCHLHStaticVolume; // // we can count open trades and in draw down trades // then do check volume based on it for gridding ... int openTrades = xCHLHTrader.Count(); if (openTrades == 0) { openTrades = 1; } // // Calculate Normalized Multiplier ... double multiplier = xCHLHVolumeMultiplier <= 0 ? 1 : xCHLHVolumeMultiplier; // result = multiplier * openTrades * xCHLHStaticVolume; // // Normalize Volume ... result = NormalizeVolume(result); // return result; } // // Calculate Signal TP and SL ... XTPSL XCHLHCalculateTPSL( 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(xCHLHMinRewardPerTradeInPips) + 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 XCHLHIssueInitializationSucceedAlert() { // string message = "Initializion of (" + XCHLHProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ..."; XCHLHIssueAlert(message); } void XCHLHIssueDeinitializationSucceedAlert() { // string message = "De Initializion of (" + XCHLHProviderName + " Provider" + ") Succeeded ..."; XCHLHIssueAlert(message); } void XCHLHIssueForceCloseTradesAlert(ENUM_X_SIGNAL_TYPE type) { // string typeStr = GetSignalType(type); if (StringLen(typeStr) == 0) { return; } // string message = "Force Close " + typeStr + " Trades ..."; XCHLHIssueAlert(message); } void XCHLHIssueMaxAllowedTradesReachedAlert() { // string message = "reached Max Allowed Same Time Trades ..."; XCHLHIssueAlert(message); } void XCHLHIssueMaxAllowedFreeMarginReachedAlert() { // string message = "reached FreeMarigin For Open Trades ..."; XCHLHIssueAlert(message); } void XCHLHIssueMinAllowedBalanceReachedAlert() { // string message = "doesn't have Minimum Balance For Open Trades ..."; XCHLHIssueAlert(message); } void XCHLHIssueSignalExecutionAlert( XSignal &signal // Executed Signal ) { // XCHLHIssueAlert(signal); } void XCHLHIssueLongInProfitTradeClosed() { // string message = "Closed Long Time in Profit Trades ..."; XCHLHIssueAlert(message); } void XCHLHIssueLongInDrawdownTradeClosed() { // string message = "Closed Long Time in Profit Trades ..."; XCHLHIssueAlert(message); } void XCHLHIssueAlert(string message) { // if (xCHLHEnableAlerts) { SendAlert(message); } else { LogMessage(message); } } void XCHLHIssueAlert(XSignal &signal) { // if (xCHLHEnableAlerts) { SendAlert(signal); } else { LogSignal(signal); } } // // END Private Functions ... //