1598 lines
36 KiB
Plaintext
1598 lines
36 KiB
Plaintext
////////////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 XEU5 Signal Provider Library
|
|
// --------------------------------------------------------
|
|
// Name: XEU5SignalProvider
|
|
// Description: XEU5 based signal provider ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://www.saherelm.ir"
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
#define XEU5ProviderName "XEU5"
|
|
|
|
//
|
|
// START Inputs ...
|
|
//
|
|
|
|
#include "x-saherelm.xeu5.provider.inputs.lib.mq5";
|
|
|
|
//
|
|
// END Inputs ...
|
|
//
|
|
|
|
//
|
|
// Include Common Library ...
|
|
#include "..\Libraries\x-saherelm.common.lib.mq5"
|
|
|
|
//
|
|
// Include Logger Library ...
|
|
#include "..\Libraries\x-saherelm.log.lib.mq5"
|
|
|
|
//
|
|
// Include Alert Library ...
|
|
#include "..\Libraries\x-saherelm.alert.lib.mq5"
|
|
|
|
//
|
|
// Include Draw Library ...
|
|
#include "..\Libraries\x-saherelm.draw.lib.mq5"
|
|
|
|
//
|
|
// Include Class Libraries ...
|
|
#include "..\Classes\x-saherelm.class.lib.mq5"
|
|
|
|
//
|
|
// START Global Definitions: Variables, Properties and etc ...
|
|
//
|
|
|
|
//
|
|
XCTrade *xEU5Trader;
|
|
XCAccountInfo xEU5AccountInfo;
|
|
|
|
//
|
|
#include "x-saherelm.xeu5.provider.indicators.lib.mq5"
|
|
|
|
//
|
|
double xEU5Deposit = 0;
|
|
double xEU5Balance = 0;
|
|
double xEU5MinReward = 0;
|
|
double xEU5FreeMargin = 0;
|
|
double xEU5BalanceForOpenTrades = 0;
|
|
double xEU5FreeMarginForOpenTrades = 0;
|
|
double xEU5BaseRiskableMoneyPerTrade = 0;
|
|
double xEU5SupportTradesPriceDistance = 0;
|
|
|
|
//
|
|
int NOT_ENOUGH_MONEY_ERROR = 4756;
|
|
|
|
//
|
|
struct XEU5_INDIRECTION
|
|
{
|
|
datetime lastCheck;
|
|
double profit;
|
|
};
|
|
|
|
//
|
|
struct XEU5_POSITION_HOLDING
|
|
{
|
|
ulong ticket;
|
|
XEU5_INDIRECTION info[];
|
|
};
|
|
|
|
//
|
|
XEU5_POSITION_HOLDING positionHoldings[];
|
|
|
|
//
|
|
// END Global Definitions: Variables, Properties and etc ...
|
|
//
|
|
|
|
//
|
|
// START Provided Functions ...
|
|
//
|
|
|
|
//
|
|
// Initial Library if required ...
|
|
bool XEU5InitSignalProviderLibrary()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Inputs ...
|
|
result = XEU5ValidateInputs();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Init Indicators ...
|
|
result = XEU5InitIndicators();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Account Deposit ...
|
|
xEU5Deposit = xEU5AccountInfo.GetInitialBalance();
|
|
|
|
//
|
|
// Prepare Min Reward ...
|
|
if (xEU5MinRewardInPips > 0)
|
|
{
|
|
xEU5MinReward = PipsToPrice(xEU5MinRewardInPips);
|
|
}
|
|
|
|
//
|
|
// Calculate Min Balance for Trades ...
|
|
if (xEU5BalanceFactorForOpenTrades > 0)
|
|
{
|
|
xEU5BalanceForOpenTrades = xEU5BalanceFactorForOpenTrades * xEU5Deposit;
|
|
}
|
|
|
|
//
|
|
// Claculate Min Free Marging for Trades ...
|
|
if (xEU5FreeMarginFactorForOpenTrades > 0)
|
|
{
|
|
xEU5FreeMarginForOpenTrades = xEU5FreeMarginFactorForOpenTrades * xEU5Deposit;
|
|
}
|
|
|
|
//
|
|
// Calculate xEU5SupportTradesPriceDistance ...
|
|
if (xEU5MaxAllowedSupportTrades > 0 && xEU5SupportTradesPriceDistanceInPips > 0)
|
|
{
|
|
xEU5SupportTradesPriceDistance = PipsToPrice(xEU5SupportTradesPriceDistanceInPips);
|
|
}
|
|
|
|
//
|
|
// Calculate Base Riskable Money Per Trade ...
|
|
if (xEU5MaxAllowedRiskPerTradesMultiplier > 0)
|
|
{
|
|
xEU5BaseRiskableMoneyPerTrade = (xEU5MaxAllowedRiskPerTradesMultiplier * xEU5Deposit);
|
|
}
|
|
|
|
//
|
|
// Make XCTrader instance ...
|
|
xEU5Trader = new XCTrade(
|
|
XEU5ProviderName,
|
|
_Symbol,
|
|
xEU5Slippage,
|
|
xEU5MagicNumber,
|
|
xEU5MaxAllowedTrades,
|
|
xEU5FreeMarginForOpenTrades,
|
|
xEU5BalanceForOpenTrades);
|
|
|
|
//
|
|
result = true;
|
|
|
|
//
|
|
// Logging State ...
|
|
XEU5IssueInitializationSucceedAlert();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// DeInitial Library if required ...
|
|
void XEU5DeinitSignalProviderLibrary(const int reason)
|
|
{
|
|
//
|
|
// Release Handlers ...
|
|
XEU5ReleaseIndicators();
|
|
|
|
//
|
|
// Logging State ...
|
|
XEU5IssueDeinitializationSucceedAlert();
|
|
}
|
|
|
|
//
|
|
// this is a Globally Function which do all of
|
|
// checkings and positions handling ...
|
|
void XEU5SignalProviderHandleTick()
|
|
{
|
|
//
|
|
// Update account Balance ...
|
|
xEU5Balance = xEU5AccountInfo.GetBalance();
|
|
xEU5FreeMargin = xEU5AccountInfo.GetFreeMargin();
|
|
|
|
//
|
|
// Check Provider is Enable or Not ...
|
|
if (!xEU5EnableProvider)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Handling Signals ...
|
|
XTraderHandlerResult handleSignalResult;
|
|
xEU5Trader.HandleSignals(handleSignalResult);
|
|
//
|
|
// TODO: Log it Later ...
|
|
|
|
//
|
|
// Reading Indicator Buffers ...
|
|
XEU5HandleReadingBuffers();
|
|
if (xEU5CalculatedBars < xEU5MaxLengthOfInputs)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Handle Open Trades ...
|
|
XEU5HandleOpenTrades();
|
|
|
|
//
|
|
// Handle Close Trades ...
|
|
XEU5HandleCloseTrades();
|
|
|
|
//
|
|
// Handle Support Trades ...
|
|
XEU5HandleSupportTrades();
|
|
|
|
//
|
|
// Handle Indirection Trades ...
|
|
XEU5HandleIndirectionTrades();
|
|
}
|
|
|
|
//
|
|
// Handle Open Trades ...
|
|
void XEU5HandleOpenTrades()
|
|
{
|
|
//
|
|
// Check Can Trade ...
|
|
bool canTrade = xEU5AllowLongTrades || xEU5AllowShortTrades;
|
|
if (!canTrade)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Check Max Open Trades ...
|
|
int openSignals = xEU5Trader.Count();
|
|
bool canOpenPositions = openSignals < xEU5MaxAllowedTrades;
|
|
if (!canOpenPositions)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Check Signals Exists ...
|
|
XEU5_SIGNAL longSignalInfo = {};
|
|
XEU5_SIGNAL shortSignalInfo = {};
|
|
bool hasLongSignal = XEU5CanOpenLongTrade(longSignalInfo);
|
|
bool hasShortSignal = XEU5CanOpenShortTrade(shortSignalInfo);
|
|
if (!hasLongSignal && !hasShortSignal)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Open Long Trades ...
|
|
if (
|
|
//
|
|
hasLongSignal &&
|
|
xEU5AllowLongTrades)
|
|
{
|
|
//
|
|
bool isOpened = XEU5OpenLongPosition(longSignalInfo);
|
|
}
|
|
|
|
//
|
|
// Open Short Trades ...
|
|
if (
|
|
//
|
|
hasShortSignal &&
|
|
xEU5AllowShortTrades)
|
|
{
|
|
//
|
|
bool isOpened = XEU5OpenShortPosition(shortSignalInfo);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle Close Trades ...
|
|
void XEU5HandleCloseTrades()
|
|
{
|
|
//
|
|
// All Close Mechanism Handles Here ...
|
|
// - Force Close;
|
|
// - Partial Close;
|
|
// - Risk Free Close;
|
|
// - Virtual TP/SL Close;
|
|
|
|
//
|
|
// Force Close Long Trades ...
|
|
bool canCloseLongTrades = XEU5CanCloseLongTrade();
|
|
if (xEU5AllowLongTrades && canCloseLongTrades)
|
|
{
|
|
//
|
|
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_LONG;
|
|
|
|
//
|
|
XSignal closed[];
|
|
xEU5Trader.CloseSignals(
|
|
closed,
|
|
type);
|
|
|
|
//
|
|
bool isClosed = ArraySize(closed) > 0;
|
|
if (isClosed)
|
|
{
|
|
XEU5IssueForceCloseTradesAlert(type);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Force Close Short Trades ...
|
|
bool canCloseShortTrades = XEU5CanCloseShortTrade();
|
|
if (xEU5AllowShortTrades && canCloseShortTrades)
|
|
{
|
|
//
|
|
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_SHORT;
|
|
|
|
//
|
|
XSignal closed[];
|
|
xEU5Trader.CloseSignals(
|
|
closed,
|
|
type);
|
|
|
|
//
|
|
bool isClosed = ArraySize(closed) > 0;
|
|
if (isClosed)
|
|
{
|
|
XEU5IssueForceCloseTradesAlert(type);
|
|
}
|
|
}
|
|
|
|
//
|
|
XEU5HandleCloseInProfitTrades();
|
|
|
|
//
|
|
XEU5HandleCloseMaxDrawDownTrades();
|
|
|
|
//
|
|
XEU5HandleCloseTooOldTrades();
|
|
|
|
//
|
|
XEU5CloseAllPositionsInPyramid();
|
|
}
|
|
|
|
//
|
|
// Handle Supported Trades ...
|
|
void XEU5HandleSupportTrades()
|
|
{
|
|
//
|
|
bool canDoTrade =
|
|
xEU5MaxAllowedSupportTrades > 0 &&
|
|
xEU5SupportTradesPriceDistanceInPips > 0;
|
|
if (!canDoTrade)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XEU5OpenSupportTrade();
|
|
}
|
|
|
|
//
|
|
// Handle Indirection Trades ...
|
|
void XEU5HandleIndirectionTrades()
|
|
{
|
|
//
|
|
if (!xEU5EnableIndirectionalSupportPositions)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve Long Enuogh inDrawDown Trades ...
|
|
// TODO: Complete this ...
|
|
// int age = 5;
|
|
// datetime time = iTime(_Symbol, _Period, 0);
|
|
|
|
// //
|
|
// XSignal oldTrades[];
|
|
// xEU5Trader.GetOldSignals(
|
|
// oldTrades
|
|
// age,
|
|
// _Period,
|
|
// X_SIGNAL_UNKNOWN);
|
|
// int oldTradesCount = ArraySize(oldTrades);
|
|
// if (oldTradesCount > 0)
|
|
// {
|
|
// //
|
|
// // Loop Through Trades to Find In DrawDown Trades ...
|
|
// for (int i = 0; i < oldTradesCount; i++)
|
|
// {
|
|
// //
|
|
// XSignal iSignal = oldTrades[i];
|
|
|
|
// //
|
|
// if (iSignal.profit >= 0)
|
|
// {
|
|
// continue;
|
|
// }
|
|
|
|
// // //
|
|
// // XEU5_INDIRECTION
|
|
// // XEU5_POSITION_HOLDING
|
|
|
|
// //
|
|
// // Check Position Exists Or not ...
|
|
// // If Exists => Update a tick ...
|
|
// // If not => Add new One ...
|
|
// int iSignalHoldingIndex = XEU5GetHoldingPositionIndex(iSignal.ticket);
|
|
// if (iSignalHoldingIndex >= 0)
|
|
// {
|
|
// //
|
|
// // Update Tick ...
|
|
// XEU5_INDIRECTION iInfo = {};
|
|
// iInfo.lastCheck = time;
|
|
// iInfo.profit = iSignal.profit;
|
|
|
|
// //
|
|
// Add(
|
|
// iInfo,
|
|
// positionHoldings[iSignalHoldingIndex].info);
|
|
// }
|
|
// else
|
|
// {
|
|
// //
|
|
// // Add new ...
|
|
// XEU5_POSITION_HOLDING iHolding;
|
|
// iHolding.ticket = iSignal.ticket;
|
|
|
|
// //
|
|
// XEU5_INDIRECTION iInfo = {};
|
|
// iInfo.lastCheck = time;
|
|
// iInfo.profit = iSignal.profit;
|
|
|
|
// //
|
|
// Add(
|
|
// iInfo,
|
|
// iHolding.info);
|
|
|
|
// //
|
|
// Add(
|
|
// iHolding,
|
|
// positionHoldings);
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// //
|
|
// int positionHoldingsCount = ArraySize(positionHoldings);
|
|
// if (positionHoldingsCount <= 0)
|
|
// {
|
|
// return;
|
|
// }
|
|
|
|
// //
|
|
// // Now Check List and Propose InDirection Trades ...
|
|
// for (int i = 0; i < positionHoldingsCount; i++)
|
|
// {
|
|
// //
|
|
// XEU5_POSITION_HOLDING iHolding = positionHoldings[i];
|
|
|
|
// //
|
|
// int infoCount = ArraySize(iHolding.info);
|
|
// if (infoCount <= 0)
|
|
// {
|
|
// continue;
|
|
// }
|
|
|
|
// //
|
|
// bool isPriceDecreasing = IsDecreasing(0, infoCount - 1, iHolding);
|
|
// if (!isPriceDecreasing)
|
|
// {
|
|
// continue;
|
|
// }
|
|
|
|
// //
|
|
// // Retrieve Signal ...
|
|
// XSignal iParent = xEU5Trader.GetPosition(iHolding.ticket);
|
|
|
|
// //
|
|
// // Generate InDirection Signal ...
|
|
// XSignal iInDirectionSignal = XEU5GenerateInDirectionalSupportSignal(iParent);
|
|
|
|
// //
|
|
// // Execute Support Signal ...
|
|
// bool isExecuted = xEU5Trader.ForceExecuteSignal(iInDirectionSignal);
|
|
// if (isExecuted)
|
|
// {
|
|
// //
|
|
// // Issue Alert ...
|
|
// XEU5IssueAlert(iInDirectionSignal.comment);
|
|
// XEU5IssueSignalExecutionAlert(iInDirectionSignal);
|
|
|
|
// //
|
|
// // Cleanup iHolding Info ...
|
|
// ArrayFree(iHolding.info);
|
|
// ArrayResize(iHolding.info, 0);
|
|
// }
|
|
// }
|
|
}
|
|
|
|
//
|
|
// Open Long Position ...
|
|
bool XEU5OpenLongPosition(
|
|
XEU5_SIGNAL &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(info.signalPusher);
|
|
|
|
//
|
|
XSignal signal = {};
|
|
signal = xEU5Trader.GenerateSignal(
|
|
X_SIGNAL_LONG,
|
|
tp,
|
|
sl,
|
|
volume,
|
|
riskFreeStep,
|
|
riskFreeRate);
|
|
bool isValidSignal = IsValid(
|
|
signal,
|
|
xEU5MagicNumber);
|
|
if (!isValidSignal)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal(signal);
|
|
result = executionResult == X_TRADER_SUCCEED_EXECUTION;
|
|
if (result)
|
|
{
|
|
XEU5IssueSignalExecutionAlert(signal);
|
|
}
|
|
else
|
|
{
|
|
XEU5IssueSignalExecutionError(executionResult);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Open Short Position ...
|
|
bool XEU5OpenShortPosition(
|
|
XEU5_SIGNAL &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(info.signalPusher);
|
|
|
|
//
|
|
XSignal signal = {};
|
|
signal = xEU5Trader.GenerateSignal(
|
|
X_SIGNAL_SHORT,
|
|
tp,
|
|
sl,
|
|
volume,
|
|
riskFreeStep,
|
|
riskFreeRate);
|
|
bool isValidSignal = IsValid(
|
|
signal,
|
|
xEU5MagicNumber);
|
|
if (!isValidSignal)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal(signal);
|
|
result = executionResult == X_TRADER_SUCCEED_EXECUTION;
|
|
if (result)
|
|
{
|
|
XEU5IssueSignalExecutionAlert(signal);
|
|
}
|
|
else
|
|
{
|
|
XEU5IssueSignalExecutionError(executionResult);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Open a Support Signal ...
|
|
void XEU5OpenSupportTrade()
|
|
{
|
|
//
|
|
bool canDoTrade =
|
|
xEU5MaxAllowedSupportTrades > 0 &&
|
|
xEU5SupportTradesPriceDistanceInPips > 0;
|
|
if (!canDoTrade)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Recieve InDD Open Trades ...
|
|
// TODO: Complete this ...
|
|
// XSignal inDDTrades[];
|
|
// xEU5Trader.GetInDrawDownTrades(
|
|
// xEU5SupportTradesPriceDistance,
|
|
// X_SIGNAL_UNKNOWN,
|
|
// X_KIND_TRADE,
|
|
// inDDTrades);
|
|
// int inDDTradesCount = ArraySize(inDDTrades);
|
|
// if (inDDTradesCount <= 0)
|
|
// {
|
|
// return;
|
|
// }
|
|
|
|
// //
|
|
// // Loop through in DD Trades ...
|
|
// for (int i = 0; i < inDDTradesCount; i++)
|
|
// {
|
|
// //
|
|
// XSignal iSignal = inDDTrades[i];
|
|
|
|
// //
|
|
// // Check Distance of Trades ...
|
|
// bool isDistancePassed =
|
|
// MathAbs(iSignal.profit) >= xEU5SupportTradesPriceDistance;
|
|
// if (!isDistancePassed)
|
|
// {
|
|
// continue;
|
|
// }
|
|
|
|
// //
|
|
// // Get Opened Support Trades for iSignal ...
|
|
// XSignal iSignalSupports[];
|
|
// xEU5Trader.GetPositionsByKind(
|
|
// X_SIGNAL_UNKNOWN,
|
|
// X_KIND_SUPPORT,
|
|
// iSignalSupports);
|
|
// int iSignalSupportsCount = ArraySize(iSignalSupports);
|
|
// if (iSignalSupportsCount > xEU5MaxAllowedSupportTrades)
|
|
// {
|
|
// continue;
|
|
// }
|
|
|
|
// //
|
|
// // Check Signal Exists or not ...
|
|
// XEU5_SIGNAL info = {};
|
|
// bool hasSignal =
|
|
// iSignal.type == X_SIGNAL_LONG ? XEU5CanOpenLongTrade(info) : XEU5CanOpenShortTrade(info);
|
|
// if (!hasSignal)
|
|
// {
|
|
// continue;
|
|
// }
|
|
|
|
// //
|
|
// LogMessage("iSignal: " + (string)iSignal.ticket + "_" + GetSignalType(iSignal) + " passed Distance for Support: " + (string)iSignal.profit);
|
|
// LogMessage("iSignal Has Support Signal ...");
|
|
|
|
// //
|
|
// // Generate Support Signal ...
|
|
// XSignal sSignal = GenerateSupportSignal(
|
|
// info.signalPusher,
|
|
// iSignal.type,
|
|
// iSignal);
|
|
|
|
// //
|
|
// int error = -1;
|
|
// bool isOpened = xEU5Trader.ExecuteSupportSignal(
|
|
// sSignal,
|
|
// error);
|
|
// if (isOpened)
|
|
// {
|
|
// XEU5IssueSignalExecutionAlert(sSignal);
|
|
// }
|
|
// else
|
|
// {
|
|
// XEU5IssueSignalExecutionError(error);
|
|
// }
|
|
// }
|
|
}
|
|
|
|
//
|
|
// Close In Profit Trades ...
|
|
// the senario is to close in profit trades
|
|
// if they are old age ...
|
|
// age calculated based on xEU5MaxInDrawDownTradeAge / 2 ...
|
|
void XEU5HandleCloseInProfitTrades()
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (xEU5MaxInProfitTradeAge <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// TODO: Complete this ...
|
|
|
|
// //
|
|
// int age = xEU5MaxInProfitTradeAge;
|
|
// double minProfit = 1;
|
|
|
|
// //
|
|
// XSignal oldTrades[];
|
|
// xEU5Trader.GetLongTimeTrades(
|
|
// age,
|
|
// _Period,
|
|
// X_SIGNAL_UNKNOWN,
|
|
// X_KIND_TRADE,
|
|
// oldTrades);
|
|
// int oldTradesCount = ArraySize(oldTrades);
|
|
// for (int i = 0; i < oldTradesCount; i++)
|
|
// {
|
|
// //
|
|
// XSignal iTrade = oldTrades[i];
|
|
// if (iTrade.profit > minProfit && iTrade.sl == 0)
|
|
// {
|
|
// //
|
|
// string comment = xEU5Trader.GetSignalForceClosedComment(iTrade);
|
|
// bool isClosed = xEU5Trader.Close(
|
|
// iTrade.ticket,
|
|
// comment);
|
|
// if (isClosed)
|
|
// {
|
|
// //
|
|
// // Issue Alert ...
|
|
// XEU5IssueAlert("Close In Profit Trade: (" + (string)iTrade.ticket + "), profit: " + (string)iTrade.profit);
|
|
// XEU5IssueAlert(comment);
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// //
|
|
// XSignal oldSupports[];
|
|
// xEU5Trader.GetLongTimeTrades(
|
|
// age,
|
|
// _Period,
|
|
// X_SIGNAL_UNKNOWN,
|
|
// X_KIND_SUPPORT,
|
|
// oldSupports);
|
|
// int oldSupportsCount = ArraySize(oldSupports);
|
|
// for (int i = 0; i < oldSupportsCount; i++)
|
|
// {
|
|
// //
|
|
// XSignal iTrade = oldSupports[i];
|
|
// if (iTrade.profit > minProfit && iTrade.sl == 0)
|
|
// {
|
|
// //
|
|
// string comment = xEU5Trader.GetSignalForceClosedComment(iTrade);
|
|
// bool isClosed = xEU5Trader.Close(
|
|
// iTrade.ticket,
|
|
// comment);
|
|
// if (isClosed)
|
|
// {
|
|
// //
|
|
// // Issue Alert ...
|
|
// XEU5IssueAlert("Close In Profit Trade: (" + (string)iTrade.ticket + "), profit: " + (string)iTrade.profit);
|
|
// XEU5IssueAlert(comment);
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
|
|
//
|
|
// Close All InDrawDown Trades ...
|
|
void XEU5HandleCloseMaxDrawDownTrades()
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (xEU5MaxAllowedRiskPerTradesMultiplier <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
double baseRiskableMoney = xEU5BaseRiskableMoneyPerTrade > 0 ? xEU5BaseRiskableMoneyPerTrade : 1;
|
|
|
|
//
|
|
// TODO: Complete this ...
|
|
|
|
// //
|
|
// XSignal inDDTrades[];
|
|
// xEU5Trader.GetInDrawDownTrades(
|
|
// 0,
|
|
// X_SIGNAL_UNKNOWN,
|
|
// X_KIND_TRADE,
|
|
// inDDTrades);
|
|
|
|
// //
|
|
// int inDDTradesCount = ArraySize(inDDTrades);
|
|
// if (inDDTradesCount > 0)
|
|
// {
|
|
// //
|
|
// // Loop through Trades ...
|
|
// for (int i = 0; i < inDDTradesCount; i++)
|
|
// {
|
|
// //
|
|
// XSignal iTrade = inDDTrades[i];
|
|
|
|
// //
|
|
// // Calculate Max Allowed Risk Per iTrade ...
|
|
// double iMaxAllowedRisk = (iTrade.volume / xEU5StaticVolume) * baseRiskableMoney;
|
|
|
|
// //
|
|
// // Check Negative Profit Matchs Riskable Money ...
|
|
// bool isProfitPassed = MathAbs(iTrade.profit) >= iMaxAllowedRisk;
|
|
// if (isProfitPassed)
|
|
// {
|
|
// //
|
|
// string comment = xEU5Trader.GetSignalForceClosedComment(iTrade);
|
|
|
|
// //
|
|
// bool isClosed = xEU5Trader.Close(iTrade.ticket, comment);
|
|
// if (isClosed)
|
|
// {
|
|
// LogMessage("Signal: " + (string)iTrade.ticket + ", closed by: " + (string)iMaxAllowedRisk);
|
|
// XEU5IssueAlert(comment);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// //
|
|
// XSignal inDDSupports[];
|
|
// xEU5Trader.GetInDrawDownTrades(
|
|
// 0,
|
|
// X_SIGNAL_UNKNOWN,
|
|
// X_KIND_SUPPORT,
|
|
// inDDSupports);
|
|
|
|
// //
|
|
// int inDDSupportsCount = ArraySize(inDDSupports);
|
|
// if (inDDSupportsCount > 0)
|
|
// {
|
|
// //
|
|
// // Loop through Trades ...
|
|
// for (int i = 0; i < inDDSupportsCount; i++)
|
|
// {
|
|
// //
|
|
// XSignal iTrade = inDDSupports[i];
|
|
|
|
// //
|
|
// // Calculate Max Allowed Risk Per iTrade ...
|
|
// double iMaxAllowedRisk = (iTrade.volume / xEU5StaticVolume) * baseRiskableMoney;
|
|
|
|
// //
|
|
// // Check Negative Profit Matchs Riskable Money ...
|
|
// bool isProfitPassed = MathAbs(iTrade.profit) >= iMaxAllowedRisk;
|
|
// if (isProfitPassed)
|
|
// {
|
|
// //
|
|
// string comment = xEU5Trader.GetSignalForceClosedComment(iTrade);
|
|
|
|
// //
|
|
// bool isClosed = xEU5Trader.Close(iTrade.ticket, comment);
|
|
// if (isClosed)
|
|
// {
|
|
// XEU5IssueAlert(comment);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
|
|
//
|
|
// Close All Too Old Trades ...
|
|
// the senario is to close all tardes which has long age ...
|
|
// age calculated based on xEU5MaxInDrawDownTradeAge ...
|
|
void XEU5HandleCloseTooOldTrades()
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (xEU5MaxInDrawDownTradeAge <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// TODO: Complete this ...
|
|
|
|
// //
|
|
// XSignal oldTrades[];
|
|
// xEU5Trader.GetLongTimeTrades(
|
|
// xEU5MaxInDrawDownTradeAge,
|
|
// _Period,
|
|
// X_SIGNAL_UNKNOWN,
|
|
// X_KIND_TRADE,
|
|
// oldTrades);
|
|
// int oldTradesCount = ArraySize(oldTrades);
|
|
// for (int i = 0; i < oldTradesCount; i++)
|
|
// {
|
|
// //
|
|
// XSignal iTrade = oldTrades[i];
|
|
// if (iTrade.profit > 0)
|
|
// {
|
|
// continue;
|
|
// }
|
|
|
|
// //
|
|
// string comment = xEU5Trader.GetSignalLongTimeClosedComment(iTrade);
|
|
// bool isClosed = xEU5Trader.Close(
|
|
// iTrade.ticket,
|
|
// comment);
|
|
// if (isClosed)
|
|
// {
|
|
// //
|
|
// // Issue Alert ...
|
|
// XEU5IssueAlert("Signal (" + (string)iTrade.ticket + ") Closed because of Too Old Age, Profit: " + (string)iTrade.profit);
|
|
// XEU5IssueAlert(comment);
|
|
// }
|
|
// }
|
|
|
|
// //
|
|
// XSignal oldSupports[];
|
|
// xEU5Trader.GetLongTimeTrades(
|
|
// xEU5MaxInDrawDownTradeAge,
|
|
// _Period,
|
|
// X_SIGNAL_UNKNOWN,
|
|
// X_KIND_SUPPORT,
|
|
// oldSupports);
|
|
// int oldSupportsCount = ArraySize(oldSupports);
|
|
// for (int i = 0; i < oldSupportsCount; i++)
|
|
// {
|
|
// //
|
|
// XSignal iTrade = oldSupports[i];
|
|
// if (iTrade.profit > 0)
|
|
// {
|
|
// continue;
|
|
// }
|
|
|
|
// //
|
|
// string comment = xEU5Trader.GetSignalLongTimeClosedComment(iTrade);
|
|
// bool isClosed = xEU5Trader.Close(
|
|
// iTrade.ticket,
|
|
// comment);
|
|
// if (isClosed)
|
|
// {
|
|
// //
|
|
// // Issue Alert ...
|
|
// XEU5IssueAlert("Signal (" + (string)iTrade.ticket + ") Closed because of Too Old Age, Profit: " + (string)iTrade.profit);
|
|
// XEU5IssueAlert(comment);
|
|
// }
|
|
// }
|
|
}
|
|
|
|
//
|
|
// Close All Positions if Balance in Profit ...
|
|
void XEU5CloseAllPositionsInPyramid()
|
|
{
|
|
//
|
|
// TODO: Complete this ...
|
|
|
|
// //
|
|
// double profits = 0;
|
|
|
|
// //
|
|
// XSignal allPositions[];
|
|
// xEU5Trader.GetSignals(allPositions);
|
|
// int allPositionsCount = ArraySize(allPositions);
|
|
// if (allPositionsCount <= 1)
|
|
// {
|
|
// return;
|
|
// }
|
|
|
|
// //
|
|
// // Loop through Positions ...
|
|
// for (int i = 0; i < allPositionsCount; i++)
|
|
// {
|
|
// //
|
|
// XSignal iPosition = allPositions[i];
|
|
|
|
// //
|
|
// profits += iPosition.profit;
|
|
// }
|
|
|
|
// //
|
|
// if (profits > 0)
|
|
// {
|
|
// //
|
|
// XSignal closed[];
|
|
// xEU5Trader.CloseAllPositions(closed);
|
|
// int closedCount = ArraySize(closed);
|
|
// if (closedCount > 0)
|
|
// {
|
|
// //
|
|
// XEU5IssueAlert("Pyramid Closing (" + (string)closedCount + "), Profits: " + (string)profits + " ...");
|
|
|
|
// //
|
|
// ArrayFree(positionHoldings);
|
|
// ArrayResize(positionHoldings, 0);
|
|
// }
|
|
// }
|
|
}
|
|
//
|
|
// END Provided Functions ...
|
|
//
|
|
|
|
//
|
|
// START Private Functions ...
|
|
//
|
|
|
|
//
|
|
// 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 ...
|
|
)
|
|
{
|
|
//
|
|
// Assign default Value ...
|
|
double result = xEU5StaticVolume;
|
|
|
|
//
|
|
// we can count open trades and in draw down trades
|
|
// then do check volume based on it for gridding ...
|
|
XSignal openInProfitTrades[];
|
|
xEU5Trader.GetInProfitSignals(openInProfitTrades);
|
|
int openTrades = ArraySize(openInProfitTrades);
|
|
|
|
//
|
|
// Calculate Normalized Multiplier ...
|
|
double mVolumeMultiplier = xEU5VolumeMultiplier <= 0 ? 1 : xEU5VolumeMultiplier;
|
|
double multiplier = mVolumeMultiplier;
|
|
multiplier = multiplier;
|
|
if (multiplier < 1)
|
|
{
|
|
multiplier = 1;
|
|
}
|
|
|
|
//
|
|
double growRate = xEU5Balance / xEU5Deposit;
|
|
if (growRate >= 1 && multiplier == 1)
|
|
{
|
|
//
|
|
double growDiff = growRate - 1;
|
|
if (growDiff < 1)
|
|
{
|
|
growRate = ((growDiff * 2) * mVolumeMultiplier);
|
|
}
|
|
|
|
//
|
|
multiplier = multiplier * growRate;
|
|
}
|
|
|
|
//
|
|
result = multiplier * xEU5StaticVolume;
|
|
|
|
//
|
|
// Apply Force Multiplier ...
|
|
if (forceMultiplier > 1)
|
|
{
|
|
result *= forceMultiplier;
|
|
}
|
|
|
|
//
|
|
// Check Max Allowed Lottage ...
|
|
double maxAllowedVolume = xEU5MaxSupportedVolumePerTradeInLots;
|
|
if (growRate >= 4 * mVolumeMultiplier)
|
|
{
|
|
maxAllowedVolume *= mVolumeMultiplier;
|
|
}
|
|
|
|
//
|
|
if (openTrades > 0)
|
|
{
|
|
result /= openTrades + 1;
|
|
}
|
|
|
|
//
|
|
if (
|
|
maxAllowedVolume > 0 &&
|
|
result > maxAllowedVolume)
|
|
{
|
|
result = maxAllowedVolume;
|
|
}
|
|
|
|
//
|
|
// Normalize Volume ...
|
|
result = NormalizeVolume(result);
|
|
|
|
//
|
|
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 = {};
|
|
|
|
//
|
|
// TODO: Complete this ...
|
|
|
|
// //
|
|
// // Validate Type ...
|
|
// bool isTypeValid = type == X_SIGNAL_LONG || type == X_SIGNAL_SHORT;
|
|
// if (!isTypeValid)
|
|
// {
|
|
// return result;
|
|
// }
|
|
|
|
// //
|
|
// // Validate Parent Signal ...
|
|
// bool isValidSignal = IsValid(parent, xEU5MagicNumber);
|
|
// 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 ...
|
|
// //
|
|
// // RISKFREE ...
|
|
// double riskFreeRate = parent.riskFree;
|
|
// double riskFreePrice = parent.riskFreeRate;
|
|
|
|
// //
|
|
// // TP ...
|
|
// double tp = MathAbs(parent.tp);
|
|
|
|
// //
|
|
// // SL ...
|
|
// double sl = parent.sl;
|
|
|
|
// //
|
|
// // VOLUME ...
|
|
// int pOpenSupportCount = xEU5Trader.CountSupportedPositions(parent);
|
|
// double volume = parent.volume * forceVolumeMultiplier * xEU5VolumeMultiplier;
|
|
|
|
// //
|
|
// // Force to Increase Volume ...
|
|
// bool isEquityPassed = xEU5Trader.IsEquityReadyForTrade();
|
|
// bool isFreeMarginPassed = xEU5Trader.IsFreeMarginReadyForTrade();
|
|
// bool isBalancePassed = xEU5Trader.IsAccountBalanceReadyForTrade();
|
|
// bool isVolumeOk =
|
|
// isEquityPassed &&
|
|
// isFreeMarginPassed &&
|
|
// isBalancePassed;
|
|
// if (!isVolumeOk)
|
|
// {
|
|
// //
|
|
// volume = NormalizeVolume(volume / 4);
|
|
// if (volume < xEU5StaticVolume)
|
|
// {
|
|
// volume = xEU5StaticVolume;
|
|
// }
|
|
// }
|
|
|
|
// //
|
|
// // Check and Normalize Volume based on MaxAllowed Volume ...
|
|
// if (xEU5MaxSupportedVolumePerTradeInLots > 0 && volume > xEU5MaxSupportedVolumePerTradeInLots)
|
|
// {
|
|
// volume = xEU5MaxSupportedVolumePerTradeInLots;
|
|
// }
|
|
|
|
// //
|
|
// // Normalize Volume ...
|
|
// volume = NormalizeVolume(volume);
|
|
|
|
// //
|
|
// // Generating Support Signal for Parent ...
|
|
// result = xEU5Trader.GenerateSupportSignal(
|
|
// type,
|
|
// tp,
|
|
// sl,
|
|
// volume,
|
|
// riskFreePrice,
|
|
// riskFreeRate,
|
|
// parent.ticket);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Parent Signal Has InDirectional Support Trade or not ...
|
|
bool XEU5HasInDirectionalSupportTrade(
|
|
XSignal &parent // generate support signal for which Trade Kind Position
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// TODO: Complete this ...
|
|
// //
|
|
// // Validate Parent Signal ...
|
|
// bool isValidSignal = IsValid(parent, xEU5MagicNumber);
|
|
// if (!isValidSignal)
|
|
// {
|
|
// return result;
|
|
// }
|
|
|
|
// //
|
|
// ENUM_X_SIGNAL_TYPE inDirectionalSignalType =
|
|
// parent.type == X_SIGNAL_LONG ? X_SIGNAL_SHORT : X_SIGNAL_LONG;
|
|
|
|
// //
|
|
// string inDirectionalComment = xEU5Trader.GenerateInDirectionalSignalComment(parent);
|
|
|
|
// //
|
|
// XSignal allPositions[];
|
|
// xEU5Trader.GetPositionsByKind(
|
|
// inDirectionalSignalType,
|
|
// X_KIND_TRADE,
|
|
// allPositions);
|
|
// int allPositionsCount = ArraySize(allPositions);
|
|
// if (allPositionsCount <= 0)
|
|
// {
|
|
// return result;
|
|
// }
|
|
|
|
// //
|
|
// // Loop Through Signals ...
|
|
// for (int i = 0; i < allPositionsCount; i++)
|
|
// {
|
|
// //
|
|
// XSignal iSignal = allPositions[i];
|
|
|
|
// //
|
|
// // Check Conditions ...
|
|
// if (iSignal.comment == inDirectionalComment)
|
|
// {
|
|
// //
|
|
// result = true;
|
|
// break;
|
|
// }
|
|
// }
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Generate InDirectional Support Signal ...
|
|
XSignal XEU5GenerateInDirectionalSupportSignal(
|
|
XSignal &parent // generate support signal for which Trade Kind Position
|
|
)
|
|
{
|
|
//
|
|
XSignal result = {};
|
|
|
|
//
|
|
// TODO: Complete this ...
|
|
|
|
// //
|
|
// // Validate Parent Signal ...
|
|
// bool isValidSignal = IsValid(parent, xEU5MagicNumber);
|
|
// if (!isValidSignal)
|
|
// {
|
|
// return result;
|
|
// }
|
|
|
|
// //
|
|
// // Check Signal Must be In DrawDown ...
|
|
// if (parent.profit > 0)
|
|
// {
|
|
// return result;
|
|
// }
|
|
|
|
// //
|
|
// ENUM_X_SIGNAL_TYPE type =
|
|
// parent.type == X_SIGNAL_LONG ? X_SIGNAL_SHORT : X_SIGNAL_LONG;
|
|
// bool isLong = type == X_SIGNAL_LONG;
|
|
|
|
// //
|
|
// string comment = xEU5Trader.GenerateInDirectionalSignalComment(parent);
|
|
|
|
// //
|
|
// // Check Has InDirectional Signal Or Not ...
|
|
// bool hasSupport = XEU5HasInDirectionalSupportTrade(parent);
|
|
// if (hasSupport)
|
|
// {
|
|
// return result;
|
|
// }
|
|
|
|
// //
|
|
// double reward = PipsToPrice(6);
|
|
// double riskFreeReward = PipsToPrice(3);
|
|
// double risk = GetSpread() * 2;
|
|
|
|
// //
|
|
// double inEntry = GetEntry(type);
|
|
// double inVolume = NormalizeVolume(parent.volume);
|
|
// double inSL =
|
|
// isLong ? inEntry - risk : inEntry + risk;
|
|
// double inTP =
|
|
// isLong ? inEntry + reward : inEntry - reward;
|
|
// double inRiskFree =
|
|
// isLong ? inEntry + riskFreeReward : inEntry - riskFreeReward;
|
|
// double inRiskFreeRate = 0.5;
|
|
|
|
// //
|
|
// // result = parent;
|
|
// result.sl = inSL;
|
|
// result.tp = inTP;
|
|
// result.type = type;
|
|
// result.entry = inEntry;
|
|
// result.volume = inVolume;
|
|
// result.comment = comment;
|
|
// result.riskFree = inRiskFree;
|
|
// result.riskFreeRate = inRiskFreeRate;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
void XEU5IssueInitializationSucceedAlert()
|
|
{
|
|
//
|
|
string message = "Initializion of (" + XEU5ProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ...";
|
|
XEU5IssueAlert(message);
|
|
}
|
|
|
|
void XEU5IssueDeinitializationSucceedAlert()
|
|
{
|
|
//
|
|
string message = "De Initializion of (" + XEU5ProviderName + " Provider" + ") Succeeded ...";
|
|
XEU5IssueAlert(message);
|
|
}
|
|
|
|
void XEU5IssueForceCloseTradesAlert(ENUM_X_SIGNAL_TYPE type)
|
|
{
|
|
//
|
|
string typeStr = GetSignalType(type);
|
|
if (StringLen(typeStr) == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
string message = "Force Close " + typeStr + " Trades ...";
|
|
XEU5IssueAlert(message);
|
|
}
|
|
|
|
void XEU5IssueMaxAllowedTradesReachedAlert()
|
|
{
|
|
//
|
|
string message = "reached Max Allowed Same Time Trades ...";
|
|
XEU5IssueAlert(message);
|
|
}
|
|
|
|
void XEU5IssueMaxAllowedFreeMarginReachedAlert()
|
|
{
|
|
//
|
|
string message = "reached FreeMarigin For Open Trades ...";
|
|
XEU5IssueAlert(message);
|
|
}
|
|
|
|
void XEU5IssueMinAllowedBalanceReachedAlert()
|
|
{
|
|
//
|
|
string message = "doesn't have Minimum Balance For Open Trades ...";
|
|
XEU5IssueAlert(message);
|
|
}
|
|
|
|
void XEU5IssueSignalExecutionAlert(
|
|
XSignal &signal // Executed Signal
|
|
)
|
|
{
|
|
//
|
|
XEU5IssueAlert(signal);
|
|
}
|
|
|
|
void XEU5IssueSignalExecutionError(int error)
|
|
{
|
|
//
|
|
string message = GetSignalExecutionError(error);
|
|
if (StringLen(message) == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XEU5IssueAlert(message);
|
|
}
|
|
|
|
void XEU5IssueRiskFreeTradesAlert()
|
|
{
|
|
//
|
|
string message = "Make Some Trades Risk Free ...";
|
|
XEU5IssueAlert(message);
|
|
}
|
|
|
|
void XEU5IssueLongInProfitTradeClosed()
|
|
{
|
|
//
|
|
string message = "Closed Long Time in Profit Trades ...";
|
|
XEU5IssueAlert(message);
|
|
}
|
|
|
|
void XEU5IssueLongInDrawdownTradeClosed()
|
|
{
|
|
//
|
|
string message = "Closed Long Time in Profit Trades ...";
|
|
XEU5IssueAlert(message);
|
|
}
|
|
|
|
void XEU5IssueAlert(string message)
|
|
{
|
|
//
|
|
if (xEU5EnableAlerts)
|
|
{
|
|
SendAlert(message);
|
|
}
|
|
else
|
|
{
|
|
LogMessage(message);
|
|
}
|
|
}
|
|
void XEU5IssueAlert(XSignal &signal)
|
|
{
|
|
//
|
|
string signalStr = xEU5Trader.ToString(signal);
|
|
XEU5IssueAlert(signalStr);
|
|
|
|
// //
|
|
// if (xEU5EnableAlerts)
|
|
// {
|
|
// SendAlert(signal);
|
|
// }
|
|
// else
|
|
// {
|
|
// LogSignal(signal);
|
|
// }
|
|
}
|
|
|
|
//
|
|
// Retrieve Holding Position Index ...
|
|
int XEU5GetHoldingPositionIndex(ulong ticket)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int total = ArraySize(positionHoldings);
|
|
if (
|
|
total <= 0 ||
|
|
ticket <= 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < total; i++)
|
|
{
|
|
//
|
|
if (positionHoldings[i].ticket == ticket)
|
|
{
|
|
//
|
|
result = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void Add(
|
|
XEU5_INDIRECTION &item,
|
|
XEU5_INDIRECTION &buffer[])
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
|
|
//
|
|
void Add(
|
|
XEU5_POSITION_HOLDING &item,
|
|
XEU5_POSITION_HOLDING &buffer[])
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
|
|
//
|
|
// Check if a Value Decreasing in Loopback ...
|
|
bool IsDecreasing(
|
|
int from, // Last Time Index
|
|
int to, // Fisr Tima Index
|
|
XEU5_POSITION_HOLDING &holding // the position holding which required to search
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
double prices[];
|
|
for (int i = 0; i < ArraySize(holding.info); i++)
|
|
{
|
|
//
|
|
XEU5_INDIRECTION info = holding.info[i];
|
|
|
|
//
|
|
Add(
|
|
info.profit,
|
|
prices);
|
|
}
|
|
|
|
//
|
|
ArraySetAsSeries(prices, true);
|
|
|
|
//
|
|
result = IsDecreasing(
|
|
to,
|
|
from,
|
|
prices);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//
|
|
// END Private Functions ...
|
|
//
|