1816 lines
40 KiB
Plaintext
1816 lines
40 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;
|
|
XCReporter *xEU5Reporter;
|
|
XCAccountInfo xEU5AccountInfo;
|
|
|
|
//
|
|
#include "x-saherelm.xeu5.provider.indicators.lib.mq5"
|
|
|
|
//
|
|
// Controlling Variables ...
|
|
bool xEU5MEnableProvider = false;
|
|
bool xEU5MAllowLongTrades = false;
|
|
bool xEU5MAllowShortTrades = false;
|
|
|
|
//
|
|
double xEU5Deposit = 0;
|
|
double xEU5Balance = 0;
|
|
double xEU5MinReward = 0;
|
|
double xEU5FreeMargin = 0;
|
|
double xEU5StaticVolume = 0;
|
|
double xEU5MaxAllowedVolume = 0;
|
|
double xEU5BalanceForOpenTrades = 0;
|
|
double xEU5FreeMarginForOpenTrades = 0;
|
|
double xEU5ApplyVolumeMultiplierPrice = 0;
|
|
|
|
//
|
|
// TODO: Complete this ...
|
|
// Buffer for Holding Max Volume and Max Drawdow ...
|
|
double xEU5MaxDrawUp = 0;
|
|
double xEU5MaxDrawDown = 0;
|
|
datetime xEU5TradeTimes[];
|
|
double xEU5TradeVolumes[];
|
|
double xEU5TradeMaxDrawdowns[];
|
|
double xEU5TradeMaxAllowdVolumes[];
|
|
double xEU5MinBalanceForTradePrices[];
|
|
|
|
//
|
|
int NOT_ENOUGH_MONEY_ERROR = 4756;
|
|
const string XEU5_SUPPORT_ID = "SP";
|
|
|
|
//
|
|
// 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;
|
|
|
|
//
|
|
if (!xEU5EnableProvider)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Controlling Variables ...
|
|
xEU5MEnableProvider = xEU5EnableProvider;
|
|
xEU5MAllowLongTrades = xEU5AllowLongTrades;
|
|
xEU5MAllowShortTrades = xEU5AllowShortTrades;
|
|
|
|
//
|
|
// 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 Volume Multiplier Apply Grow Price ...
|
|
if (xEU5ApplyVolumeMultiplierFactor > 0)
|
|
{
|
|
xEU5ApplyVolumeMultiplierPrice = xEU5Deposit * xEU5ApplyVolumeMultiplierFactor;
|
|
}
|
|
|
|
//
|
|
XEU5CalculateStaticVolume();
|
|
XEU5CalculateMaxAllowedVolume();
|
|
|
|
//
|
|
// Reset Calculations Buffers and Variables ...
|
|
XEU5ResetCollectors();
|
|
|
|
//
|
|
// Make XCTrader instance ...
|
|
xEU5Trader = new XCTrade(
|
|
XEU5ProviderName,
|
|
_Symbol,
|
|
xEU5Slippage,
|
|
xEU5MagicNumber,
|
|
xEU5MaxAllowedTrades,
|
|
xEU5FreeMarginForOpenTrades,
|
|
xEU5BalanceForOpenTrades);
|
|
|
|
//
|
|
// Retrieve an Instance of Reporter Class ...
|
|
xEU5Reporter = new XCReporter();
|
|
xEU5Reporter.ResetReports();
|
|
XEU5UpdateReports();
|
|
|
|
//
|
|
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 (!xEU5MEnableProvider)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Handling Signals ...
|
|
XTraderHandlerResult handleSignalResult;
|
|
xEU5Trader.HandleSignals(
|
|
handleSignalResult,
|
|
true, // Ignore Signal TP and SL for Virtal Handling
|
|
false // Ignore Risk Free Trdaes
|
|
);
|
|
//
|
|
// Handle Sl Reports ...
|
|
int handledSLsCount = ArraySize(handleSignalResult.sl);
|
|
if (handledSLsCount > 0)
|
|
{
|
|
//
|
|
for (int i = 0; i < handledSLsCount; i++)
|
|
{
|
|
xEU5Reporter.AddTradeSLInReports();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle TP Reports ...
|
|
int handledTPsCount = ArraySize(handleSignalResult.tp);
|
|
if (handledTPsCount > 0)
|
|
{
|
|
//
|
|
for (int i = 0; i < handledTPsCount; i++)
|
|
{
|
|
xEU5Reporter.AddTradeTPInReports();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle RFs as TP Reports ...
|
|
int handledRFsCount = ArraySize(handleSignalResult.rf);
|
|
if (handledRFsCount > 0)
|
|
{
|
|
//
|
|
for (int i = 0; i < handledRFsCount; i++)
|
|
{
|
|
xEU5Reporter.AddTradeSLInReports();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update Account Info ...
|
|
if (
|
|
handledSLsCount > 0 ||
|
|
handledTPsCount > 0 ||
|
|
handledRFsCount > 0)
|
|
{
|
|
XEU5UpdateReports();
|
|
}
|
|
|
|
//
|
|
// Reading Indicator Buffers ...
|
|
XEU5HandleReadingBuffers();
|
|
if (xEU5CalculatedBars < xEU5MaxLengthOfInputs)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Prepare and Update all required data ...
|
|
double minBalanceForTradeBasedOnBalance = MathMax(
|
|
xEU5BalanceForOpenTrades,
|
|
xEU5Balance * xEU5MaxAllowedRiskOnTradesFactor);
|
|
xEU5Trader.SetMinBalanceForTradingPrice(minBalanceForTradeBasedOnBalance);
|
|
if (xEU5Balance * xEU5MaxAllowedRiskOnTradesFactor > xEU5BalanceForOpenTrades)
|
|
{
|
|
xEU5BalanceForOpenTrades = xEU5Balance * xEU5MaxAllowedRiskOnTradesFactor;
|
|
}
|
|
|
|
//
|
|
// Handle Open Trades ...
|
|
XEU5HandleOpenTrades();
|
|
|
|
//
|
|
// Handle Close Trades ...
|
|
XEU5HandleCloseTrades();
|
|
|
|
//
|
|
// Protect Account by Guarding Maximum Drawdown ...
|
|
XEU5GuardAccount();
|
|
|
|
//
|
|
// DrawDown and DrawUp ...
|
|
XEU5HandleCalculateDrawDownUp();
|
|
}
|
|
|
|
//
|
|
// Handle Trades when OnTrade Event Hnadler Calls ...
|
|
void XEU5SignalProviderHandleTrade()
|
|
{
|
|
//
|
|
// Check Provider Enabled ...
|
|
if (!xEU5MEnableProvider)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
if (xEU5ScanStarted)
|
|
{
|
|
XEU5ProcessOnTradeContext();
|
|
}
|
|
else
|
|
{
|
|
XEU5InitOnTradeContext();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle Open Trades ...
|
|
void XEU5HandleOpenTrades()
|
|
{
|
|
//
|
|
// Check Can Trade ...
|
|
bool canTrade = xEU5MAllowLongTrades || xEU5MAllowShortTrades;
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Update Reports ...
|
|
XEU5UpdateReports();
|
|
|
|
//
|
|
// Open Long Trades ...
|
|
if (
|
|
//
|
|
hasLongSignal &&
|
|
xEU5MAllowLongTrades)
|
|
{
|
|
//
|
|
bool isOpened = XEU5OpenLongPosition(longSignalInfo);
|
|
}
|
|
|
|
//
|
|
// Open Short Trades ...
|
|
if (
|
|
//
|
|
hasShortSignal &&
|
|
xEU5MAllowShortTrades)
|
|
{
|
|
//
|
|
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 isClosedLongTrades = false;
|
|
bool canCloseLongTrades = XEU5CanCloseLongTrade();
|
|
if (xEU5MAllowLongTrades && canCloseLongTrades)
|
|
{
|
|
//
|
|
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_LONG;
|
|
|
|
//
|
|
XSignal closed[];
|
|
xEU5Trader.CloseSignals(
|
|
closed,
|
|
type);
|
|
|
|
//
|
|
int closedTradesCount = ArraySize(closed);
|
|
isClosedLongTrades = closedTradesCount > 0;
|
|
if (isClosedLongTrades)
|
|
{
|
|
//
|
|
XEU5IssueForceCloseTradesAlert(type);
|
|
|
|
//
|
|
for (int i = 0; i < closedTradesCount; i++)
|
|
{
|
|
xEU5Reporter.AddTradeSLInReports();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Force Close Short Trades ...
|
|
bool isClosedShortTrades = false;
|
|
bool canCloseShortTrades = XEU5CanCloseShortTrade();
|
|
if (xEU5MAllowShortTrades && canCloseShortTrades)
|
|
{
|
|
//
|
|
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_SHORT;
|
|
|
|
//
|
|
XSignal closed[];
|
|
xEU5Trader.CloseSignals(
|
|
closed,
|
|
type);
|
|
|
|
//
|
|
int closedTradesCount = ArraySize(closed);
|
|
isClosedShortTrades = closedTradesCount > 0;
|
|
if (isClosedShortTrades)
|
|
{
|
|
//
|
|
XEU5IssueForceCloseTradesAlert(type);
|
|
|
|
//
|
|
for (int i = 0; i < closedTradesCount; i++)
|
|
{
|
|
xEU5Reporter.AddTradeSLInReports();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle Actiong Long Time Trades ...
|
|
XSignal longTimeHandleds[];
|
|
XEU5HandleLongTimeTrades(longTimeHandleds);
|
|
int longTimeHandledsCount = ArraySize(longTimeHandleds);
|
|
if (longTimeHandledsCount > 0)
|
|
{
|
|
//
|
|
// Do What we want ...
|
|
}
|
|
|
|
//
|
|
if (isClosedLongTrades ||
|
|
isClosedShortTrades)
|
|
{
|
|
XEU5UpdateReports();
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
int signalsCount = xEU5Trader.Count();
|
|
bool isCross = signalsCount >= 1;
|
|
if (isCross)
|
|
{
|
|
//
|
|
// Handle Cross Signals ...
|
|
XEU5HnadleCrossSignal(signal);
|
|
}
|
|
|
|
//
|
|
// Retrieve Can Execute Signal or not ...
|
|
bool canExecuteSignal =
|
|
!isCross
|
|
//
|
|
||
|
|
//
|
|
(
|
|
//
|
|
isCross &&
|
|
xEU5CrossSignalsMethod != XEU5_CROSS_SIGNAL_DO_NOTHING
|
|
//
|
|
);
|
|
if (!canExecuteSignal)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Execute Signal ...
|
|
ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal(
|
|
signal,
|
|
false, // Ignore TP SL ...
|
|
false, // Ignore Number of Trades ...
|
|
true // Check Account Conditions ...
|
|
);
|
|
result = executionResult == X_TRADER_SUCCEED_EXECUTION;
|
|
if (result)
|
|
{
|
|
//
|
|
XEU5IssueSignalExecutionAlert(signal);
|
|
|
|
//
|
|
// Update Reports ...
|
|
string providers[];
|
|
for (int i = 0; i < ArraySize(info.signallers); i++)
|
|
{
|
|
//
|
|
ENUM_XEU5_SIGNAL_PROVIDERS iProvider = info.signallers[i];
|
|
|
|
//
|
|
Add(
|
|
EnumToString(iProvider),
|
|
providers);
|
|
}
|
|
xEU5Reporter.AddSignalToReports(
|
|
signal,
|
|
providers);
|
|
}
|
|
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;
|
|
}
|
|
|
|
//
|
|
int signalsCount = xEU5Trader.Count();
|
|
bool isCross = signalsCount >= 1;
|
|
if (isCross)
|
|
{
|
|
//
|
|
// Handle Cross Signals ...
|
|
XEU5HnadleCrossSignal(signal);
|
|
}
|
|
|
|
//
|
|
// Retrieve Can Execute Signal or not ...
|
|
bool canExecuteSignal =
|
|
!isCross
|
|
//
|
|
||
|
|
//
|
|
(
|
|
//
|
|
isCross &&
|
|
xEU5CrossSignalsMethod != XEU5_CROSS_SIGNAL_DO_NOTHING
|
|
//
|
|
);
|
|
if (!canExecuteSignal)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Execute Signal ...
|
|
ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal(
|
|
signal,
|
|
false, // Ignore TP SL ...
|
|
false, // Ignore Number of Trades ...
|
|
true // Check Account Conditions ...
|
|
);
|
|
result = executionResult == X_TRADER_SUCCEED_EXECUTION;
|
|
if (result)
|
|
{
|
|
//
|
|
XEU5IssueSignalExecutionAlert(signal);
|
|
|
|
//
|
|
// Update Reports ...
|
|
string providers[];
|
|
for (int i = 0; i < ArraySize(info.signallers); i++)
|
|
{
|
|
//
|
|
ENUM_XEU5_SIGNAL_PROVIDERS iProvider = info.signallers[i];
|
|
|
|
//
|
|
Add(
|
|
EnumToString(iProvider),
|
|
providers);
|
|
}
|
|
xEU5Reporter.AddSignalToReports(
|
|
signal,
|
|
providers);
|
|
}
|
|
else
|
|
{
|
|
XEU5IssueSignalExecutionError(executionResult);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Apply Cross Signal Actions ...
|
|
void XEU5HnadleCrossSignal(
|
|
XSignal &signal // Specified Signal ...
|
|
)
|
|
{
|
|
//
|
|
// Check Cross Signal Handling Enabled ...
|
|
if (xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_DO_NOTHING)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// First We have to Change Cross Signals Comment ...
|
|
string comment = xEU5Trader.GenerateSignalComment(
|
|
signal,
|
|
true);
|
|
|
|
//
|
|
signal.comment = comment;
|
|
|
|
//
|
|
// If Every thing is Regular, prevent any changes here ...
|
|
if (xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_REGULAR)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve Max in Drawdown Signal ...
|
|
XSignal maxInDDSignal = xEU5Trader.GetMaxInDrawdownSignal();
|
|
|
|
//
|
|
// Validate Signal ...
|
|
bool isValidSignal =
|
|
maxInDDSignal.ticket > 0 &&
|
|
maxInDDSignal.symbol == signal.symbol &&
|
|
IsValid(maxInDDSignal, xEU5MagicNumber);
|
|
if (!isValidSignal)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
double volume = signal.volume;
|
|
bool isDirectional = maxInDDSignal.type == signal.type;
|
|
|
|
//
|
|
// Prevent any changes on Regular Conditions ...
|
|
bool isRegular =
|
|
isDirectional
|
|
? (
|
|
//
|
|
xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_DIRECTION_REGULAR ||
|
|
xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_DIRECTION_REGULAR_INDIRECTION_IMPORTANT
|
|
//
|
|
)
|
|
: (
|
|
//
|
|
xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_INDIRECTION_REGULAR ||
|
|
xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_DIRECTION_IMPORTANT_INDIRECTION_REGULAR
|
|
//
|
|
);
|
|
if (isRegular)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Important Act needs to Multiply volume by 2 ...
|
|
volume *= 2;
|
|
|
|
//
|
|
// Set Volume of signal ...
|
|
signal.volume = volume;
|
|
}
|
|
|
|
//
|
|
// Long Time ( Too Old Trades ) Handling ...
|
|
void XEU5HandleLongTimeTrades(
|
|
XSignal &result[] // Holds Result ...
|
|
)
|
|
{
|
|
//
|
|
CleanBuffer(result);
|
|
|
|
//
|
|
// Validate Args ...
|
|
bool canHandle =
|
|
xEU5MaxAllowedTrades > 0 &&
|
|
xEU5OldTradesAction != XEU5_TOO_OLD_IGNORE;
|
|
if (!canHandle)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve Old Trades ...
|
|
XSignal signals[];
|
|
xEU5Trader.GetOldSignals(
|
|
signals,
|
|
xEU5MaxAllowedTradeAge,
|
|
_Period);
|
|
int signalsCount = ArraySize(signals);
|
|
if (signalsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Detect Which Value of Old Trade must be Closed ...
|
|
double volumeMultiplier = 1;
|
|
switch (xEU5OldTradesAction)
|
|
{
|
|
//
|
|
case XEU5_TOO_OLD_CLOSE:
|
|
case XEU5_TOO_OLD_CLOSE_IN_PROFIT:
|
|
case XEU5_TOO_OLD_CLOSE_IN_DRAWDOWN:
|
|
volumeMultiplier = 1;
|
|
break;
|
|
|
|
//
|
|
case XEU5_TOO_OLD_PARTIAL_CLOSE_01:
|
|
volumeMultiplier = 0.01;
|
|
break;
|
|
|
|
//
|
|
case XEU5_TOO_OLD_PARTIAL_CLOSE_05:
|
|
volumeMultiplier = 0.05;
|
|
break;
|
|
|
|
//
|
|
case XEU5_TOO_OLD_PARTIAL_CLOSE_10:
|
|
volumeMultiplier = 0.1;
|
|
break;
|
|
|
|
//
|
|
case XEU5_TOO_OLD_PARTIAL_CLOSE_20:
|
|
volumeMultiplier = 0.2;
|
|
break;
|
|
|
|
//
|
|
case XEU5_TOO_OLD_PARTIAL_CLOSE_25:
|
|
volumeMultiplier = 0.25;
|
|
break;
|
|
|
|
//
|
|
case XEU5_TOO_OLD_PARTIAL_CLOSE_30:
|
|
volumeMultiplier = 0.30;
|
|
break;
|
|
|
|
//
|
|
case XEU5_TOO_OLD_PARTIAL_CLOSE_50:
|
|
volumeMultiplier = 0.5;
|
|
break;
|
|
|
|
//
|
|
case XEU5_TOO_OLD_PARTIAL_CLOSE_75:
|
|
volumeMultiplier = 0.75;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Loop through Old Trades ...
|
|
for (int i = 0; i < signalsCount; i++)
|
|
{
|
|
//
|
|
XSignal iSignal = signals[i];
|
|
double pCloseVolume = iSignal.volume * volumeMultiplier;
|
|
pCloseVolume = NormalizeVolume(pCloseVolume, iSignal.symbol);
|
|
|
|
//
|
|
// Detect Completely Close Signal Or not ...
|
|
if (
|
|
xEU5OldTradesAction == XEU5_TOO_OLD_CLOSE ||
|
|
(xEU5OldTradesAction == XEU5_TOO_OLD_CLOSE_IN_PROFIT &&
|
|
iSignal.profit > 0) ||
|
|
(xEU5OldTradesAction == XEU5_TOO_OLD_CLOSE_IN_DRAWDOWN &&
|
|
iSignal.profit < 0))
|
|
{
|
|
//
|
|
bool isClosed = xEU5Trader.Close(
|
|
iSignal.ticket,
|
|
xEU5Trader.GenerateSignalAgeComment(iSignal));
|
|
|
|
//
|
|
if (isClosed)
|
|
{
|
|
Add(
|
|
iSignal,
|
|
result);
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Detect Signal Age ...
|
|
int currentStep = xEU5MaxAllowedTradeAge;
|
|
int nextStep = xEU5MaxAllowedTradeAge * 2;
|
|
int signalAge = xEU5Trader.GetSignalAge(iSignal);
|
|
if (signalAge >= currentStep && signalAge <= currentStep + 10)
|
|
{
|
|
//
|
|
// Here we can apply First Partial Closing ...
|
|
|
|
//
|
|
bool isClosed = xEU5Trader.ClosePartial(
|
|
iSignal.ticket,
|
|
pCloseVolume,
|
|
xEU5Trader.GenerateSignalAgeComment(iSignal));
|
|
|
|
//
|
|
if (isClosed)
|
|
{
|
|
Add(
|
|
iSignal,
|
|
result);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle Close Trades When Profits is Under Specified Price ...
|
|
void XEU5GuardAccount()
|
|
{
|
|
//
|
|
// Check Guard Enabled ...
|
|
if (xEU5MaxAllowedRiskOnTradesFactor <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Calculate Max Allowed Drawdown ...
|
|
double xEU5MaxAllowedRiskOnTradesPrice =
|
|
MathMax(
|
|
xEU5BalanceForOpenTrades,
|
|
xEU5Balance * xEU5MaxAllowedRiskOnTradesFactor);
|
|
|
|
//
|
|
// Count Trades ...
|
|
int signalsCount = xEU5Trader.Count();
|
|
if (signalsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Count Open Trades and Calculate Profits ...
|
|
double profit = xEU5Trader.GetSignalsProfit();
|
|
|
|
//
|
|
// Prevent Moving forward when trades on Profit ...
|
|
if (profit >= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Make Profit Check ...
|
|
bool isGuardAttacked = MathAbs(profit) >= xEU5MaxAllowedRiskOnTradesPrice;
|
|
if (!isGuardAttacked)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
string message = "";
|
|
|
|
//
|
|
// Handle Perform Guard Action ...
|
|
switch (xEU5GuardAction)
|
|
{
|
|
//
|
|
// Close All ...
|
|
case XEU5_GUARD_CLOSE_ALL:
|
|
{
|
|
//
|
|
XSignal closed[];
|
|
xEU5Trader.CloseSignals(closed);
|
|
int closedCount = ArraySize(closed);
|
|
if (closedCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
message = "Closed (" + (string)closedCount + ") Trades by Guard ...";
|
|
}
|
|
break;
|
|
|
|
//
|
|
case XEU5_GUARD_CLOSE_MAX_IN_DD:
|
|
case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5:
|
|
case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10:
|
|
case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_25:
|
|
case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_30:
|
|
case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_40:
|
|
case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_50:
|
|
case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_60:
|
|
case XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_75:
|
|
{
|
|
//
|
|
// Retrieve Max In Drawdown Trade ...
|
|
XSignal maxInDDSignal = xEU5Trader.GetMaxInDrawdownSignal();
|
|
bool isValid = IsValid(maxInDDSignal, xEU5MagicNumber) && maxInDDSignal.ticket > 0;
|
|
if (!isValid)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Close Max In Drawdown Trade ...
|
|
if (xEU5GuardAction == XEU5_GUARD_CLOSE_MAX_IN_DD)
|
|
{
|
|
//
|
|
string comment = "Signal (" + (string)maxInDDSignal.ticket + ") Closed by Guard ...";
|
|
bool isClosed = xEU5Trader.Close(
|
|
maxInDDSignal.ticket,
|
|
comment);
|
|
if (isClosed)
|
|
{
|
|
//
|
|
message = comment;
|
|
break;
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Partial Close Max In Drawdown Trade ...
|
|
double volumeRate = 0.5;
|
|
if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5)
|
|
{
|
|
volumeRate = 0.05;
|
|
}
|
|
else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10)
|
|
{
|
|
volumeRate = 0.10;
|
|
}
|
|
else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_25)
|
|
{
|
|
volumeRate = 0.25;
|
|
}
|
|
else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_30)
|
|
{
|
|
volumeRate = 0.30;
|
|
}
|
|
else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_40)
|
|
{
|
|
volumeRate = 0.40;
|
|
}
|
|
else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_50)
|
|
{
|
|
volumeRate = 0.50;
|
|
}
|
|
else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_60)
|
|
{
|
|
volumeRate = 0.60;
|
|
}
|
|
else if (xEU5GuardAction == XEU5_GUARD_PARTIAL_CLOSE_MAX_IN_DD_75)
|
|
{
|
|
volumeRate = 0.75;
|
|
}
|
|
|
|
//
|
|
double volume = NormalizeVolume(
|
|
maxInDDSignal.volume * volumeRate,
|
|
maxInDDSignal.symbol);
|
|
|
|
//
|
|
string comment = "Signal (" + (string)maxInDDSignal.ticket + ") Partial Closed (" + (string)volumeRate + ") by Guard ...";
|
|
|
|
//
|
|
bool isClosed = xEU5Trader.ClosePartial(
|
|
maxInDDSignal.ticket,
|
|
volume,
|
|
comment);
|
|
if (isClosed)
|
|
{
|
|
//
|
|
message = comment;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
//
|
|
// Nothing ...
|
|
// Default ...
|
|
default:
|
|
message = "Max Allowed Drawdown Reached ...";
|
|
break;
|
|
}
|
|
|
|
//
|
|
if (StringLen(message) <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XEU5IssueAlert(message);
|
|
}
|
|
|
|
//
|
|
// Calculate Usefull data ...
|
|
void XEU5HandleCalculateDrawDownUp()
|
|
{
|
|
//
|
|
XSignal signals[];
|
|
xEU5Trader.GetSignals(signals);
|
|
int signalsCount = ArraySize(signals);
|
|
if (signalsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
double profit = 0;
|
|
double volume = 0;
|
|
double maxAllowedVolume = xEU5MaxAllowedVolume;
|
|
for (int i = 0; i < signalsCount; i++)
|
|
{
|
|
//
|
|
XSignal iSignal = signals[i];
|
|
|
|
//
|
|
profit += iSignal.profit;
|
|
|
|
//
|
|
volume =
|
|
volume == 0 ||
|
|
volume < iSignal.volume
|
|
? iSignal.volume
|
|
: volume;
|
|
}
|
|
|
|
//
|
|
if (profit < 0)
|
|
{
|
|
//
|
|
xEU5MaxDrawDown =
|
|
xEU5MaxDrawDown == 0 ||
|
|
xEU5MaxDrawDown > MathAbs(profit)
|
|
? MathAbs(profit)
|
|
: xEU5MaxDrawDown;
|
|
|
|
//
|
|
// Update Buffers ...
|
|
datetime time = iTime(_Symbol, _Period, 0);
|
|
|
|
//
|
|
// Calculate Max Allowed Drawdown ...
|
|
double xEU5MaxAllowedRiskOnTradesPrice =
|
|
MathMax(
|
|
xEU5BalanceForOpenTrades,
|
|
xEU5Balance * xEU5MaxAllowedRiskOnTradesFactor);
|
|
|
|
//
|
|
Add(
|
|
time,
|
|
xEU5TradeTimes);
|
|
Add(
|
|
volume,
|
|
xEU5TradeVolumes);
|
|
Add(
|
|
xEU5MaxDrawDown,
|
|
xEU5TradeMaxDrawdowns);
|
|
Add(
|
|
maxAllowedVolume,
|
|
xEU5TradeMaxAllowdVolumes);
|
|
Add(
|
|
xEU5MaxAllowedRiskOnTradesPrice,
|
|
xEU5MinBalanceForTradePrices);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
xEU5MaxDrawUp =
|
|
xEU5MaxDrawUp == 0 ||
|
|
xEU5MaxDrawUp < profit
|
|
? profit
|
|
: xEU5MaxDrawUp;
|
|
}
|
|
|
|
//
|
|
// Update Reports ...
|
|
xEU5Reporter.UpdateMaxDrawUpInReports(xEU5MaxDrawUp);
|
|
xEU5Reporter.UpdateMaxDrawDownInReports(xEU5MaxDrawDown);
|
|
xEU5Reporter.UpdateMaxSameTimeTradesInReports(signalsCount);
|
|
}
|
|
|
|
//
|
|
// 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(XEU5ProviderName + "> 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(XEU5ProviderName + "> 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 ...
|
|
|
|
//
|
|
// Detected TP or SL ...
|
|
XDeal last = xEU5Trader.GetLastDeal();
|
|
if (last.reason == DEAL_REASON_SL)
|
|
{
|
|
xEU5Reporter.AddTradeSLInReports();
|
|
}
|
|
else if (last.reason == DEAL_REASON_TP)
|
|
{
|
|
xEU5Reporter.AddTradeTPInReports();
|
|
}
|
|
|
|
//
|
|
// 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 ..
|
|
//
|
|
|
|
//
|
|
// START Volume Baseed Functions ...
|
|
//
|
|
|
|
//
|
|
// Calculate Account Grow Rate ...
|
|
double XEU5GetAccountGrowRate()
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
double balanceDiff = xEU5Balance - xEU5Deposit;
|
|
result = balanceDiff / xEU5ApplyVolumeMultiplierPrice;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Base Volume Multiplier ...
|
|
double XEU5GetBaseVolumeMultiplier()
|
|
{
|
|
//
|
|
double result = xEU5VolumeMultiplier;
|
|
if (result <= 0)
|
|
{
|
|
result = 1;
|
|
}
|
|
|
|
//
|
|
double growRate = XEU5GetAccountGrowRate();
|
|
if (growRate > 1)
|
|
{
|
|
result *= growRate;
|
|
}
|
|
// else if (growRate > 0 && growRate < 1)
|
|
// {
|
|
// result = (1 + growRate);
|
|
// }
|
|
else
|
|
{
|
|
result = 1;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Max Allowed Volume Per Trades ...
|
|
void XEU5CalculateMaxAllowedVolume()
|
|
{
|
|
//
|
|
double calculatedMaxAllowedVolume = 0;
|
|
if (xEU5MaxSupportedVolumePerTradeFactor <= 0)
|
|
{
|
|
xEU5MaxAllowedVolume = 0;
|
|
}
|
|
|
|
//
|
|
calculatedMaxAllowedVolume = xEU5Deposit * xEU5MaxSupportedVolumePerTradeFactor;
|
|
|
|
//
|
|
if (xEU5IncreasedMaxSupportedVolumeRate > 0)
|
|
{
|
|
//
|
|
double balanceRate = MathRound(xEU5Balance / xEU5Deposit);
|
|
if (balanceRate >= xEU5IncreasedMaxSupportedVolumeRate)
|
|
{
|
|
//
|
|
double multiplier = MathRound(balanceRate / xEU5IncreasedMaxSupportedVolumeRate) + 1;
|
|
|
|
//
|
|
calculatedMaxAllowedVolume *= multiplier;
|
|
}
|
|
}
|
|
|
|
//
|
|
xEU5MaxAllowedVolume =
|
|
xEU5MaxAllowedVolume == 0 || calculatedMaxAllowedVolume > xEU5MaxAllowedVolume
|
|
? calculatedMaxAllowedVolume
|
|
: xEU5MaxAllowedVolume;
|
|
|
|
//
|
|
// Normalize ...
|
|
if (xEU5MaxAllowedVolume > 0)
|
|
{
|
|
xEU5MaxAllowedVolume = NormalizeVolume(xEU5MaxAllowedVolume);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Calculate Static Volume ...
|
|
void XEU5CalculateStaticVolume()
|
|
{
|
|
//
|
|
// Calculate Static Volume ...
|
|
if (xEU5StaticVolumeMethod == XEU5_STATIC_VOLUME_BASED_ON_BALANCE)
|
|
{
|
|
xEU5StaticVolume = xEU5StaticVolumeFactor * xEU5Balance;
|
|
}
|
|
else
|
|
{
|
|
xEU5StaticVolume = xEU5StaticVolumeFactor * xEU5Deposit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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 ...
|
|
)
|
|
{
|
|
//
|
|
// Calculate Static Volume ...
|
|
XEU5CalculateStaticVolume();
|
|
|
|
//
|
|
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 > 0)
|
|
{
|
|
//
|
|
// Decrease Volume if Open Trades Exists ...
|
|
double vDecreaseRate =
|
|
openSignals + 1;
|
|
|
|
//
|
|
result /= vDecreaseRate;
|
|
}
|
|
|
|
//
|
|
// Check Signal Max Allowed Volume ...
|
|
XEU5CalculateMaxAllowedVolume();
|
|
double maxAllowedVolume = xEU5MaxAllowedVolume;
|
|
if (maxAllowedVolume > 0)
|
|
{
|
|
//
|
|
result =
|
|
result < maxAllowedVolume
|
|
? result
|
|
: maxAllowedVolume;
|
|
}
|
|
|
|
//
|
|
// Normalize Volume ...
|
|
result = NormalizeVolume(result);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// END Volume Baseed Functions ...
|
|
//
|
|
|
|
//
|
|
// START Reports Preparation Functions ...
|
|
//
|
|
|
|
//
|
|
// Update Report Info ...
|
|
void XEU5UpdateReports()
|
|
{
|
|
//
|
|
XEU5CalculateStaticVolume();
|
|
XEU5CalculateMaxAllowedVolume();
|
|
double volumeMultiplier =
|
|
xEU5VolumeMultiplier > 0
|
|
? XEU5GetBaseVolumeMultiplier()
|
|
: 1;
|
|
|
|
//
|
|
double staticVolume = xEU5StaticVolume;
|
|
string staticVolumeCalculationMethod = EnumToString(xEU5StaticVolumeMethod);
|
|
double maxAllowedVolume = xEU5MaxAllowedVolume;
|
|
double volumeIncreaseMultiplier = volumeMultiplier;
|
|
double balanceGowingToApplyMultiplier = xEU5ApplyVolumeMultiplierPrice;
|
|
double balanceGrowingToIncreaseMaxAllowedVolume = xEU5Deposit * xEU5MaxSupportedVolumePerTradeFactor;
|
|
|
|
//
|
|
// Update Reports Volume Info ...
|
|
xEU5Reporter.UpdateReportsVolumeInfo(
|
|
staticVolume,
|
|
staticVolumeCalculationMethod,
|
|
maxAllowedVolume,
|
|
volumeIncreaseMultiplier,
|
|
balanceGowingToApplyMultiplier,
|
|
balanceGrowingToIncreaseMaxAllowedVolume);
|
|
|
|
//
|
|
// Calculate Max Allowed Drawdown ...
|
|
double minBalanceForTradeBasedOnBalance = MathMax(
|
|
xEU5BalanceForOpenTrades,
|
|
xEU5Balance * xEU5MaxAllowedRiskOnTradesFactor);
|
|
xEU5Reporter.UpdateMinBalanceForOpenTradesInReports(minBalanceForTradeBasedOnBalance);
|
|
}
|
|
|
|
//
|
|
// Reset XEU5 Info Buffers ...
|
|
void XEU5ResetCollectors()
|
|
{
|
|
//
|
|
// Reset Calculations Buffers and Variables ...
|
|
xEU5MaxDrawUp = 0;
|
|
xEU5MaxDrawDown = 0;
|
|
CleanBuffer(xEU5TradeTimes);
|
|
CleanBuffer(xEU5TradeVolumes);
|
|
CleanBuffer(xEU5TradeMaxDrawdowns);
|
|
CleanBuffer(xEU5TradeMaxAllowdVolumes);
|
|
CleanBuffer(xEU5MinBalanceForTradePrices);
|
|
}
|
|
|
|
//
|
|
// Generate Calculations Buffers and Variables Log String ...
|
|
string XEU5GenerateCollectorString(
|
|
int maxAvailable = 5 // Max Number of Parsing Buffers ...
|
|
)
|
|
{
|
|
//
|
|
string result = "";
|
|
|
|
//
|
|
// Validate ...
|
|
int bufferSize = ArraySize(xEU5TradeTimes);
|
|
if (bufferSize <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = "DD Info: \n";
|
|
|
|
//
|
|
int logSize = MathMin(bufferSize, maxAvailable);
|
|
for (int i = logSize - 1; i >= 0; i--)
|
|
{
|
|
//
|
|
// Reading Requirement Buffers ...
|
|
datetime iTime = xEU5TradeTimes[i];
|
|
double iVolume = xEU5TradeVolumes[i];
|
|
double iMaxDD = xEU5TradeMaxDrawdowns[i];
|
|
double iMaxAllowedVolume = xEU5TradeMaxAllowdVolumes[i];
|
|
double iMaxRiskableBalance = xEU5MinBalanceForTradePrices[i];
|
|
|
|
//
|
|
// Generate Report ...
|
|
result += (string)i + ":" + "\n";
|
|
result += "Time: " + (string)iTime + "\n";
|
|
result += "Volume: " + (string)iVolume + "\n";
|
|
result += "MaxDD: " + (string)iMaxDD + "\n";
|
|
result += "MaxAllowedVolume: " + (string)iMaxAllowedVolume + "\n";
|
|
result += "MaxRiskableBalance: " + (string)iMaxRiskableBalance + "\n";
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// END Reports Preparation Functions ...
|
|
//
|
|
|
|
//
|
|
// START Alert Functions ...
|
|
//
|
|
|
|
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
|
|
)
|
|
{
|
|
//
|
|
string message = xEU5Trader.ToString(signal);
|
|
XEU5IssueAlert(message);
|
|
}
|
|
|
|
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 = SignalToString(signal);
|
|
XEU5IssueAlert(signalStr);
|
|
}
|
|
|
|
//
|
|
// END Alert Functions ...
|
|
//
|
|
|
|
//
|
|
// END Private Functions ...
|
|
//
|