//////////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 RSI Signal Provider Library // -------------------------------------------------------- // Name: XRSISignalProvider // Description: RSI 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 "XRSI Provider"; // input group "XRSI Common"; input bool enableRSIProvider = true; // Enable Provider input bool rsiEnableAlerts = true; // Enable Events Alert // input group "XRSI Indicator"; input int rsiPeriod = 14; // RSI Period input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To // input group "XRSI Trader"; input int rsiMagicNumber = 16940561; // RSI Trader MagicNumber input int rsiSlippage = 10; // RSI Trader Slippage input double rsiLongEntryLevel = 30; // RSI Long Entry Level input double rsiLongExitLevel = 60; // RSI Long Exit Level input double rsiShortEntryLevel = 70; // RSI Short Entry Level input double rsiShortExitLevel = 40; // RSI Short Exit Level // input group "XRSI Neural Networks"; input bool rsiUseNeuralNetworks = true; // Enable Neural Networks input bool rsiNNUseContinuesLearning = true; // Enable Continues Learning on Neural Networks input int rsiNNNumberOfNodes = 10; // Number Of Input Nodes input double rsiNNLongTargetOutput = 0.3; // BackPropagation Target Output for Long Trades input double rsiNNShortTargetOutput = -0.3; // BackPropagation Target Output for Short Trades // input group "XRSI Trade Management"; input bool rsiAllowLongTrades = true; // Allow Long Trades input bool rsiAllowShortTrades = true; // Allow Short Trades input bool rsiUseGridTrades = true; // Enable Grid Trades input double rsiGridVolumeMultiplier = 2; // Grid Volume Multiplier input double rsiGridDistancePips = 10; // Grid Position Distance in Pips // input group "XRSI Risk Management"; input bool rsiUseDynamicVolume = true; // Enable Dynamic Volume input double rsiStaticVolume = 0.01; // Static Volume // input double rsiBalanceIncreasedFactor = 0.1; // RSI Balance Increase Factor // input double rsiVolumeIncreasedFactor = 0.000001; // RSI Volume Increase Factor // // // // END Inputs ... // // input double rsiBalanceIncreased = 500; // RSI Balance Increase input double rsiVolumeIncreased = 0.01; // RSI 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" // // Include Neural Networks Library ... #include "x-saherelm.nn.lib.mq5"; // // START Global Definitions: Variables, Properties and etc ... // int rsiHandler = INVALID_HANDLE; double rsiBuffer[]; // XCTrade *rsiTrader; XCAccountInfo rsiAccountInfo; // XCNNBase *rsiNN; // double rsiGridLongPrice = 0; double rsiGridLongVolume = 0; // double rsiGridShortPrice = 0; double rsiGridShortVolume = 0; // // holds Neural Networks Output Value ... double rsiNNOutput; // // END Global Definitions: Variables, Properties and etc ... // // // START Provided Functions ... // // // Initial Library if required ... bool OnInInitXRSISignalProviderLibrary() { // bool result = false; // // Error Message ... string message = ""; // // Check RSI Period ... if (rsiPeriod < 5) { // message = "invalid rsi period ..."; LogMessage(message); // return result; } // // Check RSI Over Baught and Over Sold Levels ... if ( rsiLongExitLevel <= 0 || rsiLongEntryLevel <= 0 || rsiShortExitLevel <= 0 || rsiShortEntryLevel <= 0 || rsiLongEntryLevel >= rsiLongExitLevel || rsiLongEntryLevel >= rsiShortEntryLevel || rsiShortEntryLevel <= rsiShortExitLevel || rsiShortEntryLevel <= rsiLongEntryLevel) { // message = "invalid over baught / over seld level ..."; LogMessage(message); // return result; } // // Check Risk Management ... if (rsiUseDynamicVolume) { // // if (rsiBalanceIncreasedFactor <= 0 || rsiVolumeIncreasedFactor <= 0) if (rsiBalanceIncreased <= 0 || rsiVolumeIncreased <= 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 (rsiStaticVolume > maxAvailableVolume || rsiStaticVolume < minAvailableVolume) { // message = "invalid static volume ..."; LogMessage(message); // return result; } } // // Check Neural Networks Inputs ... if (rsiUseNeuralNetworks) { // // Number Of Nodes ... if (rsiNNNumberOfNodes < 3) { // message = "invalid neurak networks inputs ..."; LogMessage(message); // return result; } // // if there is no error in nn inputs, make an instance of // Neural Networks Clsss ... rsiNN = new XCNNBase( rsiNNNumberOfNodes); } // // Preparing RSI Handler ... rsiHandler = iRSI(_Symbol, _Period, rsiPeriod, rsiAppliedTo); if (rsiHandler == INVALID_HANDLE) { // message = "failed to initialize rsi indicator handler ..."; LogMessage(message); // return result; } // // Make XCTrader instance ... rsiTrader = new XCTrade( _Symbol, rsiSlippage, rsiMagicNumber); // result = true; // // Logging State ... message = "Initializion of (" + "XRSI Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ..."; LogMessage(message); // return result; } // // DeInitial Library if required ... void OnDeinitXRSISignalProviderLibrary() { // // Logging State ... string message = "De Initializion of (" + "XRSI Provider" + ") Succeeded ..."; LogMessage(message); } // // this is a Globally Function which do all of // checkings and positions handling ... void HandleXSignalProviderTick() { // // Reading RSI Values ... ArraySetAsSeries(rsiBuffer, true); // // Copy RSI Buffers based on NN Conditions ... if (rsiUseNeuralNetworks) { // CopyBuffer(rsiHandler, 0, 0, rsiNNNumberOfNodes, rsiBuffer); // // Calculate Neural Network Output Layer based on Inputs ... // since here there is no any external inputs except rsiBuffer // we passed it directly to our Neural Networks as Inputs ... rsiNNOutput = rsiNN.CalculateOutputLayer(rsiBuffer); // // Check Continues Learning is Enabled ... if (rsiNNUseContinuesLearning) { // // Handle Back Propagation (Continues Learning) ... double targetOutput = 0; if (rsiBuffer[1] >= 50) { targetOutput = rsiNNLongTargetOutput; } else if (rsiBuffer[1] < 50) { targetOutput = rsiNNShortTargetOutput; } // // Handle Calculate Weights ... if (targetOutput != 0) { rsiNN.BackPropagation(rsiBuffer, rsiNNOutput, targetOutput); } } } else { CopyBuffer(rsiHandler, 0, 0, 5, rsiBuffer); } // // Handle Open Trades ... HandleOpenTrades(); // // Handle Close Trades ... HandleCloseTrades(); // // Draw Signals ... // bool hasPrimaryLongSignal = HasPrimaryLongSignal(); // bool hasPrimaryShortSignal = HasPrimaryShortSignal(); // bool hasPrimarySignal = hasPrimaryLongSignal || hasPrimaryShortSignal; // if (hasPrimarySignal) // { // // // ENUM_X_SIGNAL_TYPE signalType = hasPrimaryLongSignal ? X_SIGNAL_LONG : X_SIGNAL_SHORT; // double signalPrice = signalType == X_SIGNAL_LONG ? GetAsk() : GetBid(); // string signalName = logTag + "_" + EnumToString(signalType) + "_" + DoubleToString(signalPrice); // color signalColor = signalType == X_SIGNAL_LONG ? clrAqua : clrYellow; // datetime signalTime1 = iTime(_Symbol, _Period, 1); // datetime signalTime2 = iTime(_Symbol, _Period, 0); // // // DrawTrendLine( // 0, // Chart Id ... // signalName, // Object Name ... // 0, // SubWindow ... // signalTime1, // Time 1 ... // signalPrice, // Price 1 ... // signalTime2, // Time 2 ... // signalPrice, // Price 2 ... // signalColor, // Color ... // STYLE_SOLID, // 5 // ); // } } // // Check Market Conditions to find Long Primary Signals ... bool HasPrimaryLongSignal() { // bool result = false; // // Check Buy/Long Conditions ... result = rsiBuffer[1] >= rsiLongEntryLevel && rsiBuffer[2] < rsiLongEntryLevel; // return result; } // // Check Market Conditions to find Short Primary Signals ... bool HasPrimaryShortSignal() { // bool result = false; // // Check Sell/Short Conditions ... result = rsiBuffer[1] <= rsiShortEntryLevel && rsiBuffer[2] > rsiShortEntryLevel; // return result; } // // Check Market Conditions to find Long Grid Signals ... bool HasGridLongSignal() { // bool result = false; // // Check Buy/Long Conditions ... result = rsiBuffer[1] >= rsiLongEntryLevel && rsiBuffer[2] < rsiLongEntryLevel; // return result; } // // Check Market Conditions to find Short Grid Signals ... bool HasGridShortSignal() { // bool result = false; // // Check Sell/Short Conditions ... result = rsiBuffer[1] <= rsiShortEntryLevel && rsiBuffer[2] > rsiShortEntryLevel; // return result; } // // Check Market Conditions for closing Long Trades ... bool CanCloseLongTrades() { // bool result = rsiBuffer[1] > rsiLongExitLevel && rsiBuffer[2] < rsiLongExitLevel; return result; } // // Check Market Conditions for closing Short Trades ... bool CanCloseShortTrades() { // bool result = rsiBuffer[1] < rsiShortExitLevel && rsiBuffer[2] > rsiShortExitLevel; return result; } // // Handle Long/Buy for Primary Trades... bool HandlePrimaryLong( XSignal &signal, // return structure if signal founded bool doTrade = true // do trade on signal ) { // bool result = false; // ResetLastError(); // // Check Conditions of Neural Networks if it's enabled ... bool canForward = !rsiUseNeuralNetworks ? true : rsiNNOutput > 0; // if (HasPrimaryLongSignal() && rsiTrader.CountLongs() == 0 && canForward) { // double entry = GetAsk(); double volume = CalculateVolume(); // double canDoTrade = CanDoTrade(); // signal.entry = entry; signal.volume = volume; signal.symbol = _Symbol; signal.type = X_SIGNAL_LONG; signal.magicNumber = rsiMagicNumber; signal.time = iTime(_Symbol, _Period, 0); signal.comment = "Primary XRSI Long"; // if (enableRSIProvider && rsiAllowLongTrades && doTrade && canDoTrade) { // // Execute Signal ... result = rsiTrader.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 (rsiEnableAlerts) { SendAlert(signal, true); } else { LogExecutedSignal(signal); } } // return result; } // // Handle Short/Sell for Primary Trades... bool HandlePrimaryShort( XSignal &signal, // return structure if signal founded bool doTrade = true // do trade on signal ) { // bool result = false; // ResetLastError(); // // Check Conditions of Neural Networks if it's enabled ... bool canForward = !rsiUseNeuralNetworks ? true : rsiNNOutput < 0; // if (HasPrimaryShortSignal() && rsiTrader.CountShorts() == 0 && canForward) { // double entry = GetBid(); double volume = CalculateVolume(); // double canDoTrade = CanDoTrade(); // signal.entry = entry; signal.volume = volume; signal.symbol = _Symbol; signal.type = X_SIGNAL_SHORT; signal.magicNumber = rsiMagicNumber; signal.time = iTime(_Symbol, _Period, 0); signal.comment = "Primary XRSI Short"; // if (enableRSIProvider && rsiAllowShortTrades && doTrade && canDoTrade) { // // Execute Signal ... result = rsiTrader.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 (rsiEnableAlerts) { SendAlert(signal, true); } else { LogExecutedSignal(signal); } } // return result; } // // Handle Long/Buy for Grid Trades... bool HandleGridLong( XSignal &signal, // return structure if signal founded bool doTrade = true // do trade on signal ) { // bool result = false; // ResetLastError(); // double ask = GetAsk(); bool canDoGridTrade = ask <= rsiGridLongPrice; if (HasGridLongSignal() && rsiTrader.CountLongs() > 0 && canDoGridTrade) { // double entry = ask; double volume = rsiGridLongVolume; // double canDoTrade = CanDoTrade(); // signal.entry = entry; signal.volume = volume; signal.symbol = _Symbol; signal.type = X_SIGNAL_LONG; signal.magicNumber = rsiMagicNumber; signal.time = iTime(_Symbol, _Period, 0); signal.comment = "Grid XRSI Long"; // if (enableRSIProvider && rsiAllowLongTrades && rsiUseGridTrades && doTrade && canDoTrade) { // // Execute Signal ... result = rsiTrader.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 (rsiEnableAlerts) { SendAlert(signal, true); } else { LogExecutedSignal(signal); } } // return result; } // // Handle Short/Sell for Grid Trades... bool HandleGridShort( XSignal &signal, // return structure if signal founded bool doTrade = true // do trade on signal ) { // bool result = false; // ResetLastError(); // double bid = GetBid(); bool canDoGridTrade = bid >= rsiGridShortPrice; if (HasGridShortSignal() && rsiTrader.CountShorts() > 0 && canDoGridTrade) { // double entry = bid; double volume = rsiGridShortVolume; // double canDoTrade = CanDoTrade(); // signal.entry = entry; signal.volume = volume; signal.symbol = _Symbol; signal.type = X_SIGNAL_SHORT; signal.magicNumber = rsiMagicNumber; signal.time = iTime(_Symbol, _Period, 0); signal.comment = "Grid XRSI Short"; // if (enableRSIProvider && rsiAllowShortTrades && rsiUseGridTrades && doTrade && canDoTrade) { // // Execute Signal ... result = rsiTrader.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 (rsiEnableAlerts) { SendAlert(signal, true); } else { LogExecutedSignal(signal); } } // return result; } // // Handle Open Trades ... void HandleOpenTrades() { // // Primary Long Trade ... XSignal primaryLongSignal = {}; bool isPrimaryLongSignalExecuted = HandlePrimaryLong(primaryLongSignal); if (isPrimaryLongSignalExecuted) { // // Calculate Grid Long Conditions ... CalculateGridLongConditions(primaryLongSignal); } // // Primary Short Trade ... XSignal primaryShortSignal = {}; bool isPrimaryShortSignalExecuted = HandlePrimaryShort(primaryShortSignal); if (isPrimaryShortSignalExecuted) { // // Calculate Grid Short Conditions ... CalculateGridShortConditions(primaryShortSignal); } // // Check Grid Trades ... if (rsiUseGridTrades) { // // Grid Long Trade ... XSignal gridLongSignal = {}; bool isGridLongSignalExecuted = HandleGridLong(gridLongSignal); if (isGridLongSignalExecuted) { // // Calculate Grid Long Conditions ... CalculateGridLongConditions(gridLongSignal); } // // Grid Short Trade ... XSignal gridShortSignal = {}; bool isGridShortSignalExecuted = HandleGridShort(gridShortSignal); if (isGridShortSignalExecuted) { // // Calculate Grid Short Conditions ... CalculateGridShortConditions(gridShortSignal); } } } // // Handle Close Trades ... void HandleCloseTrades() { // // Handle Long/Buy Close ... if (rsiTrader.CountLongs() > 0 && CanCloseLongTrades()) { // rsiTrader.CloseLongPositions(); // // Reset Grid Long Conditions ... rsiGridLongPrice = 0; rsiGridLongVolume = 0; // string message = "XRSI Closing Long Trades ..."; // if (rsiEnableAlerts) { SendAlert(message); } else { LogMessage(message); } } // // Handle Short/Sell Close ... if (rsiTrader.CountShorts() > 0 && CanCloseShortTrades()) { // rsiTrader.CloseShortPositions(); // // Reset Grid Short Conditions ... rsiGridShortPrice = 0; rsiGridShortVolume = 0; // string message = "XRSI Closing Short Trades ..."; // if (rsiEnableAlerts) { SendAlert(message); } else { LogMessage(message); } } } // // Calculating Volume for Tradings ... double CalculateVolume() { // double result = rsiStaticVolume; if (!rsiUseDynamicVolume) { return result; } // double accountBalance = rsiAccountInfo.GetBalance(); // double accountInitialBalance = rsiAccountInfo.GetInitialBalance(); // double balanceIncreased = accountInitialBalance * rsiBalanceIncreasedFactor; // double volumeIncreased = accountInitialBalance * rsiVolumeIncreasedFactor; double balanceIncreased = rsiBalanceIncreased; double volumeIncreased = rsiVolumeIncreased; // 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 Grid Long Trades Price and Volume ... void CalculateGridLongConditions(XSignal &signal) { // // Check Grid Trades Enable ... if (!rsiUseGridTrades) { return; } // // Calculate GridLongPrice and GridLongVolume ... rsiGridLongVolume = NormalizeDouble(signal.volume * rsiGridVolumeMultiplier, 2); rsiGridLongPrice = NormalizeDouble(signal.entry - (rsiGridDistancePips * 10 * _Point), _Digits); } // // Calculate Grid Short Trades Price and Volume ... void CalculateGridShortConditions(XSignal &signal) { // // Check Grid Trades Enable ... if (!rsiUseGridTrades) { return; } // // Calculate GridShortPrice and GridShortVolume ... rsiGridShortVolume = NormalizeDouble(signal.volume * rsiGridVolumeMultiplier, 2); rsiGridShortPrice = NormalizeDouble(signal.entry + (rsiGridDistancePips * 10 * _Point), _Digits); } // // Determine based on current account state bool CanDoTrade() { // bool result = true; // // TODO: Complete this ... // return true; } // // END Provided Functions ... //