1804 lines
39 KiB
Plaintext
1804 lines
39 KiB
Plaintext
////////////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 XTM Signal Provider Library
|
|
// --------------------------------------------------------
|
|
// Name: XTMSignalProvider
|
|
// Description: XTM 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
|
|
|
|
//
|
|
// Include Models Library ...
|
|
#include "..\Libraries\x-saherelm.models.lib.mq5";
|
|
|
|
//
|
|
// START Inputs ...
|
|
#include "..\Libraries\x-saherelm.xtm.provider.inputs.mq5";
|
|
|
|
//
|
|
// 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 *xTMTrader;
|
|
XCAccountInfo xTMAccountInfo;
|
|
|
|
//
|
|
// Defined Indicator/Oscillator Handlers ...
|
|
//
|
|
// XTM Indicator ...
|
|
int xTMHandler = INVALID_HANDLE;
|
|
double xTMMaBuffer[];
|
|
double xTMStateBuffer[];
|
|
|
|
//
|
|
// XOBD Indicator ...
|
|
int xOBDHandler = INVALID_HANDLE;
|
|
double xOBDSwingsBuffer[];
|
|
|
|
//
|
|
// XTD Oscillator ...
|
|
int xTDHandler = INVALID_HANDLE;
|
|
double xTDBullishBuffer[];
|
|
double xTDBearishBuffer[];
|
|
double xTDStateBuffer[];
|
|
|
|
//
|
|
// XTPD Oscillator ...
|
|
int xTPDHandler = INVALID_HANDLE;
|
|
double xTPDBullishPowerBuffer[];
|
|
double xTPDBearishPowerBuffer[];
|
|
double xTPDStateBuffer[];
|
|
|
|
//
|
|
// XCHMA Oscillator ...
|
|
int xCHMAHandler = INVALID_HANDLE;
|
|
double xCHMALcFastBuffer[];
|
|
double xCHMALcSlowBuffer[];
|
|
double xCHMALcStateBuffer[];
|
|
double xCHMAMcFastBuffer[];
|
|
double xCHMAMcSlowBuffer[];
|
|
double xCHMAMcStateBuffer[];
|
|
double xCHMAScFastBuffer[];
|
|
double xCHMAScSlowBuffer[];
|
|
double xCHMAScStateBuffer[];
|
|
double xCHMAHotStateBuffer[];
|
|
|
|
//
|
|
// this is an important Variable which
|
|
// when it is true, all calculations paused ...
|
|
bool xTMPauseTrading = false;
|
|
//
|
|
// END Global Definitions: Variables, Properties and etc ...
|
|
//
|
|
|
|
//
|
|
// START Provided Functions ...
|
|
//
|
|
//
|
|
// Initial Library if required ...
|
|
bool OnInInitXTMSignalProviderLibrary()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Check Risk Management ...
|
|
if (xTMUseDynamicVolume)
|
|
{
|
|
//
|
|
if (xTMBalanceIncreasedFactor <= 0 || xTMVolumeIncreasedFactor <= 0)
|
|
{
|
|
//
|
|
LogMessage("invalid volume increased factors ...");
|
|
|
|
//
|
|
return result;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
double maxAvailableVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
|
|
double minAvailableVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
|
|
|
|
//
|
|
if (xTMStaticVolume > maxAvailableVolume || xTMStaticVolume < minAvailableVolume)
|
|
{
|
|
//
|
|
LogMessage("invalid static volume ...");
|
|
|
|
//
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Define Handlers ...
|
|
ResetLastError();
|
|
|
|
//
|
|
// XTM Handler ...
|
|
xTMHandler = iCustom(
|
|
_Symbol,
|
|
_Period,
|
|
"x-saherelm.xtm.indicator",
|
|
//
|
|
// Inputs ...
|
|
xTMMaPeriod,
|
|
xTMMaShift,
|
|
xTMMaMethod,
|
|
xTMMaAppliedTo);
|
|
if (xTMHandler == INVALID_HANDLE)
|
|
{
|
|
//
|
|
LogMessage("XTM Provider => error initializing XTM Indicator: " + (string)GetLastError());
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// XTD Handler ...
|
|
xTDHandler = iCustom(
|
|
_Symbol,
|
|
_Period,
|
|
"x-saherelm.xtd.oscillator",
|
|
//
|
|
// Inputs ...
|
|
xTDLength,
|
|
xTDDrawCrosses,
|
|
xTDBullishArrowCode,
|
|
xTDBullishArrowColor,
|
|
xTDBearishArrowCode,
|
|
xTDBearishArrowColor);
|
|
if (xTDHandler == INVALID_HANDLE)
|
|
{
|
|
//
|
|
LogMessage("XTM Provider => error initializing XTD Oscillator: " + (string)GetLastError());
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// XOBD Handler ...
|
|
xOBDHandler = iCustom(
|
|
_Symbol,
|
|
_Period,
|
|
"x-saherelm.xobd.indicator",
|
|
//
|
|
// Inputs ...
|
|
xOBDLength,
|
|
xOBDArrowDistanceFromPrice,
|
|
xOBDSwingHighArrowCode,
|
|
xOBDSwingHighArrowColor,
|
|
xOBDSwingLowArrowCode,
|
|
xOBDSwingLowArrowColor);
|
|
if (xOBDHandler == INVALID_HANDLE)
|
|
{
|
|
//
|
|
LogMessage("XTM Provider => error initializing XOBD Indicator: " + (string)GetLastError());
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// XTPD Handler ...
|
|
xTPDHandler = iCustom(
|
|
_Symbol,
|
|
_Period,
|
|
"x-saherelm.xtpd.oscillator",
|
|
//
|
|
// Inputs ...
|
|
xTPDLength);
|
|
if (xTPDHandler == INVALID_HANDLE)
|
|
{
|
|
//
|
|
LogMessage("XTM Provider => error initializing XTPD Oscillator: " + (string)GetLastError());
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// XCHMA Handler ...
|
|
xCHMAHandler = iCustom(
|
|
_Symbol,
|
|
_Period,
|
|
"x-saherelm.xchma.oscillator",
|
|
//
|
|
// Inputs ...
|
|
"",
|
|
xCHMADrawHotAreas,
|
|
xCHMAHotBullishArrowCode,
|
|
xCHMAHotBullishArrowColor,
|
|
xCHMAHotBearishArrowCode,
|
|
xCHMAHotBearishArrowColor,
|
|
//
|
|
// Long Cycle ...
|
|
"",
|
|
"",
|
|
xCHMALcFastLength,
|
|
xCHMALcSlowLength,
|
|
xCHMALcMethod,
|
|
xCHMALcAppliedTo,
|
|
"",
|
|
xCHMALcDrawWidth,
|
|
xCHMALcDrawType,
|
|
xCHMALcDrawStyle,
|
|
xCHMALcFastColor,
|
|
xCHMALcSlowColor,
|
|
"",
|
|
xCHMALcDrawFast,
|
|
xCHMALcDrawSlow,
|
|
xCHMALcDrawCrosses,
|
|
//
|
|
// Medium Cycle ...
|
|
"",
|
|
"",
|
|
xCHMAMcFastLength,
|
|
xCHMAMcSlowLength,
|
|
xCHMAMcMethod,
|
|
xCHMAMcAppliedTo,
|
|
"",
|
|
xCHMAMcDrawWidth,
|
|
xCHMAMcDrawType,
|
|
xCHMAMcDrawStyle,
|
|
xCHMAMcFastColor,
|
|
xCHMAMcSlowColor,
|
|
"",
|
|
xCHMAMcDrawFast,
|
|
xCHMAMcDrawSlow,
|
|
xCHMAMcDrawCrosses,
|
|
//
|
|
// Short Cycle ...
|
|
"",
|
|
"",
|
|
xCHMAScFastLength,
|
|
xCHMAScSlowLength,
|
|
xCHMAScMethod,
|
|
xCHMAScAppliedTo,
|
|
"",
|
|
xCHMAScDrawWidth,
|
|
xCHMAScDrawType,
|
|
xCHMAScDrawStyle,
|
|
xCHMAScFastColor,
|
|
xCHMAScSlowColor,
|
|
"",
|
|
xCHMAScDrawFast,
|
|
xCHMAScDrawSlow,
|
|
xCHMAScDrawCrosses);
|
|
if (xCHMAHandler == INVALID_HANDLE)
|
|
{
|
|
//
|
|
LogMessage("XTM Provider => error initializing XCHMA Oscillator: " + (string)GetLastError());
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Define Buffer States ...
|
|
ArraySetAsSeries(xTMMaBuffer, true);
|
|
ArraySetAsSeries(xTMStateBuffer, true);
|
|
ArraySetAsSeries(xTDBullishBuffer, true);
|
|
ArraySetAsSeries(xTDBearishBuffer, true);
|
|
ArraySetAsSeries(xTDStateBuffer, true);
|
|
ArraySetAsSeries(xOBDSwingsBuffer, true);
|
|
ArraySetAsSeries(xTPDBullishPowerBuffer, true);
|
|
ArraySetAsSeries(xTPDBearishPowerBuffer, true);
|
|
ArraySetAsSeries(xTPDStateBuffer, true);
|
|
ArraySetAsSeries(xCHMALcFastBuffer, true);
|
|
ArraySetAsSeries(xCHMALcSlowBuffer, true);
|
|
ArraySetAsSeries(xCHMALcStateBuffer, true);
|
|
ArraySetAsSeries(xCHMAMcFastBuffer, true);
|
|
ArraySetAsSeries(xCHMAMcSlowBuffer, true);
|
|
ArraySetAsSeries(xCHMAMcStateBuffer, true);
|
|
ArraySetAsSeries(xCHMAScFastBuffer, true);
|
|
ArraySetAsSeries(xCHMAScSlowBuffer, true);
|
|
ArraySetAsSeries(xCHMAScStateBuffer, true);
|
|
ArraySetAsSeries(xCHMAHotStateBuffer, true);
|
|
|
|
//
|
|
// Make XCTrader instance ...
|
|
xTMTrader = new XCTrade(
|
|
_Symbol,
|
|
xTMSlippage,
|
|
xTMMagicNumber);
|
|
|
|
//
|
|
result = true;
|
|
|
|
//
|
|
// Logging State ...
|
|
string message = "Initializion of (" + "XTM Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ...";
|
|
LogMessage(message);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// DeInitial Library if required ...
|
|
void OnDeinitXTMSignalProviderLibrary()
|
|
{
|
|
//
|
|
// Logging State ...
|
|
string message = "De Initializion of (" + "XTM Provider" + ") Succeeded ...";
|
|
LogMessage(message);
|
|
}
|
|
|
|
//
|
|
// this is a Globally Function which do all of
|
|
// checkings and positions handling ...
|
|
void HandleXTMSignalProviderTick()
|
|
{
|
|
//
|
|
if (xTMPauseTrading)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Copy required Buffers for handle processing and check Market Conditions ...
|
|
XTMReadingBuffers();
|
|
|
|
//
|
|
// Handle Open Trades ...
|
|
XTMHandleOpenTrades();
|
|
|
|
//
|
|
// Handle Close Trades ...
|
|
XTMHandleCloseTrades();
|
|
}
|
|
|
|
//
|
|
// Reading all required data from indicator/oscillator(s) Buffers ...
|
|
void XTMReadingBuffers()
|
|
{
|
|
//
|
|
// XTM Lines ...
|
|
CopyBuffer(
|
|
xTMHandler,
|
|
X_XTM_MA_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xTMMaBuffer);
|
|
CopyBuffer(
|
|
xTMHandler,
|
|
X_XTM_STATE_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xTMStateBuffer);
|
|
|
|
//
|
|
// XTD Lines ...
|
|
CopyBuffer(
|
|
xTDHandler,
|
|
X_XTD_BULLISH_POWER_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xTDBullishBuffer);
|
|
CopyBuffer(
|
|
xTDHandler,
|
|
X_XTD_BEARISH_POWER_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xTDBearishBuffer);
|
|
CopyBuffer(
|
|
xTDHandler,
|
|
X_XTD_TREND_STATE_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xTDStateBuffer);
|
|
|
|
//
|
|
// XOBD Lines ...
|
|
CopyBuffer(
|
|
xOBDHandler,
|
|
0,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xOBDSwingsBuffer);
|
|
|
|
//
|
|
// XTPD Lines ...
|
|
CopyBuffer(
|
|
xTPDHandler,
|
|
X_XTPD_BULLISH_POWER_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xTPDBullishPowerBuffer);
|
|
CopyBuffer(
|
|
xTPDHandler,
|
|
X_XTPD_BEARISH_POWER_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xTPDBearishPowerBuffer);
|
|
CopyBuffer(
|
|
xTPDHandler,
|
|
X_XTPD_STATE_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xTPDStateBuffer);
|
|
|
|
//
|
|
// XCHMA Buffer Readings ...
|
|
CopyBuffer(
|
|
xCHMAHandler,
|
|
X_XCHMA_LC_FAST_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xCHMALcFastBuffer);
|
|
CopyBuffer(
|
|
xCHMAHandler,
|
|
X_XCHMA_LC_SLOW_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xCHMALcSlowBuffer);
|
|
CopyBuffer(
|
|
xCHMAHandler,
|
|
X_XCHMA_LC_STATE_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xCHMALcStateBuffer);
|
|
CopyBuffer(
|
|
xCHMAHandler,
|
|
X_XCHMA_MC_FAST_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xCHMAMcFastBuffer);
|
|
CopyBuffer(
|
|
xCHMAHandler,
|
|
X_XCHMA_MC_SLOW_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xCHMAMcSlowBuffer);
|
|
CopyBuffer(
|
|
xCHMAHandler,
|
|
X_XCHMA_MC_STATE_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xCHMAMcStateBuffer);
|
|
CopyBuffer(
|
|
xCHMAHandler,
|
|
X_XCHMA_SC_FAST_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xCHMAScFastBuffer);
|
|
CopyBuffer(
|
|
xCHMAHandler,
|
|
X_XCHMA_SC_SLOW_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xCHMAScSlowBuffer);
|
|
CopyBuffer(
|
|
xCHMAHandler,
|
|
X_XCHMA_SC_STATE_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xCHMAScStateBuffer);
|
|
CopyBuffer(
|
|
xCHMAHandler,
|
|
X_XCHMA_HOT_STATE_LINE,
|
|
0,
|
|
xTMNumberOfItemsPerTick,
|
|
xCHMAHotStateBuffer);
|
|
}
|
|
|
|
//
|
|
// Check Market Conditions to find Long Primary Signals ...
|
|
bool XTMHasPrimaryLongSignal()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Check MArket Conditions Based On XCHMA Oscillator for Long Signals ...
|
|
// METHOD: we have to read HotStateBuffer and LCStateBuffer ...
|
|
//
|
|
// Check Hot Bullish State ...
|
|
bool isXCHMAHotBullishState =
|
|
xCHMAHotStateBuffer[1] == X_XCHMA_HOT_BULLISH && xCHMAHotStateBuffer[2] != X_XCHMA_HOT_BULLISH;
|
|
|
|
//
|
|
// Check Hot Bearish State ...
|
|
bool isXCHMAHotBearishState =
|
|
xCHMAHotStateBuffer[1] == X_XCHMA_HOT_BEARISH && xCHMAHotStateBuffer[2] != X_XCHMA_HOT_BEARISH;
|
|
|
|
//
|
|
// Check LC Fast Cross Over Slow ...
|
|
bool isXCHMALCFastCrossedOverSlow =
|
|
xCHMALcStateBuffer[1] == X_XCHMA_FAST_CROSSED_OVER_SLOW && xCHMALcStateBuffer[2] != X_XCHMA_FAST_CROSSED_OVER_SLOW;
|
|
|
|
//
|
|
// Check LC Fast Cross Under Slow ...
|
|
bool isXCHMALCFastCrossedUnderSlow =
|
|
xCHMALcStateBuffer[1] == X_XCHMA_FAST_CROSSED_UNDER_SLOW && xCHMALcStateBuffer[2] != X_XCHMA_FAST_CROSSED_UNDER_SLOW;
|
|
|
|
//
|
|
// Check Buy/Long Conditions ...
|
|
result = xTMAllowLongTrades &&
|
|
isXCHMAHotBullishState &&
|
|
isXCHMALCFastCrossedOverSlow;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Market Conditions to find Short Primary Signals ...
|
|
bool XTMHasPrimaryShortSignal()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Check Sell/Short Conditions ...
|
|
result = xTMAllowShortTrades &&
|
|
xTDStateBuffer[1] == X_XTD_BULLISH_CROSSED_UNDER_BEARISH && xTDStateBuffer[2] != X_XTD_BULLISH_CROSSED_UNDER_BEARISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Market Conditions for Grid Long Signals ...
|
|
bool XTMHasGridLongSignal()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// XCHMA ...
|
|
bool isXCHMAPassed = xCHMAScFastBuffer[1] < xCHMAScSlowBuffer[1] && xCHMAScFastBuffer[1] < xCHMAMcFastBuffer[1] && xCHMAScFastBuffer[1] < xCHMAMcSlowBuffer[1] && xCHMAScFastBuffer[1] < xCHMALcFastBuffer[1] && xCHMAScFastBuffer[1] < xCHMALcSlowBuffer[1] && xCHMAScFastBuffer[1] > xCHMAScFastBuffer[2];
|
|
|
|
//
|
|
// XCMA Medium Cycle ...
|
|
// bool isXCHMAMCPassed = xCHMAMcStateBuffer[1] == X_XCHMA_FAST_CROSSED_OVER_SLOW && xCHMAMcStateBuffer[2] != X_XCHMA_FAST_CROSSED_OVER_SLOW;
|
|
|
|
//
|
|
// XTD ...
|
|
// bool isXTDPassed = xTDStateBuffer[1] == X_XTD_BULLISH_CROSSED_OVER_BEARISH && xTDStateBuffer[2] != X_XTD_BULLISH_CROSSED_OVER_BEARISH;
|
|
|
|
//
|
|
// Check Market Conditions for Long Entry Grid Trades ...
|
|
result =
|
|
// isXTDPassed ||
|
|
isXCHMAPassed
|
|
// ||
|
|
// isXCHMAMCPassed
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Market Conditions for Grid Short Signals ...
|
|
bool XTMHasGridShortSignal()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Market Conditions for closing Long Trades ...
|
|
bool XTMCanCloseLongTrades()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// result = (xTDStateBuffer[1] != X_XTD_BULLISH_OVER_BEARISH && xTDStateBuffer[1] != X_XTD_BULLISH_CROSSED_OVER_BEARISH) && xTDStateBuffer[2] == X_XTD_BULLISH_OVER_BEARISH;
|
|
|
|
//
|
|
// We Want to Close Long Trades When all XCHMA's is Down ...
|
|
// Hot Bearish Area ...
|
|
// result = xCHMAHotStateBuffer[1] == X_XCHMA_HOT_BEARISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Market Conditions for closing Short Trades ...
|
|
bool XTMCanCloseShortTrades()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Handle Long/Buy for Primary Trades...
|
|
bool XTMHandlePrimaryLong(
|
|
XSignal &signal, // return structure if signal founded
|
|
bool doTrade = true // do trade on signal
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (!xTMAllowLongTrades)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ResetLastError();
|
|
|
|
//
|
|
// && xTMTrader.CountLongs() == 0
|
|
if (XTMHasPrimaryLongSignal())
|
|
{
|
|
//
|
|
double entry = GetAsk();
|
|
double volume = XTMCalculateVolume();
|
|
|
|
//
|
|
bool canDoTrade =
|
|
!xTMPauseTrading &&
|
|
XTMIsReadyForPrimaryTrades();
|
|
|
|
//
|
|
XTPSL mTpSl = XTMCalculateTPSL(X_SIGNAL_LONG, entry);
|
|
if (IsValid(mTpSl))
|
|
{
|
|
//
|
|
signal.tp = mTpSl.tp;
|
|
signal.sl = 0; // mTpSl.sl;
|
|
}
|
|
|
|
//
|
|
signal.entry = entry;
|
|
signal.volume = volume;
|
|
signal.symbol = _Symbol;
|
|
signal.type = X_SIGNAL_LONG;
|
|
signal.magicNumber = xTMMagicNumber;
|
|
signal.time = iTime(_Symbol, _Period, 0);
|
|
signal.comment = "Primary_XTM_Long";
|
|
|
|
//
|
|
if (enableXTMProvider && xTMAllowLongTrades && doTrade && canDoTrade)
|
|
{
|
|
//
|
|
// Execute Signal ...
|
|
result = xTMTrader.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 (xTMEnableAlerts)
|
|
{
|
|
SendAlert(signal, true);
|
|
}
|
|
else
|
|
{
|
|
LogExecutedSignal(signal);
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Handle Short/Sell for Primary Trades...
|
|
bool XTMHandlePrimaryShort(
|
|
XSignal &signal, // return structure if signal founded
|
|
bool doTrade = true // do trade on signal
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (!xTMAllowShortTrades)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ResetLastError();
|
|
|
|
//
|
|
if (XTMHasPrimaryShortSignal() && xTMTrader.CountShorts() == 0)
|
|
{
|
|
//
|
|
double entry = GetBid();
|
|
double volume = XTMCalculateVolume();
|
|
|
|
//
|
|
bool canDoTrade =
|
|
!xTMPauseTrading &&
|
|
XTMIsReadyForPrimaryTrades();
|
|
|
|
//
|
|
XTPSL mTpSl = XTMCalculateTPSL(X_SIGNAL_SHORT, entry);
|
|
if (IsValid(mTpSl))
|
|
{
|
|
//
|
|
signal.tp = mTpSl.tp;
|
|
signal.sl = mTpSl.sl;
|
|
}
|
|
|
|
//
|
|
signal.entry = entry;
|
|
signal.volume = volume;
|
|
signal.symbol = _Symbol;
|
|
signal.type = X_SIGNAL_SHORT;
|
|
signal.magicNumber = xTMMagicNumber;
|
|
signal.time = iTime(_Symbol, _Period, 0);
|
|
signal.comment = "Primary_XTM_Short";
|
|
|
|
//
|
|
if (enableXTMProvider && xTMAllowShortTrades && doTrade && canDoTrade)
|
|
{
|
|
//
|
|
// Execute Signal ...
|
|
result = xTMTrader.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 (xTMEnableAlerts)
|
|
{
|
|
SendAlert(signal, true);
|
|
}
|
|
else
|
|
{
|
|
LogExecutedSignal(signal);
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Handle Grid Long Trades ...
|
|
void XTMHandleGridLong()
|
|
{
|
|
//
|
|
if (!enableXTMProvider || !xTMAllowLongTrades || !xTMEnableGridTrades)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XSignal primaryLongs[];
|
|
XTMRetrievePrimaryTradesOfType(
|
|
X_SIGNAL_LONG,
|
|
primaryLongs);
|
|
int count = ArraySize(primaryLongs);
|
|
if (count == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
double price = GetAsk();
|
|
double spread = GetSpread();
|
|
double lastPrice = 0;
|
|
double lastVolume = 0;
|
|
|
|
//
|
|
// Calculate Price Distance ...
|
|
double priceDiff = PipsToPrice(xTMGridDistanceInPips);
|
|
|
|
//
|
|
// Primary Long Loop ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XSignal primary = primaryLongs[i];
|
|
if (!XTMIsPrimaryTrade(primary))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Retrieve Last Price for Grid Entry ...
|
|
XSignal latestGridSignal = XTMRetrieveLastGridTradesOfPrimary(primary);
|
|
if (
|
|
!XTMIsGridTrade(latestGridSignal) ||
|
|
latestGridSignal.type != primary.type ||
|
|
!IsValid(latestGridSignal, xTMMagicNumber))
|
|
{
|
|
//
|
|
lastPrice = primary.entry;
|
|
lastVolume = primary.volume;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
lastPrice = latestGridSignal.entry;
|
|
lastVolume = latestGridSignal.volume;
|
|
}
|
|
|
|
//
|
|
// Check Market Conditions for Grid Long Signals ...
|
|
bool canDoGridTrade = XTMHasGridLongSignal() && price <= lastPrice - priceDiff;
|
|
if (canDoGridTrade)
|
|
{
|
|
//
|
|
// Open a Long Grid Position ...
|
|
double volumeMultiplier = (primary.entry - price) / priceDiff;
|
|
double volume = NormalizeDouble(lastVolume * (volumeMultiplier * xTMGridVolumeMultiplier), 2); // NormalizeDouble(lastVolume * xTMGridVolumeMultiplier, 2);
|
|
string comment = "Grid_XTM_Long_" + XTMGenerateTicketTitle(primary.ticket);
|
|
|
|
//
|
|
XSignal gridLong = {};
|
|
|
|
//
|
|
gridLong.entry = price;
|
|
gridLong.volume = volume;
|
|
gridLong.symbol = _Symbol;
|
|
gridLong.type = X_SIGNAL_LONG;
|
|
gridLong.magicNumber = xTMMagicNumber;
|
|
gridLong.time = iTime(_Symbol, _Period, 0);
|
|
gridLong.comment = comment;
|
|
|
|
//
|
|
XTPSL mTpSl = XTMCalculateTPSL(X_SIGNAL_LONG, price);
|
|
if (IsValid(mTpSl))
|
|
{
|
|
//
|
|
gridLong.tp = price + (100 * _Point) + spread;
|
|
gridLong.sl = 0;
|
|
}
|
|
|
|
//
|
|
// Execute Signal ...
|
|
bool isExecuted = xTMTrader.ExecuteSignal(gridLong);
|
|
if (isExecuted)
|
|
{
|
|
//
|
|
// Handle Alert and Log ...
|
|
if (xTMEnableAlerts)
|
|
{
|
|
SendAlert(gridLong, true);
|
|
}
|
|
else
|
|
{
|
|
LogExecutedSignal(gridLong);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle Open Trades ...
|
|
void XTMHandleOpenTrades()
|
|
{
|
|
//
|
|
// Check Provider is Enable ...
|
|
if (!enableXTMProvider)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Primary Long Trade ...
|
|
if (xTMAllowLongTrades)
|
|
{
|
|
//
|
|
XSignal primaryLongSignal = {};
|
|
bool isPrimaryLongSignalExecuted = XTMHandlePrimaryLong(primaryLongSignal);
|
|
|
|
//
|
|
// Handle Grid Trades ...
|
|
if (xTMEnableGridTrades)
|
|
{
|
|
XTMHandleGridLong();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Primary Short Trade ...
|
|
if (xTMAllowShortTrades)
|
|
{
|
|
//
|
|
XSignal primaryShortSignal = {};
|
|
bool isPrimaryShortSignalExecuted = XTMHandlePrimaryShort(primaryShortSignal);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle Close Trades ...
|
|
void XTMHandleCloseTrades()
|
|
{
|
|
//
|
|
// Close Conditional Long Trades ...
|
|
if (xTMAllowLongTrades)
|
|
{
|
|
//
|
|
// Handle Long/Buy Close ...
|
|
if (xTMTrader.CountLongs() > 0 && XTMCanCloseLongTrades())
|
|
{
|
|
//
|
|
xTMTrader.CloseLongPositions();
|
|
|
|
//
|
|
string message = "XTM Closing Long Trades ...";
|
|
|
|
//
|
|
if (xTMEnableAlerts)
|
|
{
|
|
SendAlert(message);
|
|
}
|
|
else
|
|
{
|
|
LogMessage(message);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close Conditional Short Trades ...
|
|
if (xTMAllowShortTrades)
|
|
{
|
|
//
|
|
// Handle Short/Sell Close ...
|
|
if (xTMTrader.CountShorts() > 0 && XTMCanCloseShortTrades())
|
|
{
|
|
//
|
|
xTMTrader.CloseShortPositions();
|
|
|
|
//
|
|
string message = "XTM Closing Short Trades ...";
|
|
|
|
//
|
|
if (xTMEnableAlerts)
|
|
{
|
|
SendAlert(message);
|
|
}
|
|
else
|
|
{
|
|
LogMessage(message);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close Long Time Trades ...
|
|
if (xTMMaximumTradeLife > 0)
|
|
{
|
|
//
|
|
bool hasLongTimeTradeClosed = xTMTrader.CloseLongTimeTrades(
|
|
xTMMaximumTradeLife,
|
|
_Period);
|
|
if (hasLongTimeTradeClosed)
|
|
{
|
|
//
|
|
string message = "Close Long Time Trades ...";
|
|
if (xTMEnableAlerts)
|
|
{
|
|
SendAlert(message);
|
|
}
|
|
else
|
|
{
|
|
LogMessage(message);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close MAximum DrawDown Trades ...
|
|
if (xTMMaximumAllowedDrawDownFactorPerTrade > 0)
|
|
{
|
|
//
|
|
// Calculate Max Available DrawDown per Trade ...
|
|
double deposit = xTMAccountInfo.GetInitialBalance();
|
|
double maxAllowedDrawDown = xTMMaximumAllowedDrawDownFactorPerTrade * deposit;
|
|
|
|
//
|
|
// Try To Find and Close In Max DrawDown Trades ...
|
|
bool hasInDrawDownTradeClosed = xTMTrader.CloseInDrawDownTrades(maxAllowedDrawDown);
|
|
if (hasInDrawDownTradeClosed)
|
|
{
|
|
//
|
|
string message = "Close Max DrawDown Trades ...";
|
|
if (xTMEnableAlerts)
|
|
{
|
|
SendAlert(message);
|
|
}
|
|
else
|
|
{
|
|
LogMessage(message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Calculating Volume for Tradings ...
|
|
double XTMCalculateVolume()
|
|
{
|
|
//
|
|
double result = xTMStaticVolume;
|
|
if (!xTMUseDynamicVolume)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double balance = xTMAccountInfo.GetBalance();
|
|
double deposit = xTMAccountInfo.GetInitialBalance();
|
|
double balanceIncreasedRate = xTMBalanceIncreasedFactor * deposit;
|
|
double volumeIncreasedRate = xTMVolumeIncreasedFactor;
|
|
|
|
//
|
|
// result = (volumeIncreased * accountBalance) / balanceIncreased;
|
|
result = (balance / balanceIncreasedRate) * volumeIncreasedRate;
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// Find MIN Swing Low ...
|
|
double XTMGetMinSwingLow()
|
|
{
|
|
//
|
|
double result = EMPTY_VALUE;
|
|
|
|
//
|
|
double xOBDSwings[];
|
|
ArraySetAsSeries(xOBDSwings, true);
|
|
|
|
//
|
|
XTMReadingSwings(50, xOBDSwings);
|
|
|
|
//
|
|
// Loopp through retrieved Swings ...
|
|
int count = 0;
|
|
int swingsCountForResult = 3;
|
|
for (int i = 0; i < ArraySize(xOBDSwings) && count < swingsCountForResult; i++)
|
|
{
|
|
//
|
|
if (xOBDSwings[i] == X_SWING_LOW)
|
|
{
|
|
//
|
|
count++;
|
|
|
|
//
|
|
XOHCL candle = GetCandle(i + 4);
|
|
|
|
//
|
|
result = result == EMPTY_VALUE ? candle.low : MathMin(result, candle.low);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Free Array ...
|
|
ArrayFree(xOBDSwings);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Reading Swing Buffers from XOBD Indicator ...
|
|
void XTMReadingSwings(
|
|
int count,
|
|
double &result[])
|
|
{
|
|
//
|
|
CopyBuffer(
|
|
xOBDHandler,
|
|
0,
|
|
0,
|
|
count,
|
|
result);
|
|
}
|
|
|
|
//
|
|
// Check Provider Ready for Primary Trades ...
|
|
bool XTMIsReadyForPrimaryTrades()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
bool isEquityPassed = XTMCheckAccountEquity();
|
|
bool isBalancePassed = XTMCheckAccountBalance();
|
|
bool isTradesCountPassed = XTMCheckMaxOpenTrades();
|
|
|
|
//
|
|
result =
|
|
isEquityPassed &&
|
|
isBalancePassed &&
|
|
isTradesCountPassed;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Provider Ready for Grid Trades ...
|
|
bool XTMIsReadyForGridTrades()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
bool isBalancePassed = XTMCheckAccountBalance();
|
|
|
|
//
|
|
result =
|
|
isBalancePassed;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Max Open Trades is Valid or not ...
|
|
bool XTMCheckMaxOpenTrades()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (xTMMaxOpenTrades <= 0)
|
|
{
|
|
//
|
|
result = true;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Count Long Open Trades ...
|
|
int totalLongTrades = xTMTrader.CountLongs();
|
|
|
|
//
|
|
// Count Short Open Trades ...
|
|
int totalShortTrades = xTMTrader.CountShorts();
|
|
|
|
//
|
|
// Count all Open Positions ...
|
|
int totalTrades = xTMTrader.Count();
|
|
|
|
//
|
|
// Check Total Longs and Shorts Below or Equals to Max Open Trade Value ...
|
|
result = totalTrades < xTMMaxOpenTrades;
|
|
// totalLongTrades <= xTMMaxOpenTrades && totalShortTrades <= xTMMaxOpenTrades;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Max Equity for Trades ...
|
|
bool XTMCheckAccountEquity()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (xTMMaximumEquityFactorForTrade <= 0)
|
|
{
|
|
//
|
|
result = true;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double equity = xTMAccountInfo.GetEquity();
|
|
double balance = xTMAccountInfo.GetBalance();
|
|
double initialBalance = xTMAccountInfo.GetInitialBalance();
|
|
|
|
//
|
|
double maxAvailableEquity = balance - (xTMMaximumEquityFactorForTrade * initialBalance);
|
|
|
|
//
|
|
result = equity > maxAvailableEquity;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Account Balance For Trades ...
|
|
bool XTMCheckAccountBalance()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (xTMMinimumBalanceFactorForTrade <= 0)
|
|
{
|
|
//
|
|
result = true;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double balance = xTMAccountInfo.GetBalance();
|
|
double initialBalance = xTMAccountInfo.GetInitialBalance();
|
|
|
|
//
|
|
double minRequiredBalance = initialBalance * xTMMinimumBalanceFactorForTrade;
|
|
|
|
//
|
|
// Check Balance Bigger than Minimum Required ...
|
|
result = balance > minRequiredBalance;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate TP and SL ...
|
|
XTPSL XTMCalculateTPSL(
|
|
ENUM_X_SIGNAL_TYPE type, // Which Type to Calculate TP and SL
|
|
double entry // Signal Entry Price
|
|
)
|
|
{
|
|
//
|
|
XTPSL result = {};
|
|
result.type = X_SIGNAL_UNKNOWN;
|
|
result.tp = 0;
|
|
result.sl = 0;
|
|
result.r2r = 0;
|
|
result.entry = 0;
|
|
|
|
// //
|
|
// if (!xTMUseTPSL)
|
|
// {
|
|
// return result;
|
|
// }
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (entry <= 0 || type == X_SIGNAL_UNKNOWN)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result.type = type;
|
|
result.r2r = xTMR2r;
|
|
result.entry = entry;
|
|
|
|
//
|
|
bool isLong = type == X_SIGNAL_LONG;
|
|
|
|
//
|
|
// Retrieve Market Highest High and Lowest Low ...
|
|
double hh = GetHighestHigh(
|
|
xTMLoopback,
|
|
0);
|
|
double ll = GetLowestLow(
|
|
xTMLoopback,
|
|
0);
|
|
|
|
// //
|
|
// double maxRisk = xTMMaxRiskPerTrade * _Point;
|
|
// double minRisk = xTMMinRiskPerTrade * _Point;
|
|
|
|
//
|
|
// Calculate Long SL ...
|
|
double longSwingSL = XTMGetMinSwingLow();
|
|
longSwingSL = NormalizeDouble(longSwingSL, _Digits);
|
|
|
|
//
|
|
// Calculate and Normalize risk ...
|
|
double risk = isLong ? entry - ll : hh - entry;
|
|
// if (risk > maxRisk)
|
|
// {
|
|
// risk = maxRisk;
|
|
// }
|
|
// else if (risk < minRisk)
|
|
// {
|
|
// risk = minRisk;
|
|
// }
|
|
|
|
//
|
|
double reward = risk * xTMR2r; // 30 * _Point; // risk * xTMR2r;
|
|
|
|
//
|
|
double tp = isLong ? entry + reward : entry - reward;
|
|
double sl = isLong ? entry - risk : entry + risk; // swingSL; // isLong ? entry - risk : entry + risk;
|
|
|
|
//
|
|
tp = NormalizeDouble(tp, _Digits);
|
|
sl = NormalizeDouble(sl, _Digits);
|
|
|
|
//
|
|
result.tp = tp;
|
|
result.sl = isLong ? longSwingSL : 0; // swingSL; // sl;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Generate Ticket Title for Signal ...
|
|
string XTMGenerateTicketTitle(ulong ticket)
|
|
{
|
|
//
|
|
string result = "Ticket(" + (string)ticket + ")";
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Determines a Signal is Primary or not ...
|
|
bool XTMIsPrimaryTrade(
|
|
XSignal &signal)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int titlePosition = StringFind(
|
|
signal.comment,
|
|
"Primary");
|
|
result = titlePosition >= 0;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Determines a Signal is Grid or not ...
|
|
bool XTMIsGridTrade(
|
|
XSignal &signal)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int titlePosition = StringFind(
|
|
signal.comment,
|
|
"Grid");
|
|
result = titlePosition >= 0;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check a Signal Comment Contains Specific Ticket ...
|
|
bool XTMIsSignalContainsTicketComment(
|
|
ulong ticket, // specified ticket which going to check ...
|
|
XSignal &signal // the signal object which going to compare ...
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Generate Ticket Title ...
|
|
string title = XTMGenerateTicketTitle(ticket);
|
|
int titlePosition = StringFind(signal.comment, title);
|
|
result = titlePosition >= 0;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve All Primary Trades ...
|
|
void XTMRetrievePrimaryTrades(XSignal &result[])
|
|
{
|
|
//
|
|
ArrayFree(result);
|
|
ArrayResize(result, 0);
|
|
|
|
//
|
|
XSignal allSignals[];
|
|
xTMTrader.GetAllPositions(allSignals);
|
|
|
|
//
|
|
if (ArraySize(allSignals) <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Loop Through all Positions and Extract Primary Trades ...
|
|
for (int i = 0; i < ArraySize(allSignals); i++)
|
|
{
|
|
//
|
|
XSignal signal = allSignals[i];
|
|
|
|
//
|
|
bool isPrimary = XTMIsPrimaryTrade(signal);
|
|
if (!isPrimary)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ArrayResize(
|
|
result,
|
|
ArraySize(result) + 1);
|
|
result[ArraySize(result) - 1] = signal;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve All Primary Spcified Type Trades ...
|
|
void XTMRetrievePrimaryTradesOfType(
|
|
ENUM_X_SIGNAL_TYPE type, // Specify Signal Type ...
|
|
XSignal &result[] // hold results ...
|
|
)
|
|
{
|
|
//
|
|
ArrayFree(result);
|
|
ArrayResize(result, 0);
|
|
|
|
//
|
|
XSignal allSignals[];
|
|
XTMRetrievePrimaryTrades(allSignals);
|
|
|
|
//
|
|
if (ArraySize(allSignals) <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Loop Through all Positions and Extract Primary Trades ...
|
|
for (int i = 0; i < ArraySize(allSignals); i++)
|
|
{
|
|
//
|
|
XSignal signal = allSignals[i];
|
|
|
|
//
|
|
if (signal.type != type)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ArrayResize(
|
|
result,
|
|
ArraySize(result) + 1);
|
|
result[ArraySize(result) - 1] = signal;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve All Grid Trades ...
|
|
void XTMRetrieveGridTrades(XSignal &result[])
|
|
{
|
|
//
|
|
ArrayFree(result);
|
|
ArrayResize(result, 0);
|
|
|
|
//
|
|
XSignal allSignals[];
|
|
xTMTrader.GetAllPositions(allSignals);
|
|
|
|
//
|
|
if (ArraySize(allSignals) <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Loop Through all Positions and Extract Grid Trades ...
|
|
for (int i = 0; i < ArraySize(allSignals); i++)
|
|
{
|
|
//
|
|
XSignal signal = allSignals[i];
|
|
|
|
//
|
|
bool isGrid = XTMIsGridTrade(signal);
|
|
if (!isGrid)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ArrayResize(
|
|
result,
|
|
ArraySize(result) + 1);
|
|
result[ArraySize(result) - 1] = signal;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve All Grid Specific Type Trades ...
|
|
void XTMRetrieveGridTradesOfType(
|
|
ENUM_X_SIGNAL_TYPE type, // Specify Signal Type ...
|
|
XSignal &result[] // hold results ...
|
|
)
|
|
{
|
|
//
|
|
ArrayFree(result);
|
|
ArrayResize(result, 0);
|
|
|
|
//
|
|
XSignal allSignals[];
|
|
XTMRetrieveGridTrades(allSignals);
|
|
|
|
//
|
|
if (ArraySize(allSignals) <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Loop Through all Positions and Extract Primary Trades ...
|
|
for (int i = 0; i < ArraySize(allSignals); i++)
|
|
{
|
|
//
|
|
XSignal signal = allSignals[i];
|
|
|
|
//
|
|
if (signal.type != type)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ArrayResize(
|
|
result,
|
|
ArraySize(result) + 1);
|
|
result[ArraySize(result) - 1] = signal;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve an Specific Primary Trade's Related Grid Trades ...
|
|
void XTMRetrieveGridTradesOfPrimary(
|
|
XSignal &primary, // Primary Trade which looking for it's Grid Trades ...
|
|
XSignal &result[] // Hold Result ...
|
|
)
|
|
{
|
|
//
|
|
// Free Result ...
|
|
ArrayFree(result);
|
|
ArrayResize(result, 0);
|
|
|
|
//
|
|
// Validate Args ...
|
|
bool isPrimary = XTMIsPrimaryTrade(primary);
|
|
if (!isPrimary)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XSignal gridSignals[];
|
|
XTMRetrieveGridTrades(gridSignals);
|
|
int gridCount = ArraySize(gridSignals);
|
|
if (gridCount == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Loop Through Grid Signals for Finding Primary Grid Trades ...
|
|
for (int i = 0; i < gridCount; i++)
|
|
{
|
|
//
|
|
XSignal signal = gridSignals[i];
|
|
bool isSignalContainsTicket = XTMIsSignalContainsTicketComment(primary.ticket, signal);
|
|
if (!isSignalContainsTicket)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (signal.type != primary.type)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ArrayResize(
|
|
result,
|
|
ArraySize(result) + 1);
|
|
result[ArraySize(result) - 1] = signal;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve Most Down Grid Trades of Primary ...
|
|
XSignal XTMRetrieveLastGridTradesOfPrimary(
|
|
XSignal &primary // Primary Trade which looking for it's Grid Trades ...
|
|
)
|
|
{
|
|
//
|
|
XSignal result = {};
|
|
|
|
//
|
|
XSignal gridSignals[];
|
|
XTMRetrieveGridTradesOfPrimary(primary, gridSignals);
|
|
int gridCount = ArraySize(gridSignals);
|
|
if (gridCount == 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop Throug a Primary Grids to Find Smallest Entry Price ...
|
|
for (int i = 0; i < gridCount; i++)
|
|
{
|
|
//
|
|
XSignal grid = gridSignals[i];
|
|
|
|
//
|
|
if (!IsValid(result, xTMMagicNumber))
|
|
{
|
|
result = grid;
|
|
}
|
|
else if (primary.type == X_SIGNAL_LONG)
|
|
{
|
|
if (grid.entry < result.entry)
|
|
{
|
|
result = grid;
|
|
}
|
|
}
|
|
else if (primary.type == X_SIGNAL_SHORT)
|
|
{
|
|
if (grid.entry > result.entry)
|
|
{
|
|
result = grid;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Draw TPSL Object ...
|
|
void XTMDrawTPSL(
|
|
XTPSL &model // an instance of XTPS structure
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (!IsValid(model))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
string entryName = "T_" + EnumToString(model.type) + "_Entry_" + (string)model.entry;
|
|
string slName = entryName + "_SL_" + (string)model.sl;
|
|
string tpName = entryName + "_TP_" + (string)model.tp;
|
|
datetime time1 = iTime(_Symbol, _Period, 2);
|
|
datetime time2 = iTime(_Symbol, _Period, 0);
|
|
color tpColor = xTDBullishArrowColor;
|
|
color slColor = xTDBearishArrowColor;
|
|
|
|
//
|
|
// Draw Entry ...
|
|
DrawTrendLine(
|
|
0,
|
|
entryName,
|
|
0,
|
|
time1,
|
|
model.entry,
|
|
time2,
|
|
model.entry,
|
|
clrYellow);
|
|
|
|
//
|
|
// Draw TP ...
|
|
if (model.tp > 0)
|
|
{
|
|
//
|
|
DrawTrendLine(
|
|
0,
|
|
tpName,
|
|
0,
|
|
time1,
|
|
model.tp,
|
|
time2,
|
|
model.tp,
|
|
tpColor);
|
|
}
|
|
|
|
//
|
|
// Draw SL ...
|
|
if (model.sl > 0)
|
|
{
|
|
//
|
|
DrawTrendLine(
|
|
0,
|
|
slName,
|
|
0,
|
|
time1,
|
|
model.sl,
|
|
time2,
|
|
model.sl,
|
|
slColor);
|
|
}
|
|
}
|
|
//
|
|
// END Provided Functions ...
|
|
//
|