Files
xEaPacks/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtest.provider.lib.mq5
T
2024-01-25 04:08:38 +03:30

1074 lines
23 KiB
Plaintext

////////////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 XTEST Signal Provider Library
// --------------------------------------------------------
// Name: XTESTSignalProvider
// Description: XTEST 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 XTESTProviderName "XTEST"
//
// START Inputs ...
//
#include "x-saherelm.xtest.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 *xTESTTrader;
XCAccountInfo xTESTAccountInfo;
//
#include "x-saherelm.xtest.provider.indicators.lib.mq5"
//
double xTESTDeposit = 0;
double xTESTBalance = 0;
double xTESTFreeMargin = 0;
double xTESTRiskFreeTrades = 0;
double xTESTMinRewardPerTrade = 0;
double xTESTBalanceForOpenTrades = 0;
double xTESTFreeMarginForOpenTrades = 0;
double xTESTMinRewardPerSupportTrades = 0;
double xTESTSupportTradesPriceDistance = 0;
double xTESTMaxAllowedDrawDownPerTrades = 0;
//
// END Global Definitions: Variables, Properties and etc ...
//
//
// START Provided Functions ...
//
//
// Initial Library if required ...
bool XTESTInitSignalProviderLibrary()
{
//
bool result = false;
//
// Validate Inputs ...
result = XTESTValidateInputs();
if (!result)
{
return result;
}
//
// Init Indicators ...
result = XTESTInitIndicators();
if (!result)
{
return result;
}
//
// Calculate Account Deposit ...
xTESTDeposit = xTESTAccountInfo.GetInitialBalance();
//
// Calculate RiskFree Price Distance ...
if (xTESTRiskFreeTradesInPips > 0 && xTESTRiskFreeRate > 0)
{
xTESTRiskFreeTrades = PipsToPrice(xTESTRiskFreeTradesInPips);
}
//
// Calculate xTESTMinRewardPerTrade ...
if (xTESTMinRewardPerTradeInPips > 0)
{
xTESTMinRewardPerTrade = PipsToPrice(xTESTMinRewardPerTradeInPips);
}
//
// Calculate Min Balance for Trades ...
if (xTESTBalanceFactorForOpenTrades > 0)
{
xTESTBalanceForOpenTrades = xTESTBalanceFactorForOpenTrades * xTESTDeposit;
}
//
// Claculate Min Free Marging for Trades ...
if (xTESTFreeMarginFactorForOpenTrades > 0)
{
xTESTFreeMarginForOpenTrades = xTESTFreeMarginFactorForOpenTrades * xTESTDeposit;
}
//
// Calculate xTESTSupportTradesPriceDistance ...
if (xTESTMaxAllowedSupportTrades > 0 && xTESTSupportTradesPriceDistanceInPips > 0 && xTESTMinRewardPerSupportTradesInPips > 0)
{
xTESTMinRewardPerSupportTrades = PipsToPrice(xTESTMinRewardPerSupportTradesInPips);
xTESTSupportTradesPriceDistance = PipsToPrice(xTESTSupportTradesPriceDistanceInPips);
}
//
// Calculate xTESTMaxAllowedDrawDownPerTrade ...
if (xTESTMaxAllowedDrawDownPerTradesInPips > 0)
{
//
xTESTMaxAllowedDrawDownPerTrades = PipsToPrice(xTESTMaxAllowedDrawDownPerTradesInPips);
//
LogMessage("Max Allowed DrawDown per Trade: " + (string)xTESTMaxAllowedDrawDownPerTrades);
}
//
// Make XCTrader instance ...
xTESTTrader = new XCTrade(
XTESTProviderName,
_Symbol,
xTESTSlippage,
xTESTMagicNumber,
xTESTMaxAllowedTrades,
xTESTMaxAllowedSupportTrades,
xTESTMinRewardPerTradeInPips,
xTESTSupportTradesPriceDistanceInPips,
xTESTFreeMarginForOpenTrades,
xTESTBalanceForOpenTrades);
//
result = true;
//
// Logging State ...
XTESTIssueInitializationSucceedAlert();
//
return result;
}
//
// DeInitial Library if required ...
void XTESTDeinitSignalProviderLibrary(
const int reason)
{
//
// Release Handlers ...
XTESTReleaseIndicators();
//
// Logging State ...
XTESTIssueDeinitializationSucceedAlert();
}
//
// this is a Globally Function which do all of
// checkings and positions handling ...
void XTESTSignalProviderHandleTick()
{
//
// Update account Balance ...
xTESTBalance = xTESTAccountInfo.GetBalance();
xTESTFreeMargin = xTESTAccountInfo.GetFreeMargin();
//
// Check Provider is Enable or Not ...
if (!xTESTEnableProvider)
{
return;
}
//
// Reading Indicator Buffers ...
XTESTHandleReadingBuffers();
if (xTESTCalculatedBars < xTESTMaxLengthOfInputs)
{
return;
}
//
// Handle Open Trades ...
XTESTHandleOpenTrades();
//
// Handle Close Trades ...
XTESTHandleCloseTrades();
//
// Handle Support Trades ...
XTESTHandleSupportTrades();
}
//
// Handle Open Trades ...
void XTESTHandleOpenTrades()
{
//
// Check Can Trade ...
bool canTrade = xTESTAllowLongTrades || xTESTAllowShortTrades;
if (!canTrade)
{
return;
}
//
// Check Max Open Trades ...
int openPositions = xTESTTrader.Count();
int openTradeKinds = xTESTTrader.CountByKind(
X_SIGNAL_UNKNOWN,
X_KIND_TRADE);
bool canOpenPositions = openTradeKinds < xTESTMaxAllowedTrades;
if (!canOpenPositions)
{
return;
}
//
// Check Signals Exists ...
double longsForceVolume = 0;
double shortsForceVolume = 0;
bool hasLongSignal = XTESTCanOpenLongTrade(longsForceVolume);
bool hasShortSignal = XTESTCanOpenShortTrade(shortsForceVolume);
if (!hasLongSignal && !hasShortSignal)
{
return;
}
//
// Open Long Trades ...
if (
//
hasLongSignal &&
xTESTAllowLongTrades)
{
//
bool isOpened = XTESTOpenLongPosition(longsForceVolume);
}
//
// Open Short Trades ...
if (
//
hasShortSignal &&
xTESTAllowShortTrades)
{
//
bool isOpened = XTESTOpenShortPosition(shortsForceVolume);
}
}
//
// Handle Close Trades ...
void XTESTHandleCloseTrades()
{
//
// All Close Mechanism Handles Here ...
// - Force Close;
// - Partial Close;
// - Risk Free Close;
// - Virtual TP/SL Close;
//
// Force Close Long Trades ...
bool canCloseLongTrades = XTESTCanCloseLongTrade();
if (xTESTAllowLongTrades && canCloseLongTrades)
{
//
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_LONG;
//
XSignal closed[];
xTESTTrader.ClosePositionsByType(
type,
closed);
//
bool isClosed = ArraySize(closed) > 0;
if (isClosed)
{
XTESTIssueForceCloseTradesAlert(type);
}
}
//
// Force Close Short Trades ...
bool canCloseShortTrades = XTESTCanCloseShortTrade();
if (xTESTAllowShortTrades && canCloseShortTrades)
{
//
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_SHORT;
//
XSignal closed[];
xTESTTrader.ClosePositionsByType(
type,
closed);
//
bool isClosed = ArraySize(closed) > 0;
if (isClosed)
{
XTESTIssueForceCloseTradesAlert(type);
}
}
//
// Close Risk Free Trades ...
bool canRiskFree = xTESTRiskFreeTradesInPips > 0 && xTESTRiskFreeTrades > 0 && xTESTRiskFreeRate > 0;
if (canRiskFree)
{
XSignal riskFrees[];
xTESTTrader.RiskFreeSignals(riskFrees);
bool isRiskFree = ArraySize(riskFrees) > 0;
if (isRiskFree)
{
XTESTIssueRiskFreeTradesAlert();
}
}
//
XTESTHandleCloseMaxDrawDownTrades();
//
XTESTHandleCloseTooOldTrades();
}
//
// Handle Supported Trades ...
void XTESTHandleSupportTrades()
{
//
bool canDoTrade =
xTESTMaxAllowedSupportTrades > 0 &&
xTESTMinRewardPerSupportTradesInPips > 0 &&
xTESTSupportTradesPriceDistanceInPips > 0;
if (!canDoTrade)
{
return;
}
//
XSignal supports[];
bool hasSupportTrade = XTESTOpenSupportTrade(supports);
if (hasSupportTrade)
{
}
}
//
// Open Long Position ...
bool XTESTOpenLongPosition(double additionalVolumeMultiplier = 0)
{
//
bool result = false;
//
// Calculate Required Data for Position ...
double sl = 0;
double tp = xTESTMinRewardPerTrade;
double riskFree = xTESTRiskFreeTrades;
double riskFreeRate = xTESTRiskFreeRate;
double volume = XTESTCalculateVolume(additionalVolumeMultiplier);
//
XSignal signal = {};
signal = xTESTTrader.GenerateTradeSignal(
X_SIGNAL_LONG,
tp,
sl,
volume,
riskFree,
riskFreeRate);
bool isValidSignal = IsValid(
signal,
xTESTMagicNumber);
if (!isValidSignal)
{
return result;
}
//
int error = -1;
result = xTESTTrader.ExecuteSignal(signal, error);
if (result)
{
XTESTIssueSignalExecutionAlert(signal);
}
//
return result;
}
//
// Open Short Position ...
bool XTESTOpenShortPosition(double additionalVolumeMultiplier = 0)
{
//
bool result = false;
//
// Calculate Required Data for Position ...
double sl = 0;
double tp = xTESTMinRewardPerTrade;
double riskFree = xTESTRiskFreeTrades;
double riskFreeRate = xTESTRiskFreeRate;
double volume = XTESTCalculateVolume(additionalVolumeMultiplier);
//
XSignal signal = {};
signal = xTESTTrader.GenerateTradeSignal(
X_SIGNAL_SHORT,
tp,
sl,
volume,
riskFree,
riskFreeRate);
bool isValidSignal = IsValid(
signal,
xTESTMagicNumber);
if (!isValidSignal)
{
return result;
}
//
int error = -1;
result = xTESTTrader.ExecuteSignal(signal, error);
if (result)
{
XTESTIssueSignalExecutionAlert(signal);
}
//
return result;
}
//
// Open a Support Signal ...
bool XTESTOpenSupportTrade(
XSignal &supports[] // Holds Result ...
)
{
//
bool result = false;
//
// Check Can Trade ...
result = xTESTAllowLongTrades || xTESTAllowShortTrades;
if (!result)
{
return result;
}
//
// Check Support Trades is Enable or not ...
bool isSupportTradesEnabled =
//
xTESTMaxAllowedSupportTrades > 0 &&
xTESTMinRewardPerSupportTrades > 0 &&
xTESTSupportTradesPriceDistance > 0
//
;
if (!isSupportTradesEnabled)
{
return result;
}
//
// Recieve InDD Open Trades ...
XSignal inDDTrades[];
xTESTTrader.GetInDrawDownTrades(
xTESTSupportTradesPriceDistance,
X_SIGNAL_UNKNOWN,
X_KIND_TRADE,
inDDTrades);
int inDDTradesCount = ArraySize(inDDTrades);
result = inDDTradesCount > 0;
if (!result)
{
return result;
}
//
// Check Signals Exists ...
double longsForceVolume = 0;
double shortsForceVolume = 0;
bool hasLongSignal = XTESTCanOpenLongTrade(longsForceVolume);
bool hasShortSignal = XTESTCanOpenShortTrade(shortsForceVolume);
result = hasLongSignal || hasShortSignal;
if (!result)
{
return result;
}
//
// Loop Through In DrawDown Trades ...
XSignal supportedSignals[];
for (int i = 0; i < inDDTradesCount; i++)
{
//
// Retrieve Parent Signal ...
XSignal parent = inDDTrades[i];
//
// Check if Long Signal Happens ...
if (hasLongSignal && parent.type == X_SIGNAL_LONG)
{
//
// Generate Support Signal ...
XSignal sSignal = GenerateSupportSignal(
longsForceVolume,
X_SIGNAL_LONG,
parent);
//
// Validate it ...
bool isValidSupport = IsValid(sSignal, xTESTMagicNumber);
if (!isValidSupport)
{
continue;
;
}
//
// Try To Execute Support Signal ...
int error = 0;
bool isExecuted = xTESTTrader.ExecuteSupportSignal(
sSignal,
error);
if (isExecuted)
{
//
if (!result)
{
result = true;
}
//
Add(
sSignal,
supports);
//
XTESTIssueSignalExecutionAlert(sSignal);
}
//
continue;
}
//
// Check if Short Signal Happens ...
if (hasShortSignal && parent.type == X_SIGNAL_SHORT)
{
//
// Generate Support Signal ...
XSignal sSignal = GenerateSupportSignal(
shortsForceVolume,
X_SIGNAL_SHORT,
parent);
//
// Validate it ...
bool isValidSupport = IsValid(sSignal, xTESTMagicNumber);
if (!isValidSupport)
{
continue;
;
}
//
// Try To Execute Support Signal ...
int error = 0;
bool isExecuted = xTESTTrader.ExecuteSupportSignal(
sSignal,
error);
if (isExecuted)
{
//
if (!result)
{
result = true;
}
//
Add(
sSignal,
supports);
//
XTESTIssueSignalExecutionAlert(sSignal);
}
//
continue;
}
}
//
return result;
}
//
// Close All InDrawDown Trades ...
void XTESTHandleCloseMaxDrawDownTrades()
{
//
if (xTESTMaxAllowedDrawDownPerTrades > 0)
{
//
XSignal closed[];
xTESTTrader.CloseInDrawDownTrades(
xTESTMaxAllowedDrawDownPerTrades,
closed);
//
int count = ArraySize(closed);
if (count > 0)
{
XTESTIssueLongInDrawdownTradeClosed();
}
}
}
//
// Close All Too Old Trades ...
void XTESTHandleCloseTooOldTrades()
{
//
// in DrawDown Trades ...
if (xTESTMaxInDrawDownTradeAge > 0)
{
//
XSignal oldTrades[];
xTESTTrader.CloseLongTimeTrades(
xTESTMaxInDrawDownTradeAge,
_Period,
oldTrades);
//
bool hasOldClosedTrades = ArraySize(oldTrades) > 0;
if (hasOldClosedTrades)
{
//
LogMessage("Old Trade Closed ...");
}
}
}
//
// END Provided Functions ...
//
//
// START Private Functions ...
//
//
// Calculating Volume for Tradings ...
double XTESTCalculateVolume(
double forceMultiplier = 0 // some times we get more than one signal at the same time, here we increase volume using this ...
)
{
//
// Assign default Value ...
double result = xTESTStaticVolume;
//
// we can count open trades and in draw down trades
// then do check volume based on it for gridding ...
XSignal openInProfitTrades[];
xTESTTrader.GetInProfitTrades(
0,
X_SIGNAL_UNKNOWN,
X_KIND_TRADE,
openInProfitTrades);
int openTrades = ArraySize(openInProfitTrades);
//
// Calculate Normalized Multiplier ...
double mVolumeMultiplier = xTESTVolumeMultiplier <= 0 ? 1 : xTESTVolumeMultiplier;
double multiplier = mVolumeMultiplier;
multiplier = multiplier * openTrades;
if (multiplier < 1)
{
multiplier = 1;
}
//
double growRate = xTESTBalance / xTESTDeposit;
if (growRate >= 1 && multiplier == 1)
{
//
double growDiff = growRate - 1;
if (growDiff < 1)
{
growRate = 1 + (growDiff * mVolumeMultiplier);
}
//
multiplier = multiplier * growRate;
}
//
result = multiplier * xTESTStaticVolume;
//
// Apply Force Multiplier ...
if (forceMultiplier > 1) {
result *= forceMultiplier;
}
//
// Check Max Allowed Lottage ...
double maxAllowedVolume = xTESTMaxSupportedVolumePerTradeInLots;
if (growRate >= 4 * mVolumeMultiplier) {
maxAllowedVolume *= mVolumeMultiplier;
}
//
if (
maxAllowedVolume > 0 &&
result > maxAllowedVolume)
{
result = maxAllowedVolume;
}
//
// Normalize Volume ...
result = NormalizeVolume(result);
//
return result;
}
//
// Calculate Signal TP and SL ...
XTPSL XTESTCalculateTPSL(
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(xTESTMinRewardPerTradeInPips) + 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;
}
//
// Generate Support Signal for Specific Trade ...
XSignal GenerateSupportSignal(
double forceVolumeMultiplier, // how many time increase volume based on signal providers
ENUM_X_SIGNAL_TYPE type, // which type of support signal issued
XSignal &parent // generate support signal for which Trade Kind Position
)
{
//
XSignal result = {};
//
// Validate Type ...
bool isTypeValid = type == X_SIGNAL_LONG || type == X_SIGNAL_SHORT;
if (!isTypeValid)
{
return result;
}
//
// Validate Parent Signal ...
bool isValidSignal = IsValid(parent, xTESTMagicNumber);
if (!isValidSignal)
{
return result;
}
//
// Validate Parent is Kind ...
bool isKindValid = parent.kind == X_KIND_TRADE;
if (!isKindValid)
{
return result;
}
//
// Check Parent Ticket ...
bool isValidTicket = parent.ticket > 0;
if (!isValidTicket)
{
return result;
}
//
// Validate DrawDown ...
bool isInDD = parent.profit < 0;
if (!isInDD)
{
return result;
}
//
// Calculate What we Want ...
//
bool isLong = type == X_SIGNAL_LONG;
//
// Entry Price ...
// double entry = GetEntry(parent.symbol, type);
//
// Required for Calculating RiskFree Level of Support Signals ...
double riskFreeRate = 0;
double riskFreePrice = 0;
bool canRiskFree = xTESTRiskFreeRate > 0;
//
// TP ...
double tp = MathAbs(parent.tp - parent.entry) / 2;
// PriceToPips(MathAbs(parent.tp - parent.entry) / 2);
if (tp <= xTESTMinRewardPerSupportTrades)
{
tp = xTESTMinRewardPerSupportTrades;
}
else if (
canRiskFree &&
tp > xTESTMinRewardPerSupportTrades)
{
//
// Fill Risk Free Info ...
riskFreeRate = xTESTRiskFreeRate;
riskFreePrice =
isLong ? xTESTMinRewardPerSupportTrades : xTESTMinRewardPerSupportTrades;
}
//
// SL ...
double sl = isLong ? 0 : 0;
//
// VOLUME ...
int pOpenSupportCount = xTESTTrader.CountSupportedPositions(parent);
double volume = parent.volume * forceVolumeMultiplier;
//
// Check and Normalize Volume based on MaxAllowed Volume ...
if (xTESTMaxSupportedVolumePerTradeInLots > 0 && volume > xTESTMaxSupportedVolumePerTradeInLots) {
volume = xTESTMaxSupportedVolumePerTradeInLots;
}
//
// Normalize Volume ...
volume = NormalizeVolume(volume);
//
// Generating Support Signal for Parent ...
result = xTESTTrader.GenerateSupportSignal(
type,
tp,
sl,
volume,
riskFreePrice,
riskFreeRate,
parent.ticket);
//
return result;
}
void XTESTIssueInitializationSucceedAlert()
{
//
string message = "Initializion of (" + XTESTProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ...";
XTESTIssueAlert(message);
}
void XTESTIssueDeinitializationSucceedAlert()
{
//
string message = "De Initializion of (" + XTESTProviderName + " Provider" + ") Succeeded ...";
XTESTIssueAlert(message);
}
void XTESTIssueForceCloseTradesAlert(ENUM_X_SIGNAL_TYPE type)
{
//
string typeStr = GetSignalType(type);
if (StringLen(typeStr) == 0)
{
return;
}
//
string message = "Force Close " + typeStr + " Trades ...";
XTESTIssueAlert(message);
}
void XTESTIssueMaxAllowedTradesReachedAlert()
{
//
string message = "reached Max Allowed Same Time Trades ...";
XTESTIssueAlert(message);
}
void XTESTIssueMaxAllowedFreeMarginReachedAlert()
{
//
string message = "reached FreeMarigin For Open Trades ...";
XTESTIssueAlert(message);
}
void XTESTIssueMinAllowedBalanceReachedAlert()
{
//
string message = "doesn't have Minimum Balance For Open Trades ...";
XTESTIssueAlert(message);
}
void XTESTIssueSignalExecutionAlert(
XSignal &signal // Executed Signal
)
{
//
XTESTIssueAlert(signal);
}
void XTESTIssueSignalExecutionError(int error)
{
//
string message = GetSignalExecutionError(error);
if (StringLen(message) == 0)
{
return;
}
//
XTESTIssueAlert(message);
}
void XTESTIssueRiskFreeTradesAlert()
{
//
string message = "Make Some Trades Risk Free ...";
XTESTIssueAlert(message);
}
void XTESTIssueLongInProfitTradeClosed()
{
//
string message = "Closed Long Time in Profit Trades ...";
XTESTIssueAlert(message);
}
void XTESTIssueLongInDrawdownTradeClosed()
{
//
string message = "Closed Long Time in Profit Trades ...";
XTESTIssueAlert(message);
}
void XTESTIssueAlert(string message)
{
//
if (xTESTEnableAlerts)
{
SendAlert(message);
}
else
{
LogMessage(message);
}
}
void XTESTIssueAlert(XSignal &signal)
{
//
string signalStr = xTESTTrader.ToString(signal);
XTESTIssueAlert(signalStr);
// //
// if (xTESTEnableAlerts)
// {
// SendAlert(signal);
// }
// else
// {
// LogSignal(signal);
// }
}
//
// END Private Functions ...
//