//////////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 XOBD Signal Provider Library // -------------------------------------------------------- // Name: XSignalProvider // Description: 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 // // START Inputs ... // input group "XOBD Provider"; // input group "XOBD Common"; input bool enableXOBDProvider = true; // Enable Provider input bool xOBDEnableAlerts = true; // Enable Events Alert // input group "XOBD Indicator"; input int xOBDLength = 5; // Market Length input double xOBDArrowDistanceFromPrice = 0; // Arrow Distrance from Price input uchar xOBDSwingHighArrowCode = 108; // Swing High Arrow Code input color xOBDSwingHighArrowColor = clrMagenta; // Swing High Arrow Color input uchar xOBDSwingLowArrowCode = 108; // Swing Low Arrow Code input color xOBDSwingLowArrowColor = clrAqua; // Swing Low Arrow Color // input group "XOBD Trader"; input int xOBDMagicNumber = 16940562; // Trader MagicNumber input int xOBDSlippage = 10; // Trader Slippage // input group "XOBD Trade Management"; input bool xOBDAllowLongTrades = true; // Allow Long Trades input bool xOBDAllowShortTrades = false; // Allow Short Trades input int xOBDMaxOpenTrades = 4; // Max Open Trades at Same Time // input group "XOBD Risk Management"; input bool xOBDUseTPSL = true; // Allow use TP and SL input bool xOBDUseVirtualTPSL = false; // Allow Use Virtual TP and SL input bool xOBDDrawTPSL = true; // Draw TP and SL input double xOBDR2r = 1.5; // Risk To Reward Ratio input int xOBDLoopback = 3; // Loopback Length for TP/SL Calculation input double xOBDMinRiskPerTrade = 100; // Min Risk Per Trade in Points input double xOBDMaxRiskPerTrade = 1000; // Max Risk Per Trade in Points input bool xOBDUseDynamicVolume = false; // Enable Dynamic Volume input double xOBDStaticVolume = 0.01; // Static Volume input double xOBDBalanceIncreased = 500; // Balance Increase input double xOBDVolumeIncreased = 0.01; // Volume Increase // // 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 ... // // int xOBDHandler = INVALID_HANDLE; double xOBDBuffer[]; // XCTrade *xOBDTrader; XCAccountInfo xOBDAccountInfo; // // END Global Definitions: Variables, Properties and etc ... // // // START Provided Functions ... // // // Initial Library if required ... bool OnInInitXOBDSignalProviderLibrary() { // bool result = false; // // Error Message ... string message = ""; // ResetLastError(); xOBDHandler = iCustom( _Symbol, _Period, "x-saherelm.xobd.indicator", // xOBDLength, xOBDArrowDistanceFromPrice, xOBDSwingHighArrowCode, xOBDSwingHighArrowColor, xOBDSwingLowArrowCode, xOBDSwingLowArrowColor); if (xOBDHandler == INVALID_HANDLE) { // LogMessage("error initializing XOBD Indicator: " + (string)GetLastError()); return result; } // // Check Risk Management ... if (xOBDUseDynamicVolume) { // if (xOBDBalanceIncreased <= 0 || xOBDVolumeIncreased <= 0) { // message = "invalid volume increased factors ..."; LogMessage(message); // return result; } } else { // double maxAvailableVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); double minAvailableVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); // if (xOBDStaticVolume > maxAvailableVolume || xOBDStaticVolume < minAvailableVolume) { // message = "invalid static volume ..."; LogMessage(message); // return result; } } // // Validate use TPSL ... if (xOBDUseTPSL) { // if (xOBDR2r < 1.2) { // LogMessage("Risk to Rewadrd Ratio is too small ..."); // return result; } } // // Make XCTrader instance ... xOBDTrader = new XCTrade( _Symbol, xOBDSlippage, xOBDMagicNumber); // result = true; // // Logging State ... message = "Initializion of (" + "XOBD Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ..."; LogMessage(message); // return result; } // // DeInitial Library if required ... void OnDeinitXOBDSignalProviderLibrary() { // // Logging State ... string message = "De Initializion of (" + "XOBD Provider" + ") Succeeded ..."; LogMessage(message); } // // this is a Globally Function which do all of // checkings and positions handling ... void HandleXOBDSignalProviderTick() { // // Reding XOBD Buffer ... CopyBuffer(xOBDHandler, 0, 0, 5, xOBDBuffer); // // Handle Open Trades ... XOBDHandleOpenTrades(); // // Handle Close Trades ... XOBDHandleCloseTrades(); } // // Check Market Conditions to find Long Primary Signals ... bool XOBDHasPrimaryLongSignal() { // bool result = false; // // Check Buy/Long Conditions ... // Swing Low is a sign of Bullish Trend ... result = xOBDBuffer[4] == -1; // return result; } // // Check Market Conditions to find Short Primary Signals ... bool XOBDHasPrimaryShortSignal() { // bool result = false; // // Check Sell/Short Conditions ... // Swing High is a sign of Bearish Trend ... result = xOBDBuffer[4] == 1; // return result; } // // Check Market Conditions for closing Long Trades ... bool XOBDCanCloseLongTrades() { // bool result = false; // // Check Market Conditions for Closing // Long Trades ... // result = xOBDBuffer[4] == 1; // return result; } // // Check Market Conditions for closing Short Trades ... bool XOBDCanCloseShortTrades() { // bool result = false; // // Check Market Conditions for Closing // Short Trades ... // result = xOBDBuffer[4] == -1; // return result; } // // Handle Long/Buy for Primary Trades... bool XOBDHandlePrimaryLong( XSignal &signal, // return structure if signal founded bool doTrade = true // do trade on signal ) { // bool result = false; // ResetLastError(); // // && xOBDTrader.CountLongs() == 0 if (XOBDHasPrimaryLongSignal()) { // double entry = GetAsk(); double volume = XOBDCalculateVolume(); // double canDoTrade = XOBDCanDoTrade(); // // Handle TP SL if it's enabled ... if (xOBDUseTPSL) { XTPSL mTpSl = XOBDCalculateTPSL(X_SIGNAL_LONG, entry); if (IsValid(mTpSl)) { // // Check for Draw TP and SL ... if (xOBDDrawTPSL) { XOBDDrawTPSL(mTpSl); } // // Set TP SL in Signal if it's required to add directly ... if (!xOBDUseVirtualTPSL) { // signal.tp = mTpSl.tp; signal.sl = mTpSl.sl; } // // Draw Virtual TP SL for Closing Trades ... else { // // TODO: implement this ... } } } // signal.entry = entry; signal.volume = volume; signal.symbol = _Symbol; signal.type = X_SIGNAL_LONG; signal.magicNumber = xOBDMagicNumber; signal.time = iTime(_Symbol, _Period, 0); signal.comment = "Primary XOBD Long"; // if (enableXOBDProvider && xOBDAllowLongTrades && doTrade && canDoTrade) { // // Execute Signal ... result = xOBDTrader.ExecuteSignal(signal); // // Since this means an error happens, we have to log this error ... if (!result) { string errMessage = "failed to execute Long signal: " + (string)GetLastError(); LogMessage(errMessage); } } else { result = false; } } // // Handle Alerts ... if (result) { // if (xOBDEnableAlerts) { SendAlert(signal, true); } else { LogExecutedSignal(signal); } } // return result; } // // Handle Short/Sell for Primary Trades... bool XOBDHandlePrimaryShort( XSignal &signal, // return structure if signal founded bool doTrade = true // do trade on signal ) { // bool result = false; // ResetLastError(); // // && xOBDTrader.CountShorts() == 0 if (XOBDHasPrimaryShortSignal()) { // double entry = GetBid(); double volume = XOBDCalculateVolume(); // double canDoTrade = XOBDCanDoTrade(); // signal.entry = entry; signal.volume = volume; signal.symbol = _Symbol; signal.type = X_SIGNAL_SHORT; signal.magicNumber = xOBDMagicNumber; signal.time = iTime(_Symbol, _Period, 0); signal.comment = "Primary XOBD Short"; // if (enableXOBDProvider && xOBDAllowShortTrades && doTrade && canDoTrade) { // // Execute Signal ... result = xOBDTrader.ExecuteSignal(signal); // // Since this means an error happens, we have to log this error ... if (!result) { string errMessage = "failed to execute Short signal: " + (string)GetLastError(); LogMessage(errMessage); } } else { result = false; } } // // Handle Alerts ... if (result) { // if (xOBDEnableAlerts) { SendAlert(signal, true); } else { LogExecutedSignal(signal); } } // return result; } // // Handle Open Trades ... void XOBDHandleOpenTrades() { // // Primary Long Trade ... XSignal primaryLongSignal = {}; bool isPrimaryLongSignalExecuted = XOBDHandlePrimaryLong(primaryLongSignal); if (isPrimaryLongSignalExecuted) { } // // Primary Short Trade ... XSignal primaryShortSignal = {}; bool isPrimaryShortSignalExecuted = XOBDHandlePrimaryShort(primaryShortSignal); if (isPrimaryShortSignalExecuted) { } } // // Handle Close Trades ... void XOBDHandleCloseTrades() { // // Handle Long/Buy Close ... if (xOBDTrader.CountLongs() > 0 && XOBDCanCloseLongTrades()) { // xOBDTrader.CloseLongPositions(); // string message = "XOBD Closing Long Trades ..."; // if (xOBDEnableAlerts) { SendAlert(message); } else { LogMessage(message); } } // // Handle Short/Sell Close ... if (xOBDTrader.CountShorts() > 0 && XOBDCanCloseShortTrades()) { // xOBDTrader.CloseShortPositions(); // string message = "XOBD Closing Short Trades ..."; // if (xOBDEnableAlerts) { SendAlert(message); } else { LogMessage(message); } } } // // Calculating Volume for Tradings ... double XOBDCalculateVolume() { // double result = xOBDStaticVolume; if (!xOBDUseDynamicVolume) { return result; } // double accountBalance = xOBDAccountInfo.GetBalance(); double balanceIncreased = xOBDBalanceIncreased; double volumeIncreased = xOBDVolumeIncreased; // result = (volumeIncreased * accountBalance) / balanceIncreased; // // Normalize Volume ... result = NormalizeDouble(result, 2); // double maxAvailableVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); double minAvailableVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); // // Validate Result ... if (result > maxAvailableVolume) { result = maxAvailableVolume; } else if (result < minAvailableVolume) { result = minAvailableVolume; } // return result; } // // Calculate TP and SL ... XTPSL XOBDCalculateTPSL( ENUM_X_SIGNAL_TYPE type, // Which Type to Calculate TP and SL double entry // Signal Entry Price ) { // XTPSL result = {}; result.type = X_SIGNAL_UNKNOWN; result.tp = 0; result.sl = 0; result.r2r = 0; result.entry = 0; // if (!xOBDUseTPSL) { return result; } // // Validate Args ... if (entry <= 0 || type == X_SIGNAL_UNKNOWN) { return result; } // result.type = type; result.r2r = xOBDR2r; result.entry = entry; // bool isLong = type == X_SIGNAL_LONG; // // Retrieve Market Highest High and Lowest Low ... double hh = GetHighestHigh( xOBDLoopback, 0); double ll = GetLowestLow( xOBDLoopback, 0); // double maxRisk = xOBDMaxRiskPerTrade * _Point; double minRisk = xOBDMinRiskPerTrade * _Point; // // Calculate and Normalize risk ... double risk = isLong ? entry - ll : hh - entry; // if (risk > maxRisk) // { // risk = maxRisk; // } // else if (risk < minRisk) // { // risk = minRisk; // } // double reward = risk * xOBDR2r; // double tp = isLong ? entry + reward : entry - reward; double sl = isLong ? entry - risk : entry + risk; // tp = NormalizeDouble(tp, _Digits); sl = NormalizeDouble(sl, _Digits); // result.tp = tp; result.sl = sl; // return result; } // // Determine based on current account state bool XOBDCanDoTrade() { // bool result = false; // // Check Max Open Trades ... int totalOpenTrades = xOBDTrader.Count(); result = totalOpenTrades <= xOBDMaxOpenTrades; if (!result) { return result; } // return result; } // // START Draw Functions ... // void XOBDDrawTPSL( XTPSL &model // an instance of XTPS structure ) { // // Validate Args ... if (!IsValid(model)) { return; } // string entryName = "T_" + EnumToString(model.type) + "_Entry_" + (string)model.entry; string slName = entryName + "_SL_" + (string)model.sl; string tpName = entryName + "_TP_" + (string)model.tp; datetime time1 = iTime(_Symbol, _Period, 2); datetime time2 = iTime(_Symbol, _Period, 0); color tpColor = xOBDSwingLowArrowColor; color slColor = xOBDSwingHighArrowColor; // // Draw Entry ... DrawTrendLine( 0, entryName, 0, time1, model.entry, time2, model.entry, clrYellow); // // Draw TP ... if (model.tp > 0) { // DrawTrendLine( 0, tpName, 0, time1, model.tp, time2, model.tp, tpColor); } // // Draw SL ... if (model.sl > 0) { // DrawTrendLine( 0, slName, 0, time1, model.sl, time2, model.sl, slColor); } } // // END Draw Functions ... // // // END Provided Functions ... //