1487 lines
37 KiB
Plaintext
1487 lines
37 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Indicator
|
|
// -------------------------------------------------
|
|
// Name: XCAEAHelper Lib
|
|
// Description: Library for XCAEA Signaller ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://saherelm.ir"
|
|
#property version "1.00"
|
|
#property description "SaherElm Library for XCAEA Helper"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
#include "../../Libraries/x-saherelm.common.lib.mq5"
|
|
#include "../Classes/xcaea.x-poi.detector.class.mq5"
|
|
#include "../Helpers/xcaea.helper.mq5"
|
|
|
|
//
|
|
// Definitions ...
|
|
enum ENUM_XCAEA_TIGGER_TYPE
|
|
{
|
|
XCA_TRIGGER_NONE, // None
|
|
XCA_TRIGGER_BULL, // TriggerBull
|
|
XCA_TRIGGER_BEAR, // TriggerBear
|
|
};
|
|
|
|
//
|
|
bool IsValid(ENUM_XCAEA_TIGGER_TYPE value)
|
|
{
|
|
return value != XCA_TRIGGER_NONE;
|
|
}
|
|
|
|
//
|
|
string ToString(ENUM_XCAEA_TIGGER_TYPE value)
|
|
{
|
|
return EnumToString(value);
|
|
}
|
|
|
|
//
|
|
ENUM_XCAEA_TIGGER_TYPE GetType(string type)
|
|
{
|
|
//
|
|
ENUM_XCAEA_TIGGER_TYPE result = XCA_TRIGGER_NONE;
|
|
|
|
//
|
|
bool isTriggerBull = type == ToString(XCA_TRIGGER_BULL);
|
|
bool isTriggerBear = type == ToString(XCA_TRIGGER_BEAR);
|
|
|
|
//
|
|
if (isTriggerBull)
|
|
{
|
|
result = XCA_TRIGGER_BULL;
|
|
}
|
|
else if (isTriggerBear)
|
|
{
|
|
result = XCA_TRIGGER_BEAR;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION GetDirection(ENUM_XCAEA_TIGGER_TYPE value)
|
|
{
|
|
return value == XCA_TRIGGER_BULL
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
// Structues ...
|
|
struct XCAEATriggerBlockConfiguration
|
|
{
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// Trigger Detection ...
|
|
|
|
//
|
|
double maxAllowedRange; // Maximum Allowed Range
|
|
int minAllowedBlockEdgeLength; // Minimum Required Block Edge Length
|
|
|
|
//
|
|
// Validation ...
|
|
bool forceOBOppositBar; // Force OB to Start by Opposit Bars
|
|
bool forceFVGBarType; // Force FVG to Has Same Type of Bars
|
|
bool forceGapBarBreakout; // Force FVG's Gap Bar to Breakeout OB Edge Side
|
|
bool forceHasSwingBar; // Force Has Propper Swing
|
|
bool forceHasLiquidity; // Force Has Following Liquidity Zone
|
|
bool forceHasReversalLiquidity; // Force Has Reversal Liquidity Zone
|
|
|
|
//
|
|
// Filtering ...
|
|
bool filterBasedOnSar; // Filter Trigger Block Based on Sar
|
|
bool filterBasedOnRSI; // Filter Trigger Block Based on RSI
|
|
bool filterBasedOnADX; // Filter Trigger Block Based on ADX
|
|
bool filterBasedOnTrend; // Filter Trigger Block Based on Trend
|
|
bool filterBasedOnScores; // Filter Trigger Block Based on Scores
|
|
bool filterBasedOnVolumes; // Filter Trigger Block Based on Volumes
|
|
|
|
//
|
|
double targets[]; // Targets Collection for R:R on Signal Preparation
|
|
|
|
//
|
|
// Constructor ...
|
|
XCAEATriggerBlockConfiguration()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
// Cleanup ...
|
|
void Clean()
|
|
{
|
|
//
|
|
// Validating ...
|
|
maxAllowedRange = false;
|
|
minAllowedBlockEdgeLength = false;
|
|
|
|
//
|
|
forceOBOppositBar = false;
|
|
forceFVGBarType = false;
|
|
forceGapBarBreakout = false;
|
|
forceHasSwingBar = false;
|
|
forceHasLiquidity = false;
|
|
forceHasReversalLiquidity = false;
|
|
|
|
//
|
|
// Filtering ...
|
|
filterBasedOnSar = false;
|
|
filterBasedOnRSI = false;
|
|
filterBasedOnADX = false;
|
|
filterBasedOnTrend = false;
|
|
filterBasedOnScores = false;
|
|
filterBasedOnVolumes = false;
|
|
|
|
//
|
|
Clean(targets);
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
//
|
|
// Preset Configurations ...
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
struct XTriggerBlock
|
|
{
|
|
//
|
|
// Props ...
|
|
XBoxZone ob; // Order Block
|
|
XBoxZone fvg; // Fair Value Gap
|
|
XOHCL swingBar; // Swing of Trigger
|
|
XBoxZone trigger; // Trigger Block
|
|
XBoxZone rLiquidity; // Reversal Liquidity
|
|
XBoxZone fLiquidity; // Following Liquidity
|
|
XCAEAConditions conditions; // Market Conditions
|
|
XCAEATriggerBlockConfiguration configuration; // Detection Configuration
|
|
|
|
//
|
|
XSignal signal; // Pepared Signal
|
|
|
|
//
|
|
// Constructor ...
|
|
XTriggerBlock()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
// Cleanup ...
|
|
void Clean()
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
signal.Clean();
|
|
trigger.Clean();
|
|
swingBar.Clean();
|
|
rLiquidity.Clean();
|
|
fLiquidity.Clean();
|
|
conditions.Clean();
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = ob.IsValid() &&
|
|
fvg.IsValid() &&
|
|
trigger.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
// Extensions ...
|
|
|
|
/**
|
|
* Detect Trigger Block ...
|
|
*
|
|
* @param trigger: XTriggerBlock instance Reference, hold founded Trigger Block
|
|
* @param helper: XCXCAEAHelper instance Reference Pointer, XCAEA Market nalyser Helper for acc Drawer
|
|
* @param config: XCAEATriggerBlockConfiguration instance Reference, Trigger Block Detecting Configuration
|
|
* @param bar_index: int, Bar Index to Start Detecting
|
|
* @param loopback: int, Loopback Bars Count
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectTriggerBlock(
|
|
XTriggerBlock &trigger,
|
|
XCXCAEAHelper *helper,
|
|
XCAEATriggerBlockConfiguration &config,
|
|
int bar_index = 0,
|
|
int loopback = 10,
|
|
double slAdditionalPoint = 0,
|
|
double slATRMultiplier = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize Args ...
|
|
trigger.Clean();
|
|
loopback = NormalizeInt(loopback, 10);
|
|
bar_index = NormalizeInt(bar_index, 0);
|
|
|
|
//
|
|
// Validate Args ...
|
|
result = helper != NULL;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Required Informations ...
|
|
|
|
//
|
|
string symbol = helper.GetSymbol();
|
|
ENUM_TIMEFRAMES period = helper.GetPeriod();
|
|
|
|
//
|
|
double points = GetPoints(symbol);
|
|
|
|
//
|
|
// Retrieve Indexed Bar ...
|
|
XOHCL zBar;
|
|
XOHCL cBar;
|
|
XOHCL pBar;
|
|
XOHCL p2Bar;
|
|
result = zBar.Init(
|
|
symbol,
|
|
period,
|
|
bar_index //
|
|
);
|
|
result = result &&
|
|
zBar.GetPreviousBar(cBar);
|
|
result = result &&
|
|
cBar.GetPreviousBar(pBar);
|
|
result = result &&
|
|
pBar.GetPreviousBar(p2Bar);
|
|
|
|
//
|
|
int zIDX = 0;
|
|
int cIDX = zIDX + 1;
|
|
int pIDX = cIDX + 1;
|
|
int p2IDX = pIDX + 1;
|
|
int p3IDX = p2IDX + 1;
|
|
int p4IDX = p3IDX + 1;
|
|
|
|
//
|
|
// Check Trigger Block Exists ...
|
|
result =
|
|
result &&
|
|
helper
|
|
.barAnalyser
|
|
.IsTrigger(
|
|
zBar,
|
|
trigger.trigger,
|
|
trigger.ob,
|
|
trigger.fvg,
|
|
trigger.rLiquidity,
|
|
trigger.fLiquidity,
|
|
trigger.swingBar,
|
|
loopback,
|
|
config.maxAllowedRange,
|
|
config.minAllowedBlockEdgeLength,
|
|
config.forceOBOppositBar,
|
|
config.forceFVGBarType,
|
|
config.forceGapBarBreakout,
|
|
config.forceHasSwingBar,
|
|
config.forceHasLiquidity,
|
|
config.forceHasReversalLiquidity //
|
|
);
|
|
|
|
//
|
|
// Now we Have to Implement Required Validations ...
|
|
|
|
//
|
|
bool isBullish = trigger.trigger.IsBullish();
|
|
bool isBearish = trigger.trigger.IsBearish();
|
|
|
|
//
|
|
// First Reading Market Conditions ...
|
|
result =
|
|
result &&
|
|
helper.GetConditions(
|
|
trigger.conditions,
|
|
bar_index,
|
|
loopback //
|
|
);
|
|
|
|
//
|
|
// All Custom andAdditional Validations and Filters
|
|
// Applied here ...
|
|
|
|
//
|
|
// SAR Filter ...
|
|
if (config.filterBasedOnSar)
|
|
{
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
// Reading Values ...
|
|
|
|
//
|
|
double zSar = trigger.conditions.sarBuffer[zIDX];
|
|
double cSar = trigger.conditions.sarBuffer[cIDX];
|
|
double pSar = trigger.conditions.sarBuffer[pIDX];
|
|
double p2Sar = trigger.conditions.sarBuffer[p2IDX];
|
|
double p3Sar = trigger.conditions.sarBuffer[p3IDX];
|
|
double p4Sar = trigger.conditions.sarBuffer[p4IDX];
|
|
|
|
//
|
|
// Preparing Conditions ...
|
|
|
|
//
|
|
bool isZSarBullish = zSar < zBar.low;
|
|
bool isZSarBearish = zSar > zBar.high;
|
|
|
|
//
|
|
bool isCSarBullish = cSar < cBar.low;
|
|
bool isCSarBearish = cSar > cBar.high;
|
|
|
|
//
|
|
bool isPSarBullish = pSar < pBar.low;
|
|
bool isPSarBearish = pSar > pBar.high;
|
|
|
|
//
|
|
bool isP2SarBullish = p2Sar < p2Bar.low;
|
|
bool isP2SarBearish = p2Sar > p2Bar.high;
|
|
|
|
//
|
|
bool isCSarSwitchedToBullish =
|
|
isZSarBullish &&
|
|
isCSarBullish &&
|
|
!isPSarBullish &&
|
|
cBar.IsBullish() &&
|
|
cBar.GetUp() > pSar;
|
|
|
|
//
|
|
bool isCSarSwitchedToBearish =
|
|
isZSarBearish &&
|
|
isCSarBearish &&
|
|
!isPSarBearish &&
|
|
cBar.IsBearish() &&
|
|
cBar.GetDown() < pSar;
|
|
|
|
//
|
|
bool isPSarSwitchedToBullish =
|
|
isZSarBullish &&
|
|
isCSarBullish &&
|
|
isPSarBullish &&
|
|
!isP2SarBullish &&
|
|
pBar.IsBullish() &&
|
|
pBar.GetUp() > p2Sar;
|
|
|
|
//
|
|
bool isPSarSwitchedToBearish =
|
|
isZSarBearish &&
|
|
isCSarBearish &&
|
|
isPSarBearish &&
|
|
!isP2SarBearish &&
|
|
pBar.IsBearish() &&
|
|
pBar.GetDown() < p2Sar;
|
|
|
|
//
|
|
// Summarize Filtering ...
|
|
|
|
//
|
|
bool isBullishFilterd =
|
|
isBullish &&
|
|
(isCSarSwitchedToBullish ||
|
|
isPSarSwitchedToBullish);
|
|
|
|
//
|
|
bool isBearishFilterd =
|
|
isBearish &&
|
|
(isCSarSwitchedToBearish ||
|
|
isPSarSwitchedToBearish);
|
|
|
|
//
|
|
// Apply Result ....
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
(isBullishFilterd ||
|
|
isBearishFilterd);
|
|
}
|
|
}
|
|
|
|
//
|
|
// RSI Filter ...
|
|
if (config.filterBasedOnRSI)
|
|
{
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
// Reading Values ...
|
|
|
|
//
|
|
double rsiTrend = (trigger.conditions.rsiOBLevel + trigger.conditions.rsiOSLevel) / 2;
|
|
|
|
//
|
|
double zRSI = trigger.conditions.rsiBuffer[zIDX];
|
|
double cRSI = trigger.conditions.rsiBuffer[cIDX];
|
|
double pRSI = trigger.conditions.rsiBuffer[pIDX];
|
|
double p2RSI = trigger.conditions.rsiBuffer[p2IDX];
|
|
double p3RSI = trigger.conditions.rsiBuffer[p3IDX];
|
|
double p4RSI = trigger.conditions.rsiBuffer[p4IDX];
|
|
|
|
//
|
|
// Preparing Conditions ...
|
|
|
|
//
|
|
bool isZRSIBullish = zRSI > rsiTrend;
|
|
bool isZRSIBearish = zRSI < rsiTrend;
|
|
|
|
//
|
|
bool isCRSIBullish = cRSI > rsiTrend;
|
|
bool isCRSIBearish = cRSI < rsiTrend;
|
|
|
|
//
|
|
bool isPRSIBullish = pRSI > rsiTrend;
|
|
bool isPRSIBearish = pRSI < rsiTrend;
|
|
|
|
//
|
|
bool isP2RSIBullish = p2RSI > rsiTrend;
|
|
bool isP2RSIBearish = p2RSI < rsiTrend;
|
|
|
|
//
|
|
bool isP3RSIBullish = p3RSI > rsiTrend;
|
|
bool isP3RSIBearish = p3RSI < rsiTrend;
|
|
|
|
//
|
|
// Trending Conditions ...
|
|
|
|
//
|
|
bool isCRSISwitchedToBullish =
|
|
isZRSIBullish &&
|
|
isCRSIBullish &&
|
|
!isPRSIBullish;
|
|
|
|
//
|
|
bool isCRSISwitchedToBearish =
|
|
isZRSIBearish &&
|
|
isCRSIBearish &&
|
|
!isPRSIBearish;
|
|
|
|
//
|
|
bool isPRSISwitchedToBullish =
|
|
isZRSIBullish &&
|
|
isCRSIBullish &&
|
|
isPRSIBullish &&
|
|
!isP2RSIBullish;
|
|
|
|
//
|
|
bool isPRSISwitchedToBearish =
|
|
isZRSIBearish &&
|
|
isCRSIBearish &&
|
|
isPRSIBearish &&
|
|
!isP2RSIBearish;
|
|
|
|
//
|
|
bool isP2RSISwitchedToBullish =
|
|
isZRSIBullish &&
|
|
isCRSIBullish &&
|
|
isPRSIBullish &&
|
|
isP2RSIBullish &&
|
|
!isP3RSIBullish;
|
|
|
|
//
|
|
bool isP2RSISwitchedToBearish =
|
|
isZRSIBearish &&
|
|
isCRSIBearish &&
|
|
isPRSIBearish &&
|
|
isP2RSIBearish &&
|
|
!isP3RSIBearish;
|
|
|
|
//
|
|
// Crosses Conditions ...
|
|
|
|
//
|
|
bool isCBarCrossedOverOS =
|
|
zRSI > trigger.conditions.rsiOSLevel &&
|
|
cRSI > trigger.conditions.rsiOSLevel &&
|
|
pRSI <= trigger.conditions.rsiOSLevel;
|
|
|
|
//
|
|
bool isCBarCrossedUnderOB =
|
|
zRSI < trigger.conditions.rsiOBLevel &&
|
|
cRSI < trigger.conditions.rsiOBLevel &&
|
|
pRSI >= trigger.conditions.rsiOBLevel;
|
|
|
|
//
|
|
bool isPBarCrossedOverOS =
|
|
zRSI > trigger.conditions.rsiOSLevel &&
|
|
cRSI > trigger.conditions.rsiOSLevel &&
|
|
pRSI > trigger.conditions.rsiOSLevel &&
|
|
p2RSI <= trigger.conditions.rsiOSLevel;
|
|
|
|
//
|
|
bool isPBarCrossedUnderOB =
|
|
zRSI < trigger.conditions.rsiOBLevel &&
|
|
cRSI < trigger.conditions.rsiOBLevel &&
|
|
pRSI < trigger.conditions.rsiOBLevel &&
|
|
p2RSI >= trigger.conditions.rsiOBLevel;
|
|
|
|
//
|
|
// V Pattern Conditions ...
|
|
|
|
//
|
|
bool isCRSIHasVBullishPattern =
|
|
zRSI >= cRSI &&
|
|
cRSI > pRSI &&
|
|
p2RSI > pRSI &&
|
|
cRSI >= p2RSI;
|
|
|
|
//
|
|
bool isCRSIHasVBearishPattern =
|
|
zRSI <= cRSI &&
|
|
cRSI < pRSI &&
|
|
p2RSI < pRSI &&
|
|
cRSI <= p2RSI;
|
|
|
|
//
|
|
// Continuation Conditions ...
|
|
|
|
//
|
|
bool isRSIUp =
|
|
zRSI >= cRSI &&
|
|
(cRSI >= pRSI ||
|
|
pRSI >= p2RSI ||
|
|
p2RSI >= p3RSI);
|
|
|
|
//
|
|
bool isRSIDown =
|
|
zRSI <= cRSI &&
|
|
(cRSI <= pRSI ||
|
|
pRSI <= p2RSI ||
|
|
p2RSI <= p3RSI);
|
|
|
|
//
|
|
// Summarize Filtering ...
|
|
|
|
//
|
|
bool isBullishFilterd =
|
|
isBullish &&
|
|
(
|
|
//
|
|
// Grows ...
|
|
isRSIUp
|
|
//
|
|
||
|
|
//
|
|
// Crosses ...
|
|
(isCBarCrossedOverOS ||
|
|
isPBarCrossedOverOS)
|
|
//
|
|
||
|
|
//
|
|
// V Pattern ...
|
|
isCRSIHasVBullishPattern
|
|
//
|
|
||
|
|
//
|
|
// Trending ...
|
|
(isCRSISwitchedToBullish ||
|
|
isPRSISwitchedToBullish ||
|
|
isP2RSISwitchedToBullish)
|
|
//
|
|
);
|
|
|
|
//
|
|
bool isBearishFilterd =
|
|
isBearish &&
|
|
(
|
|
//
|
|
// Grows ...
|
|
isRSIDown
|
|
//
|
|
||
|
|
//
|
|
// Crosses ...
|
|
(isCBarCrossedUnderOB ||
|
|
isPBarCrossedUnderOB)
|
|
//
|
|
||
|
|
//
|
|
// V Pattern ...
|
|
isCRSIHasVBearishPattern
|
|
//
|
|
||
|
|
//
|
|
// Trending ...
|
|
(isCRSISwitchedToBearish ||
|
|
isPRSISwitchedToBearish ||
|
|
isP2RSISwitchedToBearish)
|
|
//
|
|
);
|
|
|
|
//
|
|
// Apply Result ....
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
(isBullishFilterd ||
|
|
isBearishFilterd);
|
|
}
|
|
}
|
|
|
|
//
|
|
// ADX Filter ...
|
|
if (config.filterBasedOnADX)
|
|
{
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
// Reading Values ...
|
|
|
|
//
|
|
// ADX ...
|
|
double zADX = trigger.conditions.adxBuffer[zIDX];
|
|
double cADX = trigger.conditions.adxBuffer[cIDX];
|
|
double pADX = trigger.conditions.adxBuffer[pIDX];
|
|
double p2ADX = trigger.conditions.adxBuffer[p2IDX];
|
|
double p3ADX = trigger.conditions.adxBuffer[p3IDX];
|
|
double p4ADX = trigger.conditions.adxBuffer[p4IDX];
|
|
|
|
//
|
|
// ADX +DI ...
|
|
double zADXP = trigger.conditions.adxpBuffer[zIDX];
|
|
double cADXP = trigger.conditions.adxpBuffer[cIDX];
|
|
double pADXP = trigger.conditions.adxpBuffer[pIDX];
|
|
double p2ADXP = trigger.conditions.adxpBuffer[p2IDX];
|
|
double p3ADXP = trigger.conditions.adxpBuffer[p3IDX];
|
|
double p4ADXP = trigger.conditions.adxpBuffer[p4IDX];
|
|
|
|
//
|
|
// ADX -DI ...
|
|
double zADXN = trigger.conditions.adxnBuffer[zIDX];
|
|
double cADXN = trigger.conditions.adxnBuffer[cIDX];
|
|
double pADXN = trigger.conditions.adxnBuffer[pIDX];
|
|
double p2ADXN = trigger.conditions.adxnBuffer[p2IDX];
|
|
double p3ADXN = trigger.conditions.adxnBuffer[p3IDX];
|
|
double p4ADXN = trigger.conditions.adxnBuffer[p4IDX];
|
|
|
|
//
|
|
// Preparing Conditions ...
|
|
|
|
//
|
|
// Grows ...
|
|
|
|
//
|
|
bool isADXUp =
|
|
zADX >= cADX &&
|
|
(cADX >= pADX ||
|
|
pADX >= p2ADX);
|
|
|
|
//
|
|
bool isADXDown =
|
|
zADX <= cADX &&
|
|
(cADX <= pADX ||
|
|
pADX <= p2ADX);
|
|
|
|
//
|
|
// Trending ...
|
|
|
|
//
|
|
bool isZADXBullish = zADX > trigger.conditions.adxThreshold;
|
|
bool isZADXBearish = zADX < trigger.conditions.adxThreshold;
|
|
|
|
//
|
|
bool isCADXBullish = cADX > trigger.conditions.adxThreshold;
|
|
bool isCADXBearish = cADX < trigger.conditions.adxThreshold;
|
|
|
|
//
|
|
bool isPADXBullish = pADX > trigger.conditions.adxThreshold;
|
|
bool isPADXBearish = pADX < trigger.conditions.adxThreshold;
|
|
|
|
//
|
|
bool isP2ADXBullish = p2ADX > trigger.conditions.adxThreshold;
|
|
bool isP2ADXBearish = p2ADX < trigger.conditions.adxThreshold;
|
|
|
|
//
|
|
bool isP3ADXBullish = p3ADX > trigger.conditions.adxThreshold;
|
|
bool isP3ADXBearish = p3ADX < trigger.conditions.adxThreshold;
|
|
|
|
//
|
|
bool isP4ADXBullish = p4ADX > trigger.conditions.adxThreshold;
|
|
bool isP4ADXBearish = p4ADX < trigger.conditions.adxThreshold;
|
|
|
|
//
|
|
bool isCADXSwitchedToBullish =
|
|
isZADXBullish &&
|
|
isCADXBullish &&
|
|
!isPADXBullish;
|
|
|
|
//
|
|
bool isCADXSwitchedToBearish =
|
|
isZADXBearish &&
|
|
isCADXBearish &&
|
|
!isPADXBearish;
|
|
|
|
//
|
|
bool isPADXSwitchedToBullish =
|
|
isZADXBullish &&
|
|
isCADXBullish &&
|
|
isPADXBullish &&
|
|
!isP2ADXBullish;
|
|
|
|
//
|
|
bool isPADXSwitchedToBearish =
|
|
isZADXBearish &&
|
|
isCADXBearish &&
|
|
isPADXBearish &&
|
|
!isP2ADXBearish;
|
|
|
|
//
|
|
// Powering ...
|
|
|
|
//
|
|
bool isZADXHasBullishPower = zADXP > zADXN;
|
|
bool isZADXHasBearishPower = zADXN > zADXP;
|
|
|
|
//
|
|
bool isCADXHasBullishPower = cADXP > cADXN;
|
|
bool isCADXHasBearishPower = cADXN > cADXP;
|
|
|
|
//
|
|
bool isPADXHasBullishPower = pADXP > pADXN;
|
|
bool isPADXHasBearishPower = pADXN > pADXP;
|
|
|
|
//
|
|
bool isP2ADXHasBullishPower = p2ADXP > p2ADXN;
|
|
bool isP2ADXHasBearishPower = p2ADXN > p2ADXP;
|
|
|
|
//
|
|
bool isP3ADXHasBullishPower = p3ADXP > p3ADXN;
|
|
bool isP3ADXHasBearishPower = p3ADXN > p3ADXP;
|
|
|
|
//
|
|
bool isP4ADXHasBullishPower = p4ADXP > p4ADXN;
|
|
bool isP4ADXHasBearishPower = p4ADXN > p4ADXP;
|
|
|
|
//
|
|
bool isCADXSwitchedToBullishPower =
|
|
isZADXHasBullishPower &&
|
|
isCADXHasBullishPower &&
|
|
!isPADXHasBullishPower;
|
|
|
|
//
|
|
bool isCADXSwitchedToBearishPower =
|
|
isZADXHasBearishPower &&
|
|
isCADXHasBearishPower &&
|
|
!isPADXHasBearishPower;
|
|
|
|
//
|
|
bool isPADXSwitchedToBullishPower =
|
|
isZADXHasBullishPower &&
|
|
isCADXHasBullishPower &&
|
|
isPADXHasBullishPower &&
|
|
!isP2ADXHasBullishPower;
|
|
|
|
//
|
|
bool isPADXSwitchedToBearishPower =
|
|
isZADXHasBearishPower &&
|
|
isCADXHasBearishPower &&
|
|
isPADXHasBearishPower &&
|
|
!isP2ADXHasBearishPower;
|
|
|
|
//
|
|
// Summarize Filtering ...
|
|
|
|
//
|
|
bool isBullishFilterd =
|
|
isBullish &&
|
|
(
|
|
//
|
|
// Grows ...
|
|
isADXUp
|
|
//
|
|
||
|
|
//
|
|
// Trending ...
|
|
(isCADXSwitchedToBullish ||
|
|
isPADXSwitchedToBullish)
|
|
//
|
|
||
|
|
//
|
|
// Powering ...
|
|
(isCADXSwitchedToBullishPower ||
|
|
isPADXSwitchedToBullishPower)
|
|
//
|
|
);
|
|
|
|
//
|
|
bool isBearishFilterd =
|
|
isBearish &&
|
|
(
|
|
//
|
|
// Grows ...
|
|
isADXDown
|
|
//
|
|
||
|
|
//
|
|
// Trending ...
|
|
(isCADXSwitchedToBearish ||
|
|
isPADXSwitchedToBearish)
|
|
//
|
|
||
|
|
//
|
|
// Powering ...
|
|
(isCADXSwitchedToBearishPower ||
|
|
isPADXSwitchedToBearishPower)
|
|
//
|
|
);
|
|
|
|
//
|
|
// Apply Result ....
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
(isBullishFilterd ||
|
|
isBearishFilterd);
|
|
}
|
|
}
|
|
|
|
//
|
|
// TREND Filter ...
|
|
if (config.filterBasedOnTrend)
|
|
{
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
// Reading Values ...
|
|
|
|
//
|
|
double zTrend = trigger.conditions.trendBuffer[zIDX];
|
|
double cTrend = trigger.conditions.trendBuffer[cIDX];
|
|
double pTrend = trigger.conditions.trendBuffer[pIDX];
|
|
double p2Trend = trigger.conditions.trendBuffer[p2IDX];
|
|
double p3Trend = trigger.conditions.trendBuffer[p3IDX];
|
|
double p4Trend = trigger.conditions.trendBuffer[p4IDX];
|
|
|
|
//
|
|
double trends[] = {
|
|
zTrend,
|
|
cTrend,
|
|
pTrend,
|
|
p2Trend,
|
|
p3Trend,
|
|
p4Trend //
|
|
};
|
|
double trendsMin = GetMin(trends);
|
|
double trendsMax = GetMax(trends);
|
|
double trendsAVG = GetAverage(trends);
|
|
|
|
//
|
|
double zTrendState = trigger.conditions.trendStateBuffer[zIDX];
|
|
double cTrendState = trigger.conditions.trendStateBuffer[cIDX];
|
|
double pTrendState = trigger.conditions.trendStateBuffer[pIDX];
|
|
double p2TrendState = trigger.conditions.trendStateBuffer[p2IDX];
|
|
double p3TrendState = trigger.conditions.trendStateBuffer[p3IDX];
|
|
double p4TrendState = trigger.conditions.trendStateBuffer[p4IDX];
|
|
|
|
//
|
|
// Preparing Conditions ...
|
|
|
|
//
|
|
// Grows ...
|
|
|
|
//
|
|
bool isTrendUp =
|
|
zTrend >= cTrend &&
|
|
cTrend >= trendsAVG &&
|
|
cTrend > trendsMin;
|
|
|
|
//
|
|
bool isTrendDown =
|
|
zTrend <= cTrend &&
|
|
cTrend <= trendsAVG &&
|
|
cTrend < trendsMax;
|
|
|
|
//
|
|
// Stating ...
|
|
|
|
//
|
|
bool isCTrendBullish =
|
|
zTrendState > 0 &&
|
|
cTrendState > 0;
|
|
|
|
//
|
|
bool isCTrendBearish =
|
|
zTrendState < 0 &&
|
|
cTrendState < 0;
|
|
|
|
//
|
|
bool isPTrendBullish =
|
|
zTrendState > 0 &&
|
|
cTrendState > 0 &&
|
|
pTrendState > 0;
|
|
|
|
//
|
|
bool isPTrendBearish =
|
|
zTrendState < 0 &&
|
|
cTrendState < 0 &&
|
|
pTrendState < 0;
|
|
|
|
//
|
|
bool isP2TrendBullish =
|
|
zTrendState > 0 &&
|
|
cTrendState > 0 &&
|
|
pTrendState > 0 &&
|
|
p2TrendState > 0;
|
|
|
|
//
|
|
bool isP2TrendBearish =
|
|
zTrendState < 0 &&
|
|
cTrendState < 0 &&
|
|
pTrendState < 0 &&
|
|
p2TrendState < 0;
|
|
|
|
//
|
|
bool isCTrendSwitchedToBullish =
|
|
isCTrendBullish &&
|
|
!isPTrendBullish;
|
|
|
|
//
|
|
bool isCTrendSwitchedToBearish =
|
|
isCTrendBearish &&
|
|
!isPTrendBearish;
|
|
|
|
//
|
|
bool isPTrendSwitchedToBullish =
|
|
isCTrendBullish &&
|
|
isPTrendBullish &&
|
|
!isP2TrendBullish;
|
|
|
|
//
|
|
bool isPTrendSwitchedToBearish =
|
|
isCTrendBearish &&
|
|
isPTrendBearish &&
|
|
!isP2TrendBearish;
|
|
|
|
//
|
|
// Summarize Filtering ...
|
|
|
|
//
|
|
bool isBullishFilterd =
|
|
isBullish &&
|
|
(
|
|
//
|
|
// Grows ...
|
|
isTrendUp
|
|
//
|
|
||
|
|
//
|
|
// Trend Stating ...
|
|
(isCTrendBullish &&
|
|
isPTrendBullish)
|
|
//
|
|
||
|
|
//
|
|
// Switching ...
|
|
(isCTrendSwitchedToBullish ||
|
|
isPTrendSwitchedToBullish)
|
|
//
|
|
);
|
|
|
|
//
|
|
bool isBearishFilterd =
|
|
isBearish &&
|
|
(
|
|
//
|
|
// Grows ...
|
|
isTrendDown
|
|
//
|
|
||
|
|
//
|
|
// Trend Stating ...
|
|
(isCTrendBearish &&
|
|
isPTrendBearish)
|
|
//
|
|
||
|
|
//
|
|
// Switching ...
|
|
(isCTrendSwitchedToBearish ||
|
|
isPTrendSwitchedToBearish)
|
|
//
|
|
);
|
|
|
|
//
|
|
// Apply Result ....
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
(isBullishFilterd ||
|
|
isBearishFilterd);
|
|
}
|
|
}
|
|
|
|
//
|
|
// SCORE Filter ...
|
|
if (config.filterBasedOnScores)
|
|
{
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
// Reading Values ...
|
|
|
|
//
|
|
double bullishScore = 0;
|
|
double bearishScore = 0;
|
|
|
|
//
|
|
trigger.conditions.GenerateScore(
|
|
bullishScore,
|
|
bearishScore //
|
|
);
|
|
|
|
//
|
|
// Preparing Conditions ...
|
|
|
|
//
|
|
bool isScoreBullish = bullishScore > bearishScore;
|
|
bool isScoreBearish = bearishScore > bullishScore;
|
|
|
|
//
|
|
// Summarize Filtering ...
|
|
|
|
//
|
|
bool isBullishFilterd =
|
|
isBullish &&
|
|
isScoreBullish;
|
|
|
|
//
|
|
bool isBearishFilterd =
|
|
isBearish &&
|
|
isScoreBearish;
|
|
|
|
//
|
|
// Apply Result ....
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
(isBullishFilterd ||
|
|
isBearishFilterd);
|
|
}
|
|
}
|
|
|
|
//
|
|
// VOLUME Filter ...
|
|
if (config.filterBasedOnVolumes)
|
|
{
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
// Reading Values ...
|
|
|
|
//
|
|
double bullishVolume = 0;
|
|
double bearishVolume = 0;
|
|
|
|
//
|
|
helper
|
|
.barAnalyser
|
|
.CalculateRangeVolume(
|
|
zBar,
|
|
bullishVolume,
|
|
bearishVolume,
|
|
loopback //
|
|
);
|
|
|
|
//
|
|
// Preparing Conditions ...
|
|
|
|
//
|
|
bool isVolumeBullish = bullishVolume > bearishVolume;
|
|
bool isVolumeBearish = bearishVolume > bullishVolume;
|
|
|
|
//
|
|
// Summarize Filtering ...
|
|
|
|
//
|
|
bool isBullishFilterd =
|
|
isBullish &&
|
|
isVolumeBullish;
|
|
|
|
//
|
|
bool isBearishFilterd =
|
|
isBearish &&
|
|
isVolumeBearish;
|
|
|
|
//
|
|
// Apply Result ....
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
(isBullishFilterd ||
|
|
isBearishFilterd);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
trigger.Clean();
|
|
}
|
|
|
|
//
|
|
// Attach Configuration if Trigger Block Founded ...
|
|
if (result)
|
|
{
|
|
//
|
|
trigger.configuration = config;
|
|
|
|
//
|
|
// Prepare Trigger Signal ...
|
|
if (HasChild(config.targets))
|
|
{
|
|
//
|
|
// Calculating Additional SL Value for Signals ...
|
|
double additionalSL = 0;
|
|
if (slATRMultiplier > 0)
|
|
{
|
|
//
|
|
double cATR = trigger.conditions.atrBuffer[cIDX];
|
|
additionalSL += (cATR * slATRMultiplier);
|
|
}
|
|
if (slAdditionalPoint > 0)
|
|
{
|
|
additionalSL += (slAdditionalPoint * points);
|
|
}
|
|
|
|
//
|
|
ToSignal(
|
|
trigger.trigger,
|
|
trigger.signal,
|
|
config.targets,
|
|
additionalSL //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Draw Specified Trigger Block ...
|
|
*
|
|
* @param trigger: XTriggerBlock instance Reference, specified Trigger Block to Draw
|
|
* @param objects: CArrayObj instance Reference Pointer, Objects Array for Providing Drawn Objects
|
|
* @param helper: XCXCAEAHelper instance Reference Pointer, XCAEA Market nalyser Helper for acc Drawer
|
|
* @param to: datetime, specified Time for update Trigger parts
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DrawTriggerBlock(
|
|
XTriggerBlock &trigger,
|
|
CArrayObj *&objects,
|
|
XCXCAEAHelper *helper,
|
|
datetime to = NULL,
|
|
int rrZoneLength = 10 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
result = helper != NULL &&
|
|
trigger.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Update To ...
|
|
bool canUpdateTo = IsValid(to);
|
|
if (canUpdateTo)
|
|
{
|
|
//
|
|
trigger.trigger.to = to;
|
|
trigger.rLiquidity.to = to;
|
|
trigger.fLiquidity.to = to;
|
|
}
|
|
|
|
//
|
|
// Draw OB ...
|
|
if (trigger.ob.IsValid())
|
|
{
|
|
//
|
|
XCBoxObject *iOBObj;
|
|
result = helper.poiDrawer.DrawBox(
|
|
trigger.ob,
|
|
iOBObj //
|
|
);
|
|
if (result)
|
|
{
|
|
objects.Add(iOBObj);
|
|
}
|
|
ZeroMemory(iOBObj);
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Draw FVG ...
|
|
if (trigger.fvg.IsValid())
|
|
{
|
|
//
|
|
XCBoxObject *iFVGObj;
|
|
result = helper.poiDrawer.DrawBox(
|
|
trigger.fvg,
|
|
iFVGObj //
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
// Style Object ...
|
|
color clr =
|
|
trigger.fvg.IsBullish()
|
|
? clrAqua
|
|
: clrMagenta;
|
|
iFVGObj.BoxWidth(2);
|
|
iFVGObj.BoxColor(clr);
|
|
iFVGObj.BoxStyle(STYLE_SOLID);
|
|
|
|
//
|
|
// Store Object ...
|
|
objects.Add(iFVGObj);
|
|
}
|
|
ZeroMemory(iFVGObj);
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Draw Trigger ...
|
|
if (trigger.trigger.IsValid())
|
|
{
|
|
//
|
|
XCBoxObject *iTriggerObj;
|
|
result = helper.poiDrawer.DrawBox(
|
|
trigger.trigger,
|
|
iTriggerObj //
|
|
);
|
|
if (result)
|
|
{
|
|
objects.Add(iTriggerObj);
|
|
}
|
|
ZeroMemory(iTriggerObj);
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Draw Liquidities ...
|
|
|
|
//
|
|
// Reversla Liquidity ...
|
|
if (trigger.rLiquidity.IsValid())
|
|
{
|
|
//
|
|
XCBoxObject *iLiqObj;
|
|
result = helper.poiDrawer.DrawBox(
|
|
trigger.rLiquidity,
|
|
iLiqObj //
|
|
);
|
|
if (result)
|
|
{
|
|
objects.Add(iLiqObj);
|
|
}
|
|
ZeroMemory(iLiqObj);
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Following Liquidity ...
|
|
if (trigger.fLiquidity.IsValid())
|
|
{
|
|
//
|
|
XCBoxObject *iLiqObj;
|
|
result = helper.poiDrawer.DrawBox(
|
|
trigger.fLiquidity,
|
|
iLiqObj //
|
|
);
|
|
if (result)
|
|
{
|
|
objects.Add(iLiqObj);
|
|
}
|
|
ZeroMemory(iLiqObj);
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Draw Swing Bar ...
|
|
if (trigger.swingBar.IsValid())
|
|
{
|
|
//
|
|
color swingColor =
|
|
trigger.fvg.IsBullish()
|
|
? clrAqua
|
|
: clrMagenta;
|
|
ENUM_X_PRICE swingPType =
|
|
trigger.fvg.IsBullish()
|
|
? X_PRICE_LOW
|
|
: X_PRICE_HIGH;
|
|
|
|
//
|
|
XCBarArrowObject *swingObj;
|
|
result = helper.poiDrawer.CreateBarArrow(
|
|
trigger.swingBar,
|
|
swingObj,
|
|
swingPType,
|
|
159,
|
|
swingColor //
|
|
);
|
|
if (result)
|
|
{
|
|
objects.Add(swingObj);
|
|
}
|
|
ZeroMemory(swingObj);
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Draw RR of Signal ...
|
|
if (trigger.signal.IsValid() &&
|
|
rrZoneLength > 0)
|
|
{
|
|
//
|
|
XCRRObject *iRRObj;
|
|
iRRObj = new XCRRObject();
|
|
result = iRRObj.Create(
|
|
helper.poiDrawer.ChartIdentification(),
|
|
helper.poiDrawer.SubWindowIdentification(),
|
|
trigger.signal,
|
|
rrZoneLength //
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
int iWidth = 2;
|
|
ENUM_LINE_STYLE iStyle = STYLE_SOLID;
|
|
|
|
//
|
|
iRRObj.TPWidth(iWidth);
|
|
iRRObj.SLWidth(iWidth);
|
|
iRRObj.EntryWidth(iWidth);
|
|
iRRObj.TargetWidth(iWidth);
|
|
|
|
//
|
|
iRRObj.TPStyle(iStyle);
|
|
iRRObj.SLStyle(iStyle);
|
|
iRRObj.EntryStyle(iStyle);
|
|
iRRObj.TargetStyle(iStyle);
|
|
|
|
//
|
|
iRRObj.TPColor(clrLime);
|
|
iRRObj.SLColor(clrRed);
|
|
iRRObj.EntryColor(clrYellow);
|
|
iRRObj.TargetColor(clrLightBlue);
|
|
|
|
//
|
|
objects.Add(iRRObj);
|
|
}
|
|
ZeroMemory(iRRObj);
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
// |