Files
xMQL5/BKPS/Series2/XTMPack/x-saherelm.xmap.provider.lib.mq5
T
2024-01-25 04:09:42 +03:30

1371 lines
28 KiB
Plaintext

////////////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 XMAP Signal Provider Library
// --------------------------------------------------------
// Name: XMAPSignalProvider
// Description: XMAP 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
//
// START Inputs ...
//
#include "x-saherelm.xmap.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 *xMAPTrader;
XCAccountInfo xMAPAccountInfo;
//
#include "x-saherelm.xmap.provider.indicators.lib.mq5"
//
// XOHCL xMAPCandles[];
//
double xMAPDeposit = 0;
double xMAPBalance = 0;
double xMAPFreeMargin = 0;
double xMAPMaxDrawDownPerTrade = 0;
double xMAPGridPriceDistance = 0;
double xMAPFreeMarginForOpenTrades = 0;
double xMAPBalanceForOpenTrades = 0;
//
// END Global Definitions: Variables, Properties and etc ...
//
//
// START Provided Functions ...
//
//
// Initial Library if required ...
bool OnInInitXMAPSignalProviderLibrary()
{
//
bool result = false;
//
// Validate Inputs ...
result = XMAPValidateInputs();
if (!result)
{
return result;
}
//
// Init Indicators ...
result = XMAPInitIndicators();
if (!result)
{
return result;
}
//
// Calculations ...
//
// Calculate Account Deposit ...
xMAPDeposit = xMAPAccountInfo.GetInitialBalance();
//
// Calculate Max DrawDown Per Trade ...
if (xMAPMaxDrawDownPerTradeFactor > 0)
{
xMAPMaxDrawDownPerTrade = xMAPDeposit * xMAPMaxDrawDownPerTradeFactor;
}
//
// Calculate Grid Distance Price ...
if (xMAPGridPriceDistanceInPips > 0)
{
xMAPGridPriceDistance = PipsToPrice(xMAPGridPriceDistanceInPips);
}
//
// Calculate Min Balance for Trades ...
if (xMAPBalanceFactorForOpenTrades > 0)
{
xMAPBalanceForOpenTrades = xMAPBalanceFactorForOpenTrades * xMAPDeposit;
}
//
// Claculate Min Free Marging for Trades ...
if (xMAPFreeMarginFactorForOpenTrades > 0)
{
xMAPFreeMarginForOpenTrades = xMAPFreeMarginFactorForOpenTrades * xMAPDeposit;
}
//
// Make XCTrader instance ...
xMAPTrader = new XCTrade(
_Symbol,
xMAPSlippage,
xMAPMagicNumber);
//
result = true;
//
// Logging State ...
string message = "Initializion of (" + "XMAP Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ...";
LogMessage(message);
//
return result;
}
//
// DeInitial Library if required ...
void OnDeinitXMAPSignalProviderLibrary()
{
//
// Release Handlers ...
XMAPReleaseIndicators();
//
// Logging State ...
string message = "De Initializion of (" + "XMAP Provider" + ") Succeeded ...";
LogMessage(message);
}
//
// this is a Globally Function which do all of
// checkings and positions handling ...
void HandleXMAPSignalProviderTick()
{
//
// Update account Balance ...
xMAPBalance = xMAPAccountInfo.GetBalance();
xMAPFreeMargin = xMAPAccountInfo.GetFreeMargin();
//
// Reading Indicator Buffers ...
XMAPHandleReadingBuffers();
if (xMAPCalculatedBars < xMAPMaxLengthOfInputs)
{
return;
}
//
// Handle Open Trades ...
XMAPHandleOpenTrades();
//
// Handle Close Trades ...
XMAPHandleCloseTrades();
//
// XMAPLogTrades();
}
//
// Handle Open Trades ...
void XMAPHandleOpenTrades()
{
//
// Count Max Open Trades ...
bool canOpenPrimaryTrades = true;
if (xMAPMaxAllowedPrimaryTrades > 0)
{
//
int count = XMAPCountPrimaryTrades();
canOpenPrimaryTrades = !(count >= xMAPMaxAllowedPrimaryTrades);
}
//
// Check Free Margin ...
if (xMAPFreeMargin <= xMAPFreeMarginForOpenTrades)
{
return;
}
//
// Check Account Balance ...
if (xMAPBalance <= xMAPBalanceForOpenTrades)
{
return;
}
//
if (canOpenPrimaryTrades)
{
//
// Primary Long Trade ...
if (xMAPAllowLongTrades)
{
//
XSignal primaryLongSignal = {};
bool isPrimaryLongSignalExecuted = XMAPHandlePrimaryLong(primaryLongSignal);
if (isPrimaryLongSignalExecuted)
{
}
}
//
// Primary Short Trade ...
if (xMAPAllowShortTrades)
{
//
XSignal primaryShortSignal = {};
bool isPrimaryShortSignalExecuted = XMAPHandlePrimaryShort(primaryShortSignal);
if (isPrimaryShortSignalExecuted)
{
}
}
}
//
if (xMAPGridPriceDistance > 0 && xMAPMaxAllowedGridTrades > 0)
{
//
bool isGridLongTradeOpened = XMAPHandleGridLong();
if (isGridLongTradeOpened)
{
}
}
}
//
// Handle Close Trades ...
void XMAPHandleCloseTrades()
{
//
// Handle Long/Buy Close ...
if (xMAPTrader.CountLongs() > 0 && XMAPCanCloseLongTrades())
{
//
XSignal closed[];
xMAPTrader.CloseLongPositions(closed);
bool hasClosed = ArraySize(closed) > 0;
if (hasClosed)
{
//
string message = "XMAP Closing Long Trades ...";
if (xMAPEnableAlerts)
{
SendAlert(message);
}
else
{
LogMessage(message);
}
}
}
//
// Handle Short/Sell Close ...
if (xMAPTrader.CountShorts() > 0 && XMAPCanCloseShortTrades())
{
//
XSignal closed[];
xMAPTrader.CloseShortPositions(closed);
bool hasClosed = ArraySize(closed) > 0;
if (hasClosed)
{
//
string message = "XMAP Closing Short Trades ...";
if (xMAPEnableAlerts)
{
SendAlert(message);
}
else
{
LogMessage(message);
}
}
}
//
// MaxDrawDown Trades ...
if (xMAPMaxDrawDownPerTrade > 0)
{
//
XSignal inDrawDownPrimarySignals[];
XSignal closed[];
XMAPGetInDrawDownPrimaryTrades(inDrawDownPrimarySignals);
for (int i = 0; i < ArraySize(inDrawDownPrimarySignals); i++)
{
//
XSignal inDP = inDrawDownPrimarySignals[i];
//
double drawDown = -1 * inDP.profit;
//
bool canClose = drawDown >= xMAPMaxDrawDownPerTrade;
if (!canClose)
{
continue;
}
//
bool isClosed = xMAPTrader.Close(inDP.ticket);
if (isClosed)
{
//
Add(
inDP,
closed);
//
// Check and Close Belongs to Primary Grid Trades ...
// XSignal grids[];
// XMAPGetGridTradesOfPrimary(inDP, grids);
// int gridCount = ArraySize(grids);
// if (gridCount == 0) {
// continue;
// }
// //
// for (int j = 0; j < gridCount; j++) {
// //
// XSignal grid = grids[j];
// bool isGridClosed = xMAPTrader.Close(grid.ticket);
// }
}
}
xMAPTrader.CloseInDrawDownTrades(
xMAPMaxDrawDownPerTrade,
X_SIGNAL_UNKNOWN,
closed);
bool hasClosed = ArraySize(closed) > 0;
if (hasClosed)
{
//
string message = "Close Max DrawDown Trades ...";
if (xMAPEnableAlerts)
{
SendAlert(message);
}
else
{
LogMessage(message);
}
}
}
//
// Close Old Primary Trades ...
if (xMAPMaxPrimaryTradeAge > 0)
{
//
XSignal trades[];
xMAPTrader.GetLongTimeTrades(
xMAPMaxPrimaryTradeAge,
_Period,
trades);
int count = ArraySize(trades);
if (count > 0)
{
//
// Lopp ...
for (int i = 0; i < count; i++)
{
//
XSignal trade = trades[i];
if (!XMAPIsPrimaryTrade(trade))
{
continue;
}
//
bool isClosed = xMAPTrader.Close(trade.ticket);
if (isClosed)
{
//
string message = "Primary: " + (string)trade.ticket + " Closed because of Long Time Passed ...";
if (xMAPEnableAlerts)
{
SendAlert(message);
}
else
{
LogMessage(message);
}
}
}
}
}
//
// Close Old Grid Trades ...
if (xMAPMaxGridTradeAge > 0)
{
//
XSignal trades[];
xMAPTrader.GetLongTimeTrades(
xMAPMaxGridTradeAge,
_Period,
trades);
int count = ArraySize(trades);
if (count > 0)
{
//
// Lopp ...
for (int i = 0; i < count; i++)
{
//
XSignal trade = trades[i];
if (!XMAPIsGridTrade(trade))
{
continue;
}
//
bool isClosed = xMAPTrader.Close(trade.ticket);
if (isClosed)
{
//
string message = "Grid: " + (string)trade.ticket + " Closed because of Long Time Passed ...";
if (xMAPEnableAlerts)
{
SendAlert(message);
}
else
{
LogMessage(message);
}
}
}
}
}
}
//
// Handle Long/Buy for Primary Trades...
bool XMAPHandlePrimaryLong(
XSignal &signal, // return structure if signal founded
bool doTrade = true // do trade on signal
)
{
//
bool result = false;
//
ResetLastError();
//
// && xMAPTrader.CountLongs() == 0 ...
if (XMAPHasPrimaryLongSignal())
{
//
double entry = GetAsk();
double volume = XMAPCalculateVolume();
//
signal.entry = entry;
signal.volume = volume;
signal.symbol = _Symbol;
signal.type = X_SIGNAL_LONG;
signal.magicNumber = xMAPMagicNumber;
signal.time = iTime(_Symbol, _Period, 0);
signal.comment = "Primary_XMAP_Long";
//
// Setting TP ...
signal.tp = XMAPCalculateTP(signal.type);
if (signal.tp == entry)
{
//
result = false;
return result;
}
//
if (enableXMAPProvider && xMAPAllowLongTrades && doTrade)
{
//
// Execute Signal ...
result = xMAPTrader.ExecuteSignal(signal);
//
// Since this means an error happens, we have to log this error ...
if (!result)
{
string errMessage = "failed to execute Long signal: " + (string)GetLastError();
LogMessage(errMessage);
}
}
else
{
result = false;
}
}
//
// Handle Alerts ...
if (result)
{
//
if (xMAPEnableAlerts)
{
SendAlert(signal, true);
}
else
{
LogExecutedSignal(signal);
}
}
//
return result;
}
//
// Handle Short/Sell for Primary Trades...
bool XMAPHandlePrimaryShort(
XSignal &signal, // return structure if signal founded
bool doTrade = true // do trade on signal
)
{
//
bool result = false;
//
ResetLastError();
//
if (XMAPHasPrimaryShortSignal() && xMAPTrader.CountShorts() == 0)
{
//
double entry = GetBid();
double volume = XMAPCalculateVolume();
//
signal.entry = entry;
signal.volume = volume;
signal.symbol = _Symbol;
signal.type = X_SIGNAL_SHORT;
signal.magicNumber = xMAPMagicNumber;
signal.time = iTime(_Symbol, _Period, 0);
signal.comment = "Primary_XMAP_Short";
//
if (enableXMAPProvider && xMAPAllowShortTrades && doTrade)
{
//
// Execute Signal ...
result = xMAPTrader.ExecuteSignal(signal);
//
// Since this means an error happens, we have to log this error ...
if (!result)
{
string errMessage = "failed to execute Short signal: " + (string)GetLastError();
LogMessage(errMessage);
}
}
else
{
result = false;
}
}
//
// Handle Alerts ...
if (result)
{
//
if (xMAPEnableAlerts)
{
SendAlert(signal, true);
}
else
{
LogExecutedSignal(signal);
}
}
//
return result;
}
//
// Handle Long Grid Trades ...
bool XMAPHandleGridLong()
{
//
bool result = false;
//
// Check Grid Long Conditions ...
result = XMAPHasGridLongSignal();
if (!result)
{
return result;
}
//
// Retrieve all In DrawDown Primary Trades ...
XSignal inDrawDownPrimaryTrades[];
XMAPGetInDrawDownPrimaryTrades(inDrawDownPrimaryTrades);
int count = ArraySize(inDrawDownPrimaryTrades);
if (count == 0)
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XSignal primary = inDrawDownPrimaryTrades[i];
if (primary.type != X_SIGNAL_LONG)
{
continue;
}
//
// Check Grids of Primary ...
XSignal grids[];
XMAPGetGridTradesOfPrimary(primary, grids);
int gridsCount = ArraySize(grids);
if (gridsCount >= xMAPMaxAllowedGridTrades)
{
continue;
}
//
XSignal firstGrid = XMAPGetFirstGridOfPrimary(primary);
XSignal latestGrid = XMAPGetLastGridOfPrimary(primary);
bool hasFirsttGrid = IsValid(firstGrid, xMAPMagicNumber) && XMAPIsGridTrade(firstGrid);
bool hasLatestGrid = IsValid(latestGrid, xMAPMagicNumber) && XMAPIsGridTrade(latestGrid);
//
double entry = GetEntry(primary.type);
double latestEntry = hasLatestGrid ? latestGrid.entry : primary.entry;
double entryPriceDiff = (latestEntry - entry);
double gridDistancePrice = xMAPGridPriceDistance;
if (entryPriceDiff >= gridDistancePrice)
{
//
// Here we Can Create a Grid Signal ...
XSignal grid = XMAPGenerateGridSignal(primary, latestGrid);
if (!IsValid(grid, xMAPMagicNumber))
{
continue;
}
//
ResetLastError();
bool isGridExecuted = xMAPTrader.ExecuteSignal(grid);
if (isGridExecuted && !result)
{
//
// if (gridsCount > 1 && hasFirsttGrid)
// {
// //
// bool isClosed = xMAPTrader.Close(firstGrid.ticket);
// }
//
// bool isClosed = xMAPTrader.Close(primary.ticket);
//
result = true;
}
}
}
//
return result;
}
//
// Check Market Conditions to find Long Primary Signals ...
bool XMAPHasPrimaryLongSignal()
{
//
bool result = false;
//
bool isXCHMAHasSignal = XTMCanOpenLongTrades();
//
result =
//
isXCHMAHasSignal
//
;
//
return result;
}
//
// Check Market Conditions to find Short Primary Signals ...
bool XMAPHasPrimaryShortSignal()
{
//
bool result = false;
//
// Check Sell/Short Conditions ...
//
return result;
}
//
// Has Long Grid Signal ...
bool XMAPHasGridLongSignal()
{
//
bool result = false;
//
// Get Long Conditions ...
result = XTMCanOpenLongTrades();
//
return result;
}
//
// Check Market Conditions for closing Long Trades ...
bool XMAPCanCloseLongTrades()
{
//
bool result = false;
//
result = XTMCanCloseLongTrades();
//
return result;
}
//
// Check Market Conditions for closing Short Trades ...
bool XMAPCanCloseShortTrades()
{
//
bool result = false;
//
return result;
}
//
// Calculating Volume for Tradings ...
double XMAPCalculateVolume()
{
//
double result = xMAPStaticVolume;
// if (!xMAPUseDynamicVolume)
// {
// return result;
// }
// //
// double accountBalance = xMAPAccountInfo.GetBalance();
// double balanceIncreased = xMAPBalanceIncreased;
// double volumeIncreased = xMAPVolumeIncreased;
// //
// result = (volumeIncreased * accountBalance) / balanceIncreased;
//
// Normalize Volume ...
result = NormalizeDouble(result, 2);
//
double maxAvailableVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double minAvailableVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
//
// Validate Result ...
if (result > maxAvailableVolume)
{
result = maxAvailableVolume;
}
else if (result < minAvailableVolume)
{
result = minAvailableVolume;
}
//
return result;
}
//
// END Provided Functions ...
//
//
// START Private Functions ...
//
//
// Calculate Signal TP ...
double XMAPCalculateTP(
ENUM_X_SIGNAL_TYPE type // Position Type
)
{
//
double result = 0;
//
// Validate Args ...
if (type == X_SIGNAL_UNKNOWN)
{
return result;
}
//
double ask = GetAsk();
double bid = GetBid();
double spread = GetSpread();
//
bool isLong = type == X_SIGNAL_LONG;
//
double entry = isLong ? ask : bid;
//
// double swingLow = XOBDGetSmallestSwingLow(
// entry,
// numberOfSwings);
// double swingHigh = XOBDGetBiggestSwingHigh(
// entry,
// numberOfSwings);
//
// Find Risk ..
//
double reward = PipsToPrice(xMAPMinRewardPerTradeInPips) + spread;
// swingHigh - entry;
// PipsToPrice(5) + spread;
//
result = isLong ? entry + reward : entry - reward;
// //
// if (result == entry)
// {
// result += PipsToPrice(1);
// }
//
return result;
}
//
// Check a Signal is Primary or not...
bool XMAPIsPrimaryTrade(XSignal &trade)
{
//
bool result = false;
//
int titlePosition = StringFind(trade.comment, "Primary");
result = titlePosition >= 0;
//
return result;
}
//
// Check a Signal is Grid or not...
bool XMAPIsGridTrade(XSignal &trade)
{
//
bool result = false;
//
int titlePosition = StringFind(trade.comment, "Grid");
result = titlePosition >= 0;
//
return result;
}
//
// Retrieve Primary Trades ...
void XMAPGetPrimaryTrades(XSignal &result[])
{
//
CleanBuffer(result);
//
XSignal trades[];
xMAPTrader.GetAllPositions(trades);
int count = ArraySize(trades);
if (count == 0)
{
return;
}
//
for (int i = 0; i < count; i++)
{
//
XSignal trade = trades[i];
if (!XMAPIsPrimaryTrade(trade))
{
continue;
}
//
Add(trade, result);
}
}
int XMAPCountPrimaryTrades()
{
//
int result = 0;
//
XSignal trades[];
XMAPGetPrimaryTrades(trades);
result = ArraySize(trades);
//
return result;
}
//
// Retrieve PrGridimary Trades ...
void XMAPGetGridTrades(XSignal &result[])
{
//
CleanBuffer(result);
//
XSignal trades[];
xMAPTrader.GetAllPositions(trades);
int count = ArraySize(trades);
if (count == 0)
{
return;
}
//
for (int i = 0; i < count; i++)
{
//
XSignal trade = trades[i];
if (!XMAPIsGridTrade(trade))
{
continue;
}
//
Add(trade, result);
}
}
int XMAPCountGridTrades()
{
//
int result = 0;
//
XSignal trades[];
XMAPGetGridTrades(trades);
result = ArraySize(trades);
//
return result;
}
//
// Retrieve In DrawDown Primary Trades ...
void XMAPGetInDrawDownPrimaryTrades(XSignal &result[])
{
//
CleanBuffer(result);
//
XSignal primaryTrades[];
XMAPGetPrimaryTrades(primaryTrades);
int count = ArraySize(primaryTrades);
if (count == 0)
{
return;
}
//
for (int i = 0; i < count; i++)
{
//
XSignal primary = primaryTrades[i];
if (primary.profit > 0)
{
continue;
}
//
Add(primary, result);
}
}
//
// Count In DrawDown Primary Trades ...
int XMAPCountInDrawDownPrimaryTrades()
{
//
int result = 0;
//
XSignal trades[];
XMAPGetInDrawDownPrimaryTrades(trades);
result = ArraySize(trades);
//
return result;
}
//
// Retrieve In Profit Primary Trades ...
void XMAPGetInProfitPrimaryTrades(XSignal &result[])
{
//
CleanBuffer(result);
//
XSignal primaryTrades[];
XMAPGetPrimaryTrades(primaryTrades);
int count = ArraySize(primaryTrades);
if (count == 0)
{
return;
}
//
for (int i = 0; i < count; i++)
{
//
XSignal primary = primaryTrades[i];
if (primary.profit <= 0)
{
continue;
}
//
Add(primary, result);
}
}
//
// Count In Profit Primary Trades ...
int XMAPCountInProfitPrimaryTrades()
{
//
int result = 0;
//
XSignal trades[];
XMAPGetInProfitPrimaryTrades(trades);
result = ArraySize(trades);
//
return result;
}
//
// Generate a Grid Trades Comment based on a Primary Trade ...
string XMAPGetGridTradeComment(XSignal &primary)
{
//
string result = "";
//
if (!XMAPIsPrimaryTrade(primary))
{
return result;
}
//
result = "Grid_" + GetSignalType(primary) + "_Ticket(" + (string)primary.ticket + ")";
//
return result;
}
//
// Check a Grid Trade Belongs to a Primary Trade or not ...
bool XMAPIsGridBelongsToPrimary(
XSignal &grid, // grid signal ...
XSignal &primary // primary signal ...
)
{
//
bool result = false;
//
if (
!XMAPIsGridTrade(grid) ||
grid.type != primary.type ||
!XMAPIsPrimaryTrade(primary))
{
return result;
}
//
string comment = XMAPGetGridTradeComment(primary);
if (StringLen(comment) == 0)
{
return result;
}
//
int titlePosition = StringFind(grid.comment, comment);
result = titlePosition >= 0;
//
return result;
}
//
// Retrieve Grid Trades which belongs to an Specified Primery Trades ...
void XMAPGetGridTradesOfPrimary(
XSignal &primary, // primary trade
XSignal &result[] // hold results
)
{
//
CleanBuffer(result);
//
string comment = XMAPGetGridTradeComment(primary);
if (StringLen(comment) == 0)
{
return;
}
//
// Get all Grid Trades ...
XSignal grids[];
XMAPGetGridTrades(grids);
int count = ArraySize(grids);
if (count == 0)
{
return;
}
//
for (int i = 0; i < count; i++)
{
//
XSignal grid = grids[i];
bool isBelongsToPrimary = XMAPIsGridBelongsToPrimary(
grid,
primary);
if (!isBelongsToPrimary)
{
continue;
}
//
Add(
grid,
result);
}
}
//
// Find Last Grid Trade of a Primary Trade ...
XSignal XMAPGetLastGridOfPrimary(XSignal &primary)
{
//
XSignal result = {};
//
if (!XMAPIsPrimaryTrade(primary))
{
return result;
}
//
XSignal grids[];
XMAPGetGridTradesOfPrimary(primary, grids);
int count = ArraySize(grids);
if (count == 0)
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XSignal grid = grids[i];
//
if (!IsValid(result, xMAPMagicNumber))
{
result = grid;
}
//
if (IsLong(primary))
{
result = grid.entry < result.entry ? grid : result;
}
else if (IsShort(primary))
{
result = grid.entry > result.entry ? grid : result;
}
else
{
continue;
}
}
//
return result;
}
//
// Find First Grid Trade of a Primary Trade ...
XSignal XMAPGetFirstGridOfPrimary(XSignal &primary)
{
//
XSignal result = {};
//
if (!XMAPIsPrimaryTrade(primary))
{
return result;
}
//
XSignal grids[];
XMAPGetGridTradesOfPrimary(primary, grids);
int count = ArraySize(grids);
if (count == 0)
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XSignal grid = grids[i];
//
if (!IsValid(result, xMAPMagicNumber))
{
result = grid;
}
//
if (IsLong(primary))
{
result = grid.entry > result.entry ? grid : result;
}
else if (IsShort(primary))
{
result = grid.entry < result.entry ? grid : result;
}
else
{
continue;
}
}
//
return result;
}
//
// Prepare and Generate XSignal instance for Grid Trades ...
XSignal XMAPGenerateGridSignal(
XSignal &primary, // Main Primary Trade
XSignal &grid // Latest Grid Trade which Belongs to Primary
)
{
//
XSignal result = {};
//
if (!XMAPIsPrimaryTrade(primary))
{
return result;
}
//
bool hasLatestGrid =
IsValid(grid, xMAPMagicNumber) &&
XMAPIsGridBelongsToPrimary(
grid,
primary);
// double gridThreshold = 7;
// double gridVolumeMultiplier = gridsCount < gridThreshold ? 2 : 1;
// double girdVolumeBase = gridsCount < gridThreshold ? grid.volume : primary.volume;
// double volume = NormalizeDouble(girdVolumeBase * gridVolumeMultiplier, 2);
//
bool isLong = primary.type == X_SIGNAL_LONG;
//
double entry = GetEntry(primary.type);
string comment = XMAPGetGridTradeComment(primary);
double volume = NormalizeDouble((hasLatestGrid ? grid.volume : primary.volume) * xMAPGridVolumeMultiplier, 2);
// if (volume >= 7 * primary.volume)
// {
// volume = primary.volume;
// }
//
double reward = NormalizeDouble(MathAbs((hasLatestGrid ? grid.entry : primary.tp) - entry) / 3, _Digits);
double tp = entry + reward;
//
result.tp = tp;
result.entry = entry;
result.sl = primary.sl;
result.volume = volume;
result.comment = comment;
result.type = primary.type;
result.magicNumber = primary.magicNumber;
result.time = iTime(_Symbol, _Period, 0);
//
return result;
}
//
// END Private Functions ...
//