Files
xMQL5/BKPS/14020926 XEU5/Providers/x-saherelm.xeu5.provider.lib.mq5
T
2024-01-25 04:09:42 +03:30

903 lines
19 KiB
Plaintext

////////////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 XEU5 Signal Provider Library
// --------------------------------------------------------
// Name: XEU5SignalProvider
// Description: XEU5 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 XEU5ProviderName "XEU5"
//
// START Inputs ...
//
#include "x-saherelm.xeu5.provider.inputs.lib.mq5";
//
// END Inputs ...
//
//
// Include Common Library ...
#include "..\Libraries\x-saherelm.common.lib.mq5"
//
// Include Logger Library ...
#include "..\Libraries\x-saherelm.log.lib.mq5"
//
// Include Alert Library ...
#include "..\Libraries\x-saherelm.alert.lib.mq5"
//
// Include Draw Library ...
#include "..\Libraries\x-saherelm.draw.lib.mq5"
//
// Include Class Libraries ...
#include "..\Classes\x-saherelm.class.lib.mq5"
//
// START Global Definitions: Variables, Properties and etc ...
//
//
XCTrade *xEU5Trader;
XCAccountInfo xEU5AccountInfo;
//
#include "x-saherelm.xeu5.provider.indicators.lib.mq5"
//
double xEU5Deposit = 0;
double xEU5Balance = 0;
double xEU5MinReward = 0;
double xEU5FreeMargin = 0;
double xEU5BalanceForOpenTrades = 0;
double xEU5FreeMarginForOpenTrades = 0;
double xEU5BaseRiskableMoneyPerTrade = 0;
double xEU5SupportTradesPriceDistance = 0;
//
int NOT_ENOUGH_MONEY_ERROR = 4756;
//
// On Trade Context Data ...
//
int xEU5DaysForRead = 1;
//
// set the limits of the trade history on the global scope ...
datetime xEU5StartDate; // start date for trade history in cache
datetime xEU5EndDate; // end date for trade history in cache
//
// global counters ...
int xEU5Orders; // number of active orders
int xEU5Positions; // number of open positions
int xEU5Deals; // number of deals in the trade history cache
int xEU5HistoryOrders; // number of orders in the trade history cache
bool xEU5ScanStarted = false; // flag of counter relevance
//
// END Global Definitions: Variables, Properties and etc ...
//
//
// START Provided Functions ...
//
//
// Initial Library if required ...
bool XEU5InitSignalProviderLibrary()
{
//
bool result = false;
//
// Reset On Trade Counter ...
XEU5ResetOnTradeContext();
//
// Init On Trade Context ...
XEU5InitOnTradeContext();
//
// Validate Inputs ...
result = XEU5ValidateInputs();
if (!result)
{
return result;
}
//
// Init Indicators ...
result = XEU5InitIndicators();
if (!result)
{
return result;
}
//
// Calculate Account Deposit ...
xEU5Deposit = xEU5AccountInfo.GetInitialBalance();
//
// Prepare Min Reward ...
if (xEU5MinRewardInPips > 0)
{
xEU5MinReward = PipsToPrice(xEU5MinRewardInPips);
}
//
// Calculate Min Balance for Trades ...
if (xEU5BalanceFactorForOpenTrades > 0)
{
xEU5BalanceForOpenTrades = xEU5BalanceFactorForOpenTrades * xEU5Deposit;
}
//
// Claculate Min Free Marging for Trades ...
if (xEU5FreeMarginFactorForOpenTrades > 0)
{
xEU5FreeMarginForOpenTrades = xEU5FreeMarginFactorForOpenTrades * xEU5Deposit;
}
//
// Calculate xEU5SupportTradesPriceDistance ...
if (xEU5MaxAllowedSupportTrades > 0 && xEU5SupportTradesPriceDistanceInPips > 0)
{
xEU5SupportTradesPriceDistance = PipsToPrice(xEU5SupportTradesPriceDistanceInPips);
}
//
// Calculate Base Riskable Money Per Trade ...
if (xEU5MaxAllowedRiskPerTradesMultiplier > 0)
{
xEU5BaseRiskableMoneyPerTrade = (xEU5MaxAllowedRiskPerTradesMultiplier * xEU5Deposit);
}
//
// Make XCTrader instance ...
xEU5Trader = new XCTrade(
XEU5ProviderName,
_Symbol,
xEU5Slippage,
xEU5MagicNumber,
xEU5MaxAllowedTrades,
xEU5FreeMarginForOpenTrades,
xEU5BalanceForOpenTrades);
//
result = true;
//
// Logging State ...
XEU5IssueInitializationSucceedAlert();
//
return result;
}
//
// DeInitial Library if required ...
void XEU5DeinitSignalProviderLibrary(const int reason)
{
//
// Release Handlers ...
XEU5ReleaseIndicators();
//
// Logging State ...
XEU5IssueDeinitializationSucceedAlert();
}
//
// this is a Globally Function which do all of
// checkings and positions handling ...
void XEU5SignalProviderHandleTick()
{
//
// Update account Balance ...
xEU5Balance = xEU5AccountInfo.GetBalance();
xEU5FreeMargin = xEU5AccountInfo.GetFreeMargin();
//
// Check Provider is Enable or Not ...
if (!xEU5EnableProvider)
{
return;
}
//
// Handling Signals ...
XTraderHandlerResult handleSignalResult;
xEU5Trader.HandleSignals(
handleSignalResult,
true, // Ignore Signal TP and SL for Virtal Handling
false // Ignore Risk Free Trdaes
);
//
// TODO: Log it Later ...
//
// Reading Indicator Buffers ...
XEU5HandleReadingBuffers();
if (xEU5CalculatedBars < xEU5MaxLengthOfInputs)
{
return;
}
//
// Handle Open Trades ...
XEU5HandleOpenTrades();
//
// Handle Close Trades ...
XEU5HandleCloseTrades();
}
//
// Handle Trades when OnTrade Event Hnadler Calls ...
void XEU5SignalProviderHandleTrade()
{
//
if (xEU5ScanStarted)
{
XEU5ProcessOnTradeContext();
}
else
{
XEU5InitOnTradeContext();
}
}
//
// Handle Open Trades ...
void XEU5HandleOpenTrades()
{
//
// Check Can Trade ...
bool canTrade = xEU5AllowLongTrades || xEU5AllowShortTrades;
if (!canTrade)
{
return;
}
//
// Check Max Open Trades ...
int openSignals = xEU5Trader.Count();
bool canOpenPositions = openSignals < xEU5MaxAllowedTrades;
if (!canOpenPositions)
{
return;
}
//
// Check Signals Exists ...
XEU5Signal longSignalInfo;
XEU5Signal shortSignalInfo;
bool hasLongSignal = XEU5CanOpenLongTrade(longSignalInfo);
bool hasShortSignal = XEU5CanOpenShortTrade(shortSignalInfo);
if (!hasLongSignal && !hasShortSignal)
{
return;
}
//
// Open Long Trades ...
if (
//
hasLongSignal &&
xEU5AllowLongTrades)
{
//
bool isOpened = XEU5OpenLongPosition(longSignalInfo);
}
//
// Open Short Trades ...
if (
//
hasShortSignal &&
xEU5AllowShortTrades)
{
//
bool isOpened = XEU5OpenShortPosition(shortSignalInfo);
}
}
//
// Handle Close Trades ...
void XEU5HandleCloseTrades()
{
//
// All Close Mechanism Handles Here ...
// - Force Close;
// - Partial Close;
// - Risk Free Close;
// - Virtual TP/SL Close;
//
// Force Close Long Trades ...
bool canCloseLongTrades = XEU5CanCloseLongTrade();
if (xEU5AllowLongTrades && canCloseLongTrades)
{
//
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_LONG;
//
XSignal closed[];
xEU5Trader.CloseSignals(
closed,
type);
//
bool isClosed = ArraySize(closed) > 0;
if (isClosed)
{
XEU5IssueForceCloseTradesAlert(type);
}
}
//
// Force Close Short Trades ...
bool canCloseShortTrades = XEU5CanCloseShortTrade();
if (xEU5AllowShortTrades && canCloseShortTrades)
{
//
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_SHORT;
//
XSignal closed[];
xEU5Trader.CloseSignals(
closed,
type);
//
bool isClosed = ArraySize(closed) > 0;
if (isClosed)
{
XEU5IssueForceCloseTradesAlert(type);
}
}
}
//
// Open Long Position ...
bool XEU5OpenLongPosition(
XEU5Signal &info // Retrieve Signal Additional Info on this Object
)
{
//
bool result = false;
//
// Calculate Required Data for Position ...
double entry = GetEntry(_Symbol, X_SIGNAL_LONG);
double sl = info.sl > 0 ? info.sl : 0;
double tp = info.tp > 0 ? info.tp : entry + xEU5MinReward;
double riskFreeRate = xEU5RiskFreeRate;
double riskFreeStep = xEU5RiskFreeStepInPips;
double volume = XEU5CalculateVolume(ArraySize(info.signallers));
//
XSignal signal = {};
signal = xEU5Trader.GenerateSignal(
X_SIGNAL_LONG,
tp,
sl,
volume,
riskFreeStep,
riskFreeRate);
bool isValidSignal = IsValid(
signal,
xEU5MagicNumber);
if (!isValidSignal)
{
return result;
}
//
ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal(signal);
result = executionResult == X_TRADER_SUCCEED_EXECUTION;
if (result)
{
XEU5IssueSignalExecutionAlert(signal);
}
else
{
XEU5IssueSignalExecutionError(executionResult);
}
//
return result;
}
//
// Open Short Position ...
bool XEU5OpenShortPosition(
XEU5Signal &info // Retrieve Signal Additional Info on this Object
)
{
//
bool result = false;
//
// Calculate Required Data for Position ...
double entry = GetEntry(_Symbol, X_SIGNAL_SHORT);
double sl = info.sl > 0 ? info.sl : 0;
double tp = info.tp > 0 ? info.tp : entry - xEU5MinReward;
double riskFreeRate = xEU5RiskFreeRate;
double riskFreeStep = xEU5RiskFreeStepInPips;
double volume = XEU5CalculateVolume(ArraySize(info.signallers));
//
XSignal signal = {};
signal = xEU5Trader.GenerateSignal(
X_SIGNAL_SHORT,
tp,
sl,
volume,
riskFreeStep,
riskFreeRate);
bool isValidSignal = IsValid(
signal,
xEU5MagicNumber);
if (!isValidSignal)
{
return result;
}
//
ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal(signal);
result = executionResult == X_TRADER_SUCCEED_EXECUTION;
if (result)
{
XEU5IssueSignalExecutionAlert(signal);
}
else
{
XEU5IssueSignalExecutionError(executionResult);
}
//
return result;
}
//
// END Provided Functions ...
//
//
// START Private Functions ...
//
//
// START On Trade Context Handler ..
//
//
// Reset On Trade Scanner Context ...
void XEU5ResetOnTradeContext()
{
//
xEU5EndDate = TimeCurrent();
xEU5StartDate = xEU5EndDate - (xEU5DaysForRead * PeriodSeconds(PERIOD_D1));
}
//
// Initial Context Of Trade Scanner ...
void XEU5InitOnTradeContext()
{
//
ResetLastError();
//
// load history ...
bool selected = HistorySelect(xEU5StartDate, xEU5EndDate);
if (!selected)
{
//
LogMessage("XEU5 > Failed to Load OnTrade Context History ...");
//
return;
}
//
// get the current value ...
xEU5Orders = OrdersTotal();
xEU5Positions = PositionsTotal();
xEU5Deals = HistoryDealsTotal();
xEU5HistoryOrders = HistoryOrdersTotal();
//
xEU5ScanStarted = true;
}
//
// Process On Trade Context ...
void XEU5ProcessOnTradeContext()
{
//
xEU5EndDate = TimeCurrent();
//
ResetLastError();
//
// download trading history from the specified interval to the program cache ...
bool selected = HistorySelect(xEU5StartDate, xEU5EndDate);
if (!selected)
{
//
LogMessage("XEU5 > Failed to Load OnTrade Context History ...");
//
return;
}
//
// get the current values ...
int currOrders = OrdersTotal();
int currPositions = PositionsTotal();
int currDeals = HistoryDealsTotal();
int currHistoryOrders = HistoryOrdersTotal();
//
// Orders ...
// check if the number of active orders has been changed ...
if (currOrders != xEU5Orders)
{
//
// number of active orders has been changed ...
//
// update the value ...
xEU5Orders = currOrders;
}
//
// Positions ...
// changes in the number of open positions ...
if (currPositions != xEU5Positions)
{
//
// number of open positions has been changed ...
//
// update the value ...
xEU5Positions = currPositions;
}
//
// Deals ...
// changes in the number of deals in the trade history cache ...
if (currDeals != xEU5Deals)
{
//
// number of deals in the trade history cache has been changed ...
LogMessage("Handle New Deals: " + (string)TimeCurrent());
//
// update the value ...
xEU5Deals = currDeals;
}
//
// History Orders ...
// changes in the number of history orders in the trade history cache ...
if (currHistoryOrders != xEU5HistoryOrders)
{
//
// number of history orders in the trade history cache has been changed ...
//
// update the value ...
xEU5HistoryOrders = currHistoryOrders;
}
//
// checking if it is necessary to change the limits of the trade history to be requested in cache ...
XEU5CheckStartDateInTradeHistory();
}
//
// Check Statrt Date In Trade History ...
void XEU5CheckStartDateInTradeHistory()
{
//
// initial interval, if we were to start working right now ..
datetime currStart = TimeCurrent() - (xEU5DaysForRead * PeriodSeconds(PERIOD_D1));
//
// make sure that the start limit of the trade history has not gone
// more than 1 day over the intended date ...
if (currStart - xEU5StartDate > PeriodSeconds(PERIOD_D1))
{
//
// correct the start date of history to be loaded in the cache ...
xEU5StartDate = currStart;
//
// now reload the trade history for the updated interval ...
HistorySelect(xEU5StartDate, xEU5EndDate);
//
//--- correct the deal and order counters in history for further comparison
xEU5HistoryOrders = HistoryOrdersTotal();
xEU5Deals = HistoryDealsTotal();
}
}
//
// END On Trade Context Handler ..
//
//
// Calculate Account Grow Rate ...
double XEU5GetAccountGrowRate()
{
//
double result = 0;
//
result = xEU5Balance / xEU5Deposit;
result = MathRound(result);
//
return result;
}
//
// Calculate Base Volume Multiplier ...
double XEU5GetBaseVolumeMultiplier()
{
//
double result = xEU5VolumeMultiplier;
if (result <= 0)
{
result = 1;
}
//
double growRate = XEU5GetAccountGrowRate();
if (growRate > 1)
{
result *= growRate;
}
//
return result;
}
//
// Calculate Max Allowed Volume Per Trades ...
double XEU5GetMaxAllowedVolume()
{
//
double result = 0;
//
result =
xEU5MaxSupportedVolumePerTradeInLots > 0
? xEU5MaxSupportedVolumePerTradeInLots
: 1;
//
double growRate = XEU5GetAccountGrowRate();
double growMultipier =
xEU5VolumeMultiplier > 0
? MathRound(growRate / (xEU5VolumeMultiplier * 3))
: 1;
//
if (growMultipier > 5)
{
growMultipier = 5;
}
//
result *=
growMultipier > 1
? growMultipier
: 1;
//
return result;
}
//
// Calculating Volume for Tradings ...
double XEU5CalculateVolume(
double forceMultiplier = 0 // some times we get more than one signal at the same time, here we increase volume using this ...
)
{
//
double result = xEU5StaticVolume;
//
double volumeMultiplier =
xEU5VolumeMultiplier > 0
? XEU5GetBaseVolumeMultiplier()
: 1;
volumeMultiplier =
forceMultiplier > 0
? volumeMultiplier * forceMultiplier
: volumeMultiplier;
//
result *= volumeMultiplier;
//
// Check Open Trades ...
int openSignals = xEU5Trader.Count();
if (openSignals > 1)
{
//
// Decrease Volume if Open Trades Exists ...
double vDecreaseRate =
openSignals == 1
? 2
: openSignals;
//
result /= vDecreaseRate;
}
//
// Check Signal Max Allowed Volume ...
double maxAllowedVolume = XEU5GetMaxAllowedVolume();
//
result =
result < maxAllowedVolume
? result
: maxAllowedVolume;
//
// Normalize Volume ...
result = NormalizeVolume(result);
//
return result;
}
void XEU5IssueInitializationSucceedAlert()
{
//
string message = "Initializion of (" + XEU5ProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ...";
XEU5IssueAlert(message);
}
void XEU5IssueDeinitializationSucceedAlert()
{
//
string message = "De Initializion of (" + XEU5ProviderName + " Provider" + ") Succeeded ...";
XEU5IssueAlert(message);
}
void XEU5IssueForceCloseTradesAlert(ENUM_X_SIGNAL_TYPE type)
{
//
string typeStr = GetSignalType(type);
if (StringLen(typeStr) == 0)
{
return;
}
//
string message = "Force Close " + typeStr + " Trades ...";
XEU5IssueAlert(message);
}
void XEU5IssueMaxAllowedTradesReachedAlert()
{
//
string message = "reached Max Allowed Same Time Trades ...";
XEU5IssueAlert(message);
}
void XEU5IssueMaxAllowedFreeMarginReachedAlert()
{
//
string message = "reached FreeMarigin For Open Trades ...";
XEU5IssueAlert(message);
}
void XEU5IssueMinAllowedBalanceReachedAlert()
{
//
string message = "doesn't have Minimum Balance For Open Trades ...";
XEU5IssueAlert(message);
}
void XEU5IssueSignalExecutionAlert(
XSignal &signal // Executed Signal
)
{
//
XEU5IssueAlert(signal);
}
void XEU5IssueSignalExecutionError(int error)
{
//
string message = GetSignalExecutionError(error);
if (StringLen(message) == 0)
{
return;
}
//
XEU5IssueAlert(message);
}
void XEU5IssueRiskFreeTradesAlert()
{
//
string message = "Make Some Trades Risk Free ...";
XEU5IssueAlert(message);
}
void XEU5IssueLongInProfitTradeClosed()
{
//
string message = "Closed Long Time in Profit Trades ...";
XEU5IssueAlert(message);
}
void XEU5IssueLongInDrawdownTradeClosed()
{
//
string message = "Closed Long Time in Profit Trades ...";
XEU5IssueAlert(message);
}
void XEU5IssueAlert(string message)
{
//
if (xEU5EnableAlerts)
{
SendAlert(message);
}
else
{
LogMessage(message);
}
}
void XEU5IssueAlert(XSignal &signal)
{
//
string signalStr = xEU5Trader.ToString(signal);
XEU5IssueAlert(signalStr);
// //
// if (xEU5EnableAlerts)
// {
// SendAlert(signal);
// }
// else
// {
// LogSignal(signal);
// }
}
//
// END Private Functions ...
//