1106 lines
23 KiB
Plaintext
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 ...
|
|
//
|