Files
xMQL5/BKPS/Projects/XTF-EA/Libraries/x-saherelm.xtf.provider.lib.mq5
2024-01-25 04:09:42 +03:30

1106 lines
23 KiB
Plaintext

////////////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 XTF Signal Provider Library
// --------------------------------------------------------
// Name: XTFSignalProvider
// Description: XTF 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 XTFProviderName "XTF"
//
// START Inputs ...
//
#include "x-saherelm.xtf.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 *xTFTrader;
XCAccountInfo xTFAccountInfo;
//
#include "x-saherelm.xtf.provider.indicators.lib.mq5"
//
double xTFDeposit = 0;
double xTFBalance = 0;
double xTFFreeMargin = 0;
double xTFRiskFreeTrades = 0;
double xTFMinRewardPerTrade = 0;
double xTFBalanceForOpenTrades = 0;
double xTFFreeMarginForOpenTrades = 0;
double xTFMinRewardPerSupportTrades = 0;
double xTFSupportTradesPriceDistance = 0;
double xTFMaxAllowedDrawDownPerTrades = 0;
//
// END Global Definitions: Variables, Properties and etc ...
//
//
// START Provided Functions ...
//
//
// Initial Library if required ...
bool XTFInitSignalProviderLibrary()
{
//
bool result = false;
//
// Validate Inputs ...
result = XTFValidateInputs();
if (!result)
{
return result;
}
//
// Init Indicators ...
result = XTFInitIndicators();
if (!result)
{
return result;
}
//
// Calculate Account Deposit ...
xTFDeposit = xTFAccountInfo.GetInitialBalance();
//
// Calculate RiskFree Price Distance ...
if (xTFRiskFreeTradesInPips > 0 && xTFRiskFreeRate > 0)
{
xTFRiskFreeTrades = PipsToPrice(xTFRiskFreeTradesInPips);
}
//
// Calculate xTFMinRewardPerTrade ...
if (xTFMinRewardPerTradeInPips > 0)
{
xTFMinRewardPerTrade = PipsToPrice(xTFMinRewardPerTradeInPips);
}
//
// Calculate Min Balance for Trades ...
if (xTFBalanceFactorForOpenTrades > 0)
{
xTFBalanceForOpenTrades = xTFBalanceFactorForOpenTrades * xTFDeposit;
}
//
// Claculate Min Free Marging for Trades ...
if (xTFFreeMarginFactorForOpenTrades > 0)
{
xTFFreeMarginForOpenTrades = xTFFreeMarginFactorForOpenTrades * xTFDeposit;
}
//
// Calculate xTFSupportTradesPriceDistance ...
if (xTFMaxAllowedSupportTrades > 0 && xTFSupportTradesPriceDistanceInPips > 0 && xTFMinRewardPerSupportTradesInPips > 0)
{
xTFMinRewardPerSupportTrades = PipsToPrice(xTFMinRewardPerSupportTradesInPips);
xTFSupportTradesPriceDistance = PipsToPrice(xTFSupportTradesPriceDistanceInPips);
}
//
// Calculate xTFMaxAllowedDrawDownPerTrade ...
if (xTFMaxAllowedDrawDownPerTradesInPips > 0)
{
//
xTFMaxAllowedDrawDownPerTrades = PipsToPrice(xTFMaxAllowedDrawDownPerTradesInPips);
//
LogMessage("Max Allowed DrawDown per Trade: " + (string)xTFMaxAllowedDrawDownPerTrades);
}
//
// Make XCTrader instance ...
xTFTrader = new XCTrade(
XTFProviderName,
_Symbol,
xTFSlippage,
xTFMagicNumber,
xTFMaxAllowedTrades,
xTFMaxAllowedSupportTrades,
xTFMinRewardPerTradeInPips,
xTFSupportTradesPriceDistanceInPips,
xTFFreeMarginForOpenTrades,
xTFBalanceForOpenTrades);
//
result = true;
//
// Logging State ...
XTFIssueInitializationSucceedAlert();
//
return result;
}
//
// DeInitial Library if required ...
void XTFDeinitSignalProviderLibrary(
const int reason)
{
//
// Release Handlers ...
XTFReleaseIndicators();
//
// Logging State ...
XTFIssueDeinitializationSucceedAlert();
}
//
// this is a Globally Function which do all of
// checkings and positions handling ...
void XTFSignalProviderHandleTick()
{
//
// Update account Balance ...
xTFBalance = xTFAccountInfo.GetBalance();
xTFFreeMargin = xTFAccountInfo.GetFreeMargin();
//
// Check Provider is Enable or Not ...
if (!xTFEnableProvider)
{
return;
}
//
// Reading Indicator Buffers ...
XTFHandleReadingBuffers();
if (xTFCalculatedBars < xTFMaxLengthOfInputs)
{
return;
}
//
// Handle Open Trades ...
XTFHandleOpenTrades();
//
// Handle Close Trades ...
XTFHandleCloseTrades();
//
// Handle Support Trades ...
XTFHandleSupportTrades();
}
//
// Handle Open Trades ...
void XTFHandleOpenTrades()
{
//
// Check Can Trade ...
bool canTrade = xTFAllowLongTrades || xTFAllowShortTrades;
if (!canTrade)
{
return;
}
//
// Check Max Open Trades ...
int openPositions = xTFTrader.Count();
int openTradeKinds = xTFTrader.CountByKind(
X_SIGNAL_UNKNOWN,
X_KIND_TRADE);
bool canOpenPositions = openTradeKinds < xTFMaxAllowedTrades;
if (!canOpenPositions)
{
return;
}
//
// Check Signals Exists ...
XTF_SIGNAL longInfo = {};
double longsForceVolume = 0;
XTF_SIGNAL shortInfo = {};
double shortsForceVolume = 0;
bool hasLongSignal = XTFCanOpenLongTrade(
longsForceVolume,
longInfo);
bool hasShortSignal = XTFCanOpenShortTrade(
shortsForceVolume,
shortInfo);
if (!hasLongSignal && !hasShortSignal)
{
return;
}
//
// Open Long Trades ...
if (
//
hasLongSignal &&
xTFAllowLongTrades)
{
//
bool isOpened = XTFOpenLongPosition(
longInfo,
longsForceVolume);
}
//
// Open Short Trades ...
if (
//
hasShortSignal &&
xTFAllowShortTrades)
{
//
bool isOpened = XTFOpenShortPosition(
shortInfo,
shortsForceVolume);
}
}
//
// Handle Close Trades ...
void XTFHandleCloseTrades()
{
//
// All Close Mechanism Handles Here ...
// - Force Close;
// - Partial Close;
// - Risk Free Close;
// - Virtual TP/SL Close;
//
// Force Close Long Trades ...
bool canCloseLongTrades = XTFCanCloseLongTrade();
if (xTFAllowLongTrades && canCloseLongTrades)
{
//
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_LONG;
//
XSignal closed[];
xTFTrader.ClosePositionsByType(
type,
closed);
//
bool isClosed = ArraySize(closed) > 0;
if (isClosed)
{
XTFIssueForceCloseTradesAlert(type);
}
}
//
// Force Close Short Trades ...
bool canCloseShortTrades = XTFCanCloseShortTrade();
if (xTFAllowShortTrades && canCloseShortTrades)
{
//
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_SHORT;
//
XSignal closed[];
xTFTrader.ClosePositionsByType(
type,
closed);
//
bool isClosed = ArraySize(closed) > 0;
if (isClosed)
{
XTFIssueForceCloseTradesAlert(type);
}
}
//
// Close Risk Free Trades ...
bool canRiskFree = xTFRiskFreeTradesInPips > 0 && xTFRiskFreeTrades > 0 && xTFRiskFreeRate > 0;
if (canRiskFree)
{
XSignal riskFrees[];
xTFTrader.RiskFreeSignals(riskFrees);
bool isRiskFree = ArraySize(riskFrees) > 0;
if (isRiskFree)
{
XTFIssueRiskFreeTradesAlert();
}
}
//
XTFHandleCloseMaxDrawDownTrades();
//
XTFHandleCloseTooOldTrades();
}
//
// Handle Supported Trades ...
void XTFHandleSupportTrades()
{
//
bool canDoTrade =
xTFMaxAllowedSupportTrades > 0 &&
xTFMinRewardPerSupportTradesInPips > 0 &&
xTFSupportTradesPriceDistanceInPips > 0;
if (!canDoTrade)
{
return;
}
//
XSignal supports[];
bool hasSupportTrade = XTFOpenSupportTrade(supports);
if (hasSupportTrade)
{
}
}
//
// Open Long Position ...
bool XTFOpenLongPosition(
XTF_SIGNAL &info, // Retrieve Signal Additional Info on this Object
double additionalVolumeMultiplier = 0)
{
//
bool result = false;
//
// Calculate Required Data for Position ...
double sl = info.sl > 0 ? info.sl : 0;
double tp = info.tp > 0 ? info.tp : xTFMinRewardPerTrade;
double riskFree = info.tp > 0 && info.riskFree > 0 ? info.riskFree : info.tp > 0 ? 0
: xTFRiskFreeTrades;
double riskFreeRate = xTFRiskFreeRate;
double volume = XTFCalculateVolume(additionalVolumeMultiplier);
//
XSignal signal = {};
signal = xTFTrader.GenerateTradeSignal(
X_SIGNAL_LONG,
tp,
sl,
volume,
riskFree,
riskFreeRate);
bool isValidSignal = IsValid(
signal,
xTFMagicNumber);
if (!isValidSignal)
{
return result;
}
//
int error = -1;
result = xTFTrader.ExecuteSignal(signal, error);
if (result)
{
XTFIssueSignalExecutionAlert(signal);
}
//
return result;
}
//
// Open Short Position ...
bool XTFOpenShortPosition(
XTF_SIGNAL &info, // Retrieve Signal Additional Info on this Object
double additionalVolumeMultiplier = 0)
{
//
bool result = false;
//
// Calculate Required Data for Position ...
double sl = info.sl > 0 ? info.sl : 0;
double tp = info.tp > 0 ? info.tp : xTFMinRewardPerTrade;
double riskFree = info.tp > 0 && info.riskFree > 0 ? info.riskFree : info.tp > 0 ? 0
: xTFRiskFreeTrades;
double riskFreeRate = xTFRiskFreeRate;
double volume = XTFCalculateVolume(additionalVolumeMultiplier);
//
XSignal signal = {};
signal = xTFTrader.GenerateTradeSignal(
X_SIGNAL_SHORT,
tp,
sl,
volume,
riskFree,
riskFreeRate);
bool isValidSignal = IsValid(
signal,
xTFMagicNumber);
if (!isValidSignal)
{
return result;
}
//
int error = -1;
result = xTFTrader.ExecuteSignal(signal, error);
if (result)
{
XTFIssueSignalExecutionAlert(signal);
}
//
return result;
}
//
// Open a Support Signal ...
bool XTFOpenSupportTrade(
XSignal &supports[] // Holds Result ...
)
{
//
bool result = false;
//
// Check Can Trade ...
result = xTFAllowLongTrades || xTFAllowShortTrades;
if (!result)
{
return result;
}
//
// Check Support Trades is Enable or not ...
bool isSupportTradesEnabled =
//
xTFMaxAllowedSupportTrades > 0 &&
xTFMinRewardPerSupportTrades > 0 &&
xTFSupportTradesPriceDistance > 0
//
;
if (!isSupportTradesEnabled)
{
return result;
}
//
// Recieve InDD Open Trades ...
XSignal inDDTrades[];
xTFTrader.GetInDrawDownTrades(
xTFSupportTradesPriceDistance,
X_SIGNAL_UNKNOWN,
X_KIND_TRADE,
inDDTrades);
int inDDTradesCount = ArraySize(inDDTrades);
result = inDDTradesCount > 0;
if (!result)
{
return result;
}
//
// Check Signals Exists ...
double longsForceVolume = 0;
XTF_SIGNAL longInfo = {};
double shortsForceVolume = 0;
XTF_SIGNAL shortInfo = {};
bool hasLongSignal = XTFCanOpenLongTrade(
longsForceVolume,
longInfo);
bool hasShortSignal = XTFCanOpenShortTrade(
shortsForceVolume,
shortInfo);
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 = XTFGenerateSupportSignal(
longsForceVolume,
X_SIGNAL_LONG,
parent);
//
// Validate it ...
bool isValidSupport = IsValid(sSignal, xTFMagicNumber);
if (!isValidSupport)
{
continue;
;
}
//
// Try To Execute Support Signal ...
int error = 0;
bool isExecuted = xTFTrader.ExecuteSupportSignal(
sSignal,
error);
if (isExecuted)
{
//
if (!result)
{
result = true;
}
//
Add(
sSignal,
supports);
//
XTFIssueSignalExecutionAlert(sSignal);
}
//
continue;
}
//
// Check if Short Signal Happens ...
if (hasShortSignal && parent.type == X_SIGNAL_SHORT)
{
//
// Generate Support Signal ...
XSignal sSignal = XTFGenerateSupportSignal(
shortsForceVolume,
X_SIGNAL_SHORT,
parent);
//
// Validate it ...
bool isValidSupport = IsValid(sSignal, xTFMagicNumber);
if (!isValidSupport)
{
continue;
;
}
//
// Try To Execute Support Signal ...
int error = 0;
bool isExecuted = xTFTrader.ExecuteSupportSignal(
sSignal,
error);
if (isExecuted)
{
//
if (!result)
{
result = true;
}
//
Add(
sSignal,
supports);
//
XTFIssueSignalExecutionAlert(sSignal);
}
//
continue;
}
}
//
return result;
}
//
// Close All InDrawDown Trades ...
void XTFHandleCloseMaxDrawDownTrades()
{
//
if (xTFMaxAllowedDrawDownPerTrades > 0)
{
//
XSignal closed[];
xTFTrader.CloseInDrawDownTrades(
xTFMaxAllowedDrawDownPerTrades,
closed);
//
int count = ArraySize(closed);
if (count > 0)
{
XTFIssueLongInDrawdownTradeClosed();
}
}
}
//
// Close All Too Old Trades ...
void XTFHandleCloseTooOldTrades()
{
//
// in DrawDown Trades ...
if (xTFMaxInDrawDownTradeAge > 0)
{
//
XSignal oldTrades[];
xTFTrader.CloseLongTimeTrades(
xTFMaxInDrawDownTradeAge,
_Period,
oldTrades);
//
bool hasOldClosedTrades = ArraySize(oldTrades) > 0;
if (hasOldClosedTrades)
{
//
LogMessage("Old Trade Closed ...");
}
}
}
//
// END Provided Functions ...
//
//
// START Private Functions ...
//
//
// Calculating Volume for Tradings ...
double XTFCalculateVolume(
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 = xTFStaticVolume;
//
// we can count open trades and in draw down trades
// then do check volume based on it for gridding ...
XSignal openInProfitTrades[];
xTFTrader.GetInProfitTrades(
0,
X_SIGNAL_UNKNOWN,
X_KIND_TRADE,
openInProfitTrades);
int openTrades = ArraySize(openInProfitTrades);
//
// Calculate Normalized Multiplier ...
double mVolumeMultiplier = xTFVolumeMultiplier <= 0 ? 1 : xTFVolumeMultiplier;
double multiplier = mVolumeMultiplier;
multiplier = multiplier * openTrades;
if (multiplier < 1)
{
multiplier = 1;
}
//
double growRate = xTFBalance / xTFDeposit;
if (growRate >= 1 && multiplier == 1)
{
//
double growDiff = growRate - 1;
if (growDiff < 1)
{
growRate = 1 + (growDiff * mVolumeMultiplier);
}
//
multiplier = multiplier * growRate;
}
//
result = multiplier * xTFStaticVolume;
//
// Apply Force Multiplier ...
if (forceMultiplier > 1)
{
result *= forceMultiplier;
}
//
// Check Max Allowed Lottage ...
double maxAllowedVolume = xTFMaxSupportedVolumePerTradeInLots;
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 XTFCalculateTPSL(
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(xTFMinRewardPerTradeInPips) + 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 XTFGenerateSupportSignal(
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, xTFMagicNumber);
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 = xTFRiskFreeRate > 0;
//
// TP ...
double tp = MathAbs(parent.tp - parent.entry) / 2;
// PriceToPips(MathAbs(parent.tp - parent.entry) / 2);
if (tp <= xTFMinRewardPerSupportTrades)
{
tp = xTFMinRewardPerSupportTrades;
}
else if (
canRiskFree &&
tp > xTFMinRewardPerSupportTrades)
{
//
// Fill Risk Free Info ...
riskFreeRate = xTFRiskFreeRate;
riskFreePrice =
isLong ? xTFMinRewardPerSupportTrades : xTFMinRewardPerSupportTrades;
}
//
// SL ...
double sl = isLong ? 0 : 0;
//
// VOLUME ...
int pOpenSupportCount = xTFTrader.CountSupportedPositions(parent);
double volume = parent.volume * forceVolumeMultiplier;
//
// Check and Normalize Volume based on MaxAllowed Volume ...
if (xTFMaxSupportedVolumePerTradeInLots > 0 && volume > xTFMaxSupportedVolumePerTradeInLots)
{
volume = xTFMaxSupportedVolumePerTradeInLots;
}
//
// Normalize Volume ...
volume = NormalizeVolume(volume);
//
// Generating Support Signal for Parent ...
result = xTFTrader.GenerateSupportSignal(
type,
tp,
sl,
volume,
riskFreePrice,
riskFreeRate,
parent.ticket);
//
// TODO: Fix this ...
result.tp = parent.tp;
result.sl = parent.sl;
result.riskFree = 0;
result.riskFreeRate = 0;
//
return result;
}
void XTFIssueInitializationSucceedAlert()
{
//
string message = "Initializion of (" + XTFProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ...";
XTFIssueAlert(message);
}
void XTFIssueDeinitializationSucceedAlert()
{
//
string message = "De Initializion of (" + XTFProviderName + " Provider" + ") Succeeded ...";
XTFIssueAlert(message);
}
void XTFIssueForceCloseTradesAlert(ENUM_X_SIGNAL_TYPE type)
{
//
string typeStr = GetSignalType(type);
if (StringLen(typeStr) == 0)
{
return;
}
//
string message = "Force Close " + typeStr + " Trades ...";
XTFIssueAlert(message);
}
void XTFIssueMaxAllowedTradesReachedAlert()
{
//
string message = "reached Max Allowed Same Time Trades ...";
XTFIssueAlert(message);
}
void XTFIssueMaxAllowedFreeMarginReachedAlert()
{
//
string message = "reached FreeMarigin For Open Trades ...";
XTFIssueAlert(message);
}
void XTFIssueMinAllowedBalanceReachedAlert()
{
//
string message = "doesn't have Minimum Balance For Open Trades ...";
XTFIssueAlert(message);
}
void XTFIssueSignalExecutionAlert(
XSignal &signal // Executed Signal
)
{
//
XTFIssueAlert(signal);
}
void XTFIssueSignalExecutionError(int error)
{
//
string message = GetSignalExecutionError(error);
if (StringLen(message) == 0)
{
return;
}
//
XTFIssueAlert(message);
}
void XTFIssueRiskFreeTradesAlert()
{
//
string message = "Make Some Trades Risk Free ...";
XTFIssueAlert(message);
}
void XTFIssueLongInProfitTradeClosed()
{
//
string message = "Closed Long Time in Profit Trades ...";
XTFIssueAlert(message);
}
void XTFIssueLongInDrawdownTradeClosed()
{
//
string message = "Closed Long Time in Profit Trades ...";
XTFIssueAlert(message);
}
void XTFIssueAlert(string message)
{
//
if (xTFEnableAlerts)
{
SendAlert(message);
}
else
{
LogMessage(message);
}
}
void XTFIssueAlert(XSignal &signal)
{
//
string signalStr = xTFTrader.ToString(signal);
XTFIssueAlert(signalStr);
// //
// if (xTFEnableAlerts)
// {
// SendAlert(signal);
// }
// else
// {
// LogSignal(signal);
// }
}
//
// END Private Functions ...
//