1215 lines
33 KiB
Plaintext
1215 lines
33 KiB
Plaintext
|
|
//
|
|
// Detect Trigger Block ...
|
|
bool DetectTriggerBlock(
|
|
//
|
|
string symbol,
|
|
ENUM_TIMEFRAMES period,
|
|
//
|
|
XTriggerBlock &tb,
|
|
//
|
|
XCBarAnalyser *barAnalyser,
|
|
//
|
|
// Required Buffers ...
|
|
const double &_atrBuffer[],
|
|
const double &_rsiBuffer[],
|
|
const double &_adxBuffer[],
|
|
const double &_adxpBuffer[],
|
|
const double &_adxnBuffer[],
|
|
const double &_peakBuffer[],
|
|
const double &_valeBuffer[],
|
|
const double &_deltaBuffer[],
|
|
const double &_sarBuffer[],
|
|
const double &_sarStateBuffer[],
|
|
const double &_trendBuffer[],
|
|
const double &_trendStateBuffer[],
|
|
const double &_atrUpperBuffer[],
|
|
const double &_atrLowerBuffer[],
|
|
const double &_sBarOpenSBuffer[],
|
|
const double &_sBarCloseBuffer[],
|
|
const double &_hkSBarOpenBuffer[],
|
|
const double &_hkSBarCloseBuffer[],
|
|
const double &_peakGoldenBuffer[],
|
|
const double &_valeGoldenBuffer[],
|
|
const double &_deltaSignalBuffer[],
|
|
const double &_bullishVolumeSignalBuffer[],
|
|
const double &_bearishVolumeSignalBuffer[],
|
|
//
|
|
int barIndex,
|
|
//
|
|
int _r2r,
|
|
double _slAtrMultiplier,
|
|
//
|
|
// Configs ...
|
|
double _rsiOBLevel,
|
|
double _rsiOSLevel,
|
|
double _adxThreshold,
|
|
//
|
|
// Validators ...
|
|
//
|
|
bool _forceOBBarType = false,
|
|
bool _forceFVGBarType = false,
|
|
bool _forceHasSwing = false,
|
|
bool _forceHasFLiquidity = false,
|
|
bool _forceHasRLiquidity = false,
|
|
bool _validateGapSequence = false,
|
|
bool _validateBlockEdgeBreakout = false,
|
|
//
|
|
// Filters ...
|
|
bool _filterBasedOnPV = false,
|
|
bool _filterBasedOnSar = false,
|
|
bool _filterBasedOnRSI = false,
|
|
bool _filterBasedOnADX = false,
|
|
bool _filterBasedOnATR = false,
|
|
bool _filterBasedOnTrend = false,
|
|
bool _filterBasedOnDelta = false,
|
|
bool _filterBasedOnVolume = false,
|
|
bool _filterBasedOnSignalBar = false,
|
|
bool _filterBasedOnHKSignalBar = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Custom Configs ...
|
|
|
|
// //
|
|
// _r2r = 2;
|
|
// _slAtrMultiplier = 1;
|
|
|
|
// //
|
|
// // Validators ...
|
|
// _forceHasSwing = true;
|
|
// _forceOBBarType = true;
|
|
// _forceFVGBarType = true;
|
|
// _validateGapSequence = true;
|
|
|
|
// //
|
|
// _forceHasFLiquidity = false;
|
|
// _forceHasRLiquidity = false;
|
|
// _validateBlockEdgeBreakout = true;
|
|
|
|
// //
|
|
// // Filters ...
|
|
// _filterBasedOnPV = true;
|
|
// _filterBasedOnATR = true;
|
|
// _filterBasedOnDelta = true;
|
|
// _filterBasedOnVolume = true;
|
|
|
|
// //
|
|
// _filterBasedOnSar = true;
|
|
// _filterBasedOnRSI = false;
|
|
// _filterBasedOnADX = false;
|
|
// _filterBasedOnTrend = false;
|
|
// _filterBasedOnSignalBar = true;
|
|
// _filterBasedOnHKSignalBar = true;
|
|
|
|
//
|
|
tb.Clean();
|
|
|
|
//
|
|
result = barAnalyser != NULL;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int zIDX = 0;
|
|
bool has = false;
|
|
bool isDone = false;
|
|
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Retrieve Required Bars ...
|
|
|
|
//
|
|
XOHCL iBar;
|
|
XOHCL zBar; // Current Start Checking Bar (Usually Used for Triggering) ...
|
|
has = zBar.Init(
|
|
symbol,
|
|
period,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
// Detect Based Order Block ...
|
|
has =
|
|
has &&
|
|
barAnalyser.IsOB(
|
|
zBar,
|
|
tb.ob,
|
|
_forceFVGBarType, // Force FVG Bar Type ...
|
|
_forceOBBarType // Force Block Two Bar Checking ...
|
|
);
|
|
|
|
//
|
|
// Detect Based Fair Value Gap ...
|
|
has =
|
|
has &&
|
|
barAnalyser.IsFVG(
|
|
zBar,
|
|
tb.fvg,
|
|
_forceFVGBarType // Force FVG Bar Type ...
|
|
);
|
|
|
|
//
|
|
// Clone Trigger Block ...
|
|
if (has)
|
|
{
|
|
//
|
|
tb.trigger = tb.ob;
|
|
tb.trigger.type = "XTRGB";
|
|
}
|
|
|
|
//
|
|
bool isBullish =
|
|
has &&
|
|
tb.IsBullish();
|
|
|
|
//
|
|
bool isBearish =
|
|
has &&
|
|
tb.IsBearish();
|
|
|
|
//
|
|
int toIDX = tb.ToIndex();
|
|
int fromIDX = tb.FromIndex();
|
|
|
|
//
|
|
// Verifications and Filters ...
|
|
|
|
//
|
|
int loopback = 144;
|
|
|
|
//
|
|
// Forces ...
|
|
|
|
//
|
|
// Force Has Proper Swing ...
|
|
if (has &&
|
|
_forceHasSwing)
|
|
{
|
|
//
|
|
XOHCL iPBar;
|
|
XOHCL iP2Bar;
|
|
toIDX = tb.ToIndex();
|
|
fromIDX = tb.FromIndex();
|
|
for (int i = toIDX; i <= fromIDX; i++)
|
|
{
|
|
//
|
|
// Initialize iBar ...
|
|
isDone = iBar.Init(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
i //
|
|
);
|
|
isDone =
|
|
isDone &&
|
|
iBar.GetPreviousBar(iPBar);
|
|
isDone =
|
|
isDone &&
|
|
iPBar.GetPreviousBar(iP2Bar);
|
|
isDone =
|
|
isDone &&
|
|
barAnalyser.IsSimpleSwing(
|
|
iBar,
|
|
iDir //
|
|
) &&
|
|
iDir == tb.GetDirection();
|
|
if (isDone)
|
|
{
|
|
//
|
|
bool canSet =
|
|
!tb.swingBar.IsValid()
|
|
? true
|
|
: (isBullish
|
|
? tb.swingBar.low > iP2Bar.low
|
|
: tb.swingBar.high < iP2Bar.high);
|
|
if (canSet)
|
|
{
|
|
tb.swingBar = iP2Bar;
|
|
}
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
iP2Bar.Clean();
|
|
}
|
|
|
|
//
|
|
has = tb.swingBar.IsValid();
|
|
}
|
|
|
|
//
|
|
// Force Has Liquidity ...
|
|
// TODO: Add Validation based on Liquidities
|
|
// if necessary ...
|
|
if (has &&
|
|
(_forceHasFLiquidity ||
|
|
_forceHasRLiquidity))
|
|
{
|
|
//
|
|
toIDX = tb.ToIndex();
|
|
fromIDX = tb.FromIndex();
|
|
for (int i = toIDX; i < fromIDX + loopback; i++)
|
|
{
|
|
//
|
|
// Initialize iBar ...
|
|
isDone = iBar.Init(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
i //
|
|
);
|
|
|
|
//
|
|
bool isRejected =
|
|
isDone &&
|
|
barAnalyser.IsRejected(
|
|
iBar,
|
|
iDir,
|
|
false, // Force Bar Type ...
|
|
true // Force Fibo Pressure ...
|
|
);
|
|
|
|
//
|
|
// Following Liquidity ...
|
|
bool isFLiq =
|
|
isDone &&
|
|
isRejected &&
|
|
iDir == tb.GetDirection() &&
|
|
(isBullish
|
|
? iBar.low < tb.trigger.lower
|
|
: iBar.high > tb.trigger.upper);
|
|
if (isFLiq &&
|
|
_forceHasFLiquidity &&
|
|
!tb.fLiquidity.IsValid())
|
|
{
|
|
//
|
|
FillLiquidity(
|
|
iBar,
|
|
iDir,
|
|
tb.fLiquidity,
|
|
tb.trigger.to //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Reversal Liquidity ...
|
|
bool isRLiq =
|
|
isDone &&
|
|
isRejected &&
|
|
Opposit(iDir) == tb.GetDirection() &&
|
|
(isBullish
|
|
? iBar.low > tb.trigger.upper
|
|
: iBar.high < tb.trigger.lower);
|
|
if (isRLiq &&
|
|
_forceHasRLiquidity &&
|
|
!tb.rLiquidity.IsValid())
|
|
{
|
|
//
|
|
FillLiquidity(
|
|
iBar,
|
|
iDir,
|
|
tb.rLiquidity,
|
|
tb.trigger.to //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Checking Conditions ...
|
|
isDone =
|
|
(!_forceHasFLiquidity
|
|
? true
|
|
: tb.fLiquidity.IsValid()) &&
|
|
(!_forceHasRLiquidity
|
|
? true
|
|
: tb.rLiquidity.IsValid());
|
|
if (isDone)
|
|
{
|
|
//
|
|
iBar.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Checking Conditions ...
|
|
has =
|
|
(!_forceHasFLiquidity
|
|
? true
|
|
: tb.fLiquidity.IsValid()) &&
|
|
(!_forceHasRLiquidity
|
|
? true
|
|
: tb.rLiquidity.IsValid());
|
|
}
|
|
|
|
//
|
|
// Validations ...
|
|
|
|
//
|
|
// Validating Gap Sequence means
|
|
// Gap Bars must Follow each Other ...
|
|
if (has &&
|
|
_validateGapSequence)
|
|
{
|
|
//
|
|
XOHCL iPBar;
|
|
toIDX = tb.fvg.ToIndex();
|
|
fromIDX = tb.fvg.FromIndex();
|
|
|
|
//
|
|
for (int i = toIDX; i < fromIDX - 1; i++)
|
|
{
|
|
//
|
|
// Initialize iBar ...
|
|
has = iBar.Init(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
i //
|
|
);
|
|
has =
|
|
has &&
|
|
iBar.GetPreviousBar(iPBar);
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? iBar.low > iPBar.low
|
|
: iBar.high < iPBar.high);
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Validate Block Edge Breakout ...
|
|
if (has &&
|
|
_validateBlockEdgeBreakout)
|
|
{
|
|
//
|
|
has = tb.fvg.ToBar(iBar);
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? (iBar.GetDown() < tb.ob.upper &&
|
|
iBar.GetUp() > tb.ob.upper)
|
|
: (iBar.GetDown() < tb.ob.lower &&
|
|
iBar.GetUp() > tb.ob.lower));
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Filters ...
|
|
|
|
//
|
|
// PV ...
|
|
if (has &&
|
|
_filterBasedOnPV)
|
|
{
|
|
//
|
|
double iPeak = _peakBuffer[barIndex];
|
|
double iPPeak = _peakBuffer[barIndex + 1];
|
|
double iP2Peak = _peakBuffer[barIndex + 2];
|
|
|
|
//
|
|
double iPeakGolden = _peakGoldenBuffer[barIndex];
|
|
double iPPeakGolden = _peakGoldenBuffer[barIndex + 1];
|
|
double iP2PeakGolden = _peakGoldenBuffer[barIndex + 2];
|
|
|
|
//
|
|
double iVale = _valeBuffer[barIndex];
|
|
double iPVale = _valeBuffer[barIndex + 1];
|
|
double iP2Vale = _valeBuffer[barIndex + 2];
|
|
|
|
//
|
|
double iValeGolden = _valeGoldenBuffer[barIndex];
|
|
double iPValeGolden = _valeGoldenBuffer[barIndex + 1];
|
|
double iP2ValeGolden = _valeGoldenBuffer[barIndex + 2];
|
|
|
|
//
|
|
// TODO: Fix this ...
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? (tb.trigger.lower <= iVale &&
|
|
tb.trigger.upper < iPeak
|
|
// || tb.trigger.lower <= iValeGolden
|
|
)
|
|
: (tb.trigger.upper >= iPeak &&
|
|
tb.trigger.lower > iVale
|
|
// || tb.trigger.upper >= iPeakGolden
|
|
));
|
|
}
|
|
|
|
//
|
|
// SAR ...
|
|
if (has &&
|
|
_filterBasedOnSar)
|
|
{
|
|
//
|
|
double iSarState = _sarStateBuffer[barIndex];
|
|
double iPSarState = _sarStateBuffer[barIndex + 1];
|
|
double iP2SarState = _sarStateBuffer[barIndex + 2];
|
|
|
|
//
|
|
bool isSarBullish = iSarState > 0;
|
|
bool isPSarBullish = iPSarState > 0;
|
|
bool isP2SarBullish = iP2SarState > 0;
|
|
|
|
//
|
|
bool isSarBearish = iSarState < 0;
|
|
bool isPSarBearish = iPSarState < 0;
|
|
bool isP2SarBearish = iP2SarState < 0;
|
|
|
|
//
|
|
bool isSarSwitchedToBullish =
|
|
isSarBullish &&
|
|
!isPSarBullish;
|
|
|
|
//
|
|
bool isSarSwitchedToBearish =
|
|
isSarBearish &&
|
|
!isPSarBearish;
|
|
|
|
//
|
|
bool isSarPSwitchedToBullish =
|
|
isPSarBullish &&
|
|
!isP2SarBullish;
|
|
|
|
//
|
|
bool isSarPSwitchedToBearish =
|
|
isPSarBearish &&
|
|
!isP2SarBearish;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? (isSarSwitchedToBullish ||
|
|
isSarPSwitchedToBullish)
|
|
: (isSarSwitchedToBearish ||
|
|
isSarPSwitchedToBearish));
|
|
}
|
|
|
|
//
|
|
// RSI ...
|
|
if (has &&
|
|
_filterBasedOnRSI)
|
|
{
|
|
//
|
|
double rsiTrend = (_rsiOBLevel + _rsiOSLevel) / 2;
|
|
|
|
//
|
|
double iRSI = _rsiBuffer[barIndex];
|
|
double iPRSI = _rsiBuffer[barIndex + 1];
|
|
double iP2RSI = _rsiBuffer[barIndex + 2];
|
|
|
|
//
|
|
bool isRSICrossedOverOS =
|
|
iRSI > _rsiOSLevel &&
|
|
iPRSI <= _rsiOSLevel;
|
|
|
|
//
|
|
bool isRSICrossedUnderOB =
|
|
iRSI < _rsiOBLevel &&
|
|
iPRSI >= _rsiOBLevel;
|
|
|
|
//
|
|
bool isPRSICrossedOverOS =
|
|
iPRSI > _rsiOSLevel &&
|
|
iP2RSI <= _rsiOSLevel;
|
|
|
|
//
|
|
bool isPRSICrossedUnderOB =
|
|
iPRSI < _rsiOBLevel &&
|
|
iP2RSI >= _rsiOBLevel;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? (isRSICrossedOverOS ||
|
|
isPRSICrossedOverOS)
|
|
: (isRSICrossedUnderOB ||
|
|
isPRSICrossedUnderOB));
|
|
}
|
|
|
|
//
|
|
// ADX ...
|
|
if (has &&
|
|
_filterBasedOnADX)
|
|
{
|
|
//
|
|
// ADX ...
|
|
double iADX = _adxBuffer[barIndex];
|
|
double iPADX = _adxBuffer[barIndex + 1];
|
|
double iP2ADX = _adxBuffer[barIndex + 2];
|
|
|
|
//
|
|
// ADX +DI ...
|
|
double iADXP = _adxpBuffer[barIndex];
|
|
double iPADXP = _adxpBuffer[barIndex + 1];
|
|
double iP2ADXP = _adxpBuffer[barIndex + 2];
|
|
|
|
//
|
|
// ADX -DI ...
|
|
double iADXN = _adxnBuffer[barIndex];
|
|
double iPADXN = _adxnBuffer[barIndex + 1];
|
|
double iP2ADXN = _adxnBuffer[barIndex + 2];
|
|
|
|
//
|
|
// Preparing Conditions ...
|
|
|
|
//
|
|
bool isADXBullish = iADX > _adxThreshold;
|
|
bool isADXBearish = iADX < _adxThreshold;
|
|
|
|
//
|
|
bool isPADXBullish = iPADX > _adxThreshold;
|
|
bool isPADXBearish = iPADX < _adxThreshold;
|
|
|
|
//
|
|
bool isP2ADXBullish = iP2ADX > _adxThreshold;
|
|
bool isP2ADXBearish = iP2ADX < _adxThreshold;
|
|
|
|
//
|
|
bool isADXSwitchedToBullish =
|
|
isADXBullish &&
|
|
!isPADXBullish;
|
|
|
|
//
|
|
bool isADXSwitchedToBearish =
|
|
isADXBearish &&
|
|
!isPADXBearish;
|
|
|
|
//
|
|
bool isPADXSwitchedToBullish =
|
|
isPADXBullish &&
|
|
!isP2ADXBullish;
|
|
|
|
//
|
|
bool isPADXSwitchedToBearish =
|
|
isPADXBearish &&
|
|
!isP2ADXBearish;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? (isADXSwitchedToBullish ||
|
|
isPADXSwitchedToBullish)
|
|
: (isADXSwitchedToBearish ||
|
|
isPADXSwitchedToBearish));
|
|
}
|
|
|
|
//
|
|
// ATR ...
|
|
if (has &&
|
|
_filterBasedOnATR)
|
|
{
|
|
//
|
|
fromIDX = tb.FromIndex();
|
|
double iATRUpper = _atrUpperBuffer[fromIDX];
|
|
double iATRLower = _atrLowerBuffer[fromIDX];
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? tb.trigger.lower < iATRLower
|
|
: tb.trigger.upper > iATRUpper);
|
|
}
|
|
|
|
//
|
|
// TREND ...
|
|
if (has &&
|
|
_filterBasedOnTrend)
|
|
{
|
|
//
|
|
double iTrendState = _trendStateBuffer[barIndex];
|
|
double iPTrendState = _trendStateBuffer[barIndex + 1];
|
|
|
|
//
|
|
bool isTrendBullish = iTrendState > 0;
|
|
bool isPTrendBullish = iPTrendState > 0;
|
|
|
|
//
|
|
bool isTrendBearish = iTrendState < 0;
|
|
bool isPTrendBearish = iPTrendState < 0;
|
|
|
|
//
|
|
double trends[];
|
|
int toIDX = tb.ToIndex();
|
|
int fromIDX = tb.FromIndex();
|
|
double iTrend = _trendBuffer[toIDX];
|
|
for (int i = toIDX; i <= fromIDX; i++)
|
|
{
|
|
//
|
|
Add(
|
|
_trendBuffer[i],
|
|
trends //
|
|
);
|
|
}
|
|
double trendsMin = GetMin(trends);
|
|
double trendsMax = GetMax(trends);
|
|
double trendsAVG = GetAverage(trends);
|
|
|
|
//
|
|
bool isTrendUp =
|
|
iTrend > trendsMin &&
|
|
iTrend >= trendsAVG;
|
|
|
|
//
|
|
bool isTrendDown =
|
|
iTrend < trendsMax &&
|
|
iTrend <= trendsAVG;
|
|
|
|
//
|
|
bool isTrendSwitchedToBullish =
|
|
isTrendUp &&
|
|
isTrendBullish &&
|
|
!isPTrendBullish;
|
|
|
|
//
|
|
bool isTrendSwitchedToBearish =
|
|
isTrendDown &&
|
|
isTrendBearish &&
|
|
!isPTrendBearish;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? isTrendSwitchedToBullish
|
|
: isTrendSwitchedToBearish);
|
|
}
|
|
|
|
//
|
|
// DELTA ...
|
|
if (has &&
|
|
_filterBasedOnDelta)
|
|
{
|
|
//
|
|
double iDelta = _deltaBuffer[barIndex];
|
|
double iPDelta = _deltaBuffer[barIndex + 1];
|
|
|
|
//
|
|
bool isDeltaUp = iDelta > iPDelta;
|
|
bool isDeltaDown = iDelta < iPDelta;
|
|
|
|
//
|
|
double iDeltaSignal = _deltaSignalBuffer[barIndex];
|
|
double iPDeltaSignal = _deltaSignalBuffer[barIndex + 1];
|
|
|
|
//
|
|
bool isDeltaSignalUp = iDeltaSignal > iPDeltaSignal;
|
|
bool isDeltaSignalDown = iDeltaSignal < iPDeltaSignal;
|
|
|
|
//
|
|
bool isDeltaSwitchedToBullish =
|
|
isDeltaUp &&
|
|
isDeltaSignalUp &&
|
|
iDelta > iDeltaSignal &&
|
|
iPDelta < iPDeltaSignal;
|
|
|
|
//
|
|
bool isDeltaSwitchedToBearish =
|
|
isDeltaDown &&
|
|
isDeltaSignalDown &&
|
|
iDelta < iDeltaSignal &&
|
|
iPDelta > iPDeltaSignal;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? isDeltaSwitchedToBullish
|
|
: isDeltaSwitchedToBearish);
|
|
}
|
|
|
|
//
|
|
// VOLUME ...
|
|
if (has &&
|
|
_filterBasedOnVolume)
|
|
{
|
|
//
|
|
double iBullishVolumeSignal = _bullishVolumeSignalBuffer[barIndex];
|
|
double iPBullishVolumeSignal = _bullishVolumeSignalBuffer[barIndex + 1];
|
|
|
|
//
|
|
bool isBullishVolumeSignalUp = iBullishVolumeSignal > iPBullishVolumeSignal;
|
|
bool isBullishVolumeSignalDown = iBullishVolumeSignal < iPBullishVolumeSignal;
|
|
|
|
//
|
|
double iBearishVolumeSignal = _bearishVolumeSignalBuffer[barIndex];
|
|
double iPBearishVolumeSignal = _bearishVolumeSignalBuffer[barIndex + 1];
|
|
|
|
//
|
|
bool isBearishVolumeSignalUp = iBearishVolumeSignal > iPBearishVolumeSignal;
|
|
bool isBearishVolumeSignalDown = iBearishVolumeSignal < iPBearishVolumeSignal;
|
|
|
|
//
|
|
bool isVolumeSwitchdToBullish =
|
|
isBullishVolumeSignalUp &&
|
|
!isBearishVolumeSignalUp &&
|
|
iBullishVolumeSignal > iBearishVolumeSignal &&
|
|
iPBullishVolumeSignal < iPBearishVolumeSignal;
|
|
|
|
//
|
|
bool isVolumeSwitchdToBearish =
|
|
isBearishVolumeSignalUp &&
|
|
!isBullishVolumeSignalUp &&
|
|
iBearishVolumeSignal > iBullishVolumeSignal &&
|
|
iPBearishVolumeSignal < iPBullishVolumeSignal;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? isVolumeSwitchdToBullish
|
|
: isVolumeSwitchdToBearish);
|
|
}
|
|
|
|
//
|
|
// SIGNAL Bar ...
|
|
if (has &&
|
|
_filterBasedOnSignalBar)
|
|
{
|
|
//
|
|
double iSignalOpen = _sBarOpenSBuffer[barIndex];
|
|
double iPSignalOpen = _sBarOpenSBuffer[barIndex + 1];
|
|
|
|
//
|
|
double iSignalClose = _sBarCloseBuffer[barIndex];
|
|
double iPSignalClose = _sBarCloseBuffer[barIndex + 1];
|
|
|
|
//
|
|
bool isSignalBarBullish = iSignalOpen < iSignalClose;
|
|
bool isPSignalBarBullish = iPSignalOpen < iPSignalClose;
|
|
|
|
//
|
|
bool isSignalBarBearish = iSignalOpen > iSignalClose;
|
|
bool isPSignalBarBearish = iPSignalOpen > iPSignalClose;
|
|
|
|
//
|
|
bool isSignalBarSwitchedToBullish =
|
|
isSignalBarBullish &&
|
|
!isPSignalBarBullish;
|
|
|
|
//
|
|
bool isSignalBarSwitchedToBearish =
|
|
isSignalBarBearish &&
|
|
!isPSignalBarBearish;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? isSignalBarSwitchedToBullish
|
|
: isSignalBarSwitchedToBearish);
|
|
}
|
|
|
|
//
|
|
// HK SIGNAL Bar ...
|
|
if (has &&
|
|
_filterBasedOnHKSignalBar)
|
|
{
|
|
//
|
|
double iHKSignalOpen = _hkSBarOpenBuffer[barIndex];
|
|
double iPHKSignalOpen = _hkSBarOpenBuffer[barIndex + 1];
|
|
|
|
//
|
|
double iHKSignalClose = _hkSBarCloseBuffer[barIndex];
|
|
double iPHKSignalClose = _hkSBarCloseBuffer[barIndex + 1];
|
|
|
|
//
|
|
bool isHKSignalBarBullish = iHKSignalOpen < iHKSignalClose;
|
|
bool isPHKSignalBarBullish = iPHKSignalOpen < iPHKSignalClose;
|
|
|
|
//
|
|
bool isHKSignalBarBearish = iHKSignalOpen > iHKSignalClose;
|
|
bool isPHKSignalBarBearish = iPHKSignalOpen > iPHKSignalClose;
|
|
|
|
//
|
|
bool isHKSignalBarSwitchedToBullish =
|
|
isHKSignalBarBullish &&
|
|
!isPHKSignalBarBullish;
|
|
|
|
//
|
|
bool isHKSignalBarSwitchedToBearish =
|
|
isHKSignalBarBearish &&
|
|
!isPHKSignalBarBearish;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? isHKSignalBarSwitchedToBullish
|
|
: isHKSignalBarSwitchedToBearish);
|
|
}
|
|
|
|
//
|
|
// Valdating Directional Trending ...
|
|
bool _filterBasedOnDirection = false;
|
|
if (has &&
|
|
_filterBasedOnDirection)
|
|
{
|
|
//
|
|
iBar.Clean();
|
|
fromIDX = tb.FromIndex();
|
|
int loopbackForValidating = 30;
|
|
for (int i = fromIDX; i < fromIDX + loopbackForValidating; i++)
|
|
{
|
|
//
|
|
// Initialize iBar ...
|
|
iBar.Clean();
|
|
has = iBar.Init(
|
|
symbol,
|
|
period,
|
|
i //
|
|
);
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? iBar.high < tb.trigger.upper
|
|
: iBar.low > tb.trigger.lower);
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update Trigger Block ...
|
|
if (has)
|
|
{
|
|
tb.trigger.from = iBar.time;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Preparing Signal ...
|
|
if (has)
|
|
{
|
|
//
|
|
// CArrayObj *tbObjects = new CArrayObj();
|
|
// DrawTriggerBlock(
|
|
// tb,
|
|
// drawer,
|
|
// tbObjects,
|
|
// NULL //
|
|
// );
|
|
|
|
//
|
|
double targets[];
|
|
for (int i = 1; i <= _r2r; i++)
|
|
{
|
|
//
|
|
Add(
|
|
(double)i,
|
|
targets //
|
|
);
|
|
}
|
|
|
|
//
|
|
double iATR = 0;
|
|
if (barIndex > 0 &&
|
|
barIndex < ArraySize(_atrBuffer))
|
|
{
|
|
iATR = _atrBuffer[barIndex];
|
|
}
|
|
double slAdditional = _slAtrMultiplier * iATR;
|
|
|
|
//
|
|
has = ToSignal(
|
|
tb.trigger,
|
|
tb.signal,
|
|
targets,
|
|
slAdditional //
|
|
);
|
|
}
|
|
|
|
//
|
|
result = has;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Signal ...
|
|
// int signalR2R; // Risk Reward Ratio
|
|
// bool drawSignals; // Draw Signal
|
|
// bool drawTriggerBlock; // Draw Trigger Block
|
|
// double slAtrMultiplier; // ATR Multiplier for SL
|
|
|
|
//
|
|
// Validating ...
|
|
bool forceHasSwing; // Force Blocks to Have Swing
|
|
bool forceOBBarType; // Force Block Has Reversal Bar
|
|
bool forceOBFVGBarType; // Force FVG Has Same Bars
|
|
bool forceHasFLiquidity; // Force Blocks to Have Following Liquidity
|
|
bool forceHasRLiquidity; // Force Blocks to Have Reversal Liquidity
|
|
bool validateGapSequence; // Validate Block's Gap Sequence
|
|
bool validateBlockEdgeBreakout; // Validate Block's Edge Breakout
|
|
|
|
//
|
|
// Filtering ...
|
|
bool filterBasedOnPV; // Filter Based on Peak and Vale
|
|
bool filterBasedOnSar; // Filter Based on Sar
|
|
bool filterBasedOnRSI; // Filter Based on RSI
|
|
bool filterBasedOnADX; // Filter Based on ADX
|
|
bool filterBasedOnATR; // Filter Based on ATR
|
|
bool filterBasedOnTrend; // Filter Based on Trend
|
|
bool filterBasedOnDelta; // Filter Based on Delta
|
|
bool filterBasedOnVolume; // Filter Based on Volume
|
|
bool filterBasedOnSignalBar; // Filter Based on Signal Bar
|
|
bool filterBasedOnHKSignalBar; // Filter Based on Hiken Ashi Signal Bar
|
|
|
|
//
|
|
// Alert ...
|
|
string alertPrefix; // Alert Prefix
|
|
bool logAlerts; // Log Alerts
|
|
bool pushAlerts; // Push Alerts
|
|
bool mailAlerts; // Mail Alerts
|
|
bool terminalAlerts; // Terminal Alerts
|
|
|
|
//
|
|
// Initialize and Configure Alert ...
|
|
mAlert = new XCAlert();
|
|
mEnableAlerts =
|
|
_logAlerts ||
|
|
_pushAlerts ||
|
|
_mailAlerts ||
|
|
_terminalAlerts;
|
|
string mPrefix = ShortName +
|
|
(!IsValid(mAlertPrefix)
|
|
? ""
|
|
: "[" + mAlertPrefix + "]");
|
|
mAlert.SetPrefix(mPrefix);
|
|
mAlert.SetLogAlerts(_logAlerts);
|
|
mAlert.SetMailAlerts(_mailAlerts);
|
|
mAlert.SetPushAlerts(_pushAlerts);
|
|
mAlert.SetEnableAlerts(mEnableAlerts);
|
|
mAlert.SetTerminalAlerts(_terminalAlerts);
|
|
|
|
//
|
|
// Validating ...
|
|
forceHasSwing = false; // Force Blocks to Have Swing
|
|
forceOBBarType = false; // Force Block Has Reversal Bar
|
|
forceOBFVGBarType = false; // Force FVG Has Same Bars
|
|
forceHasFLiquidity = false; // Force Blocks to Have Following Liquidity
|
|
forceHasRLiquidity = false; // Force Blocks to Have Reversal Liquidity
|
|
validateGapSequence = false; // Validate Block's Gap Sequence
|
|
validateBlockEdgeBreakout = false; // Validate Block's Edge Breakout
|
|
|
|
//
|
|
// Filtering ...
|
|
filterBasedOnPV = false; // Filter Based on Peak and Vale
|
|
filterBasedOnSar = false; // Filter Based on Sar
|
|
filterBasedOnRSI = false; // Filter Based on RSI
|
|
filterBasedOnADX = false; // Filter Based on ADX
|
|
filterBasedOnATR = false; // Filter Based on ATR
|
|
filterBasedOnTrend = false; // Filter Based on Trend
|
|
filterBasedOnDelta = false; // Filter Based on Delta
|
|
filterBasedOnVolume = false; // Filter Based on Volume
|
|
filterBasedOnSignalBar = false; // Filter Based on Signal Bar
|
|
filterBasedOnHKSignalBar = false; // Filter Based on Hiken Ashi Signal Bar
|
|
|
|
//
|
|
// Alert ...
|
|
alertPrefix = ""; // Alert Prefix
|
|
logAlerts = false; // Log Alerts
|
|
pushAlerts = false; // Push Alerts
|
|
mailAlerts = false; // Mail Alerts
|
|
terminalAlerts = false; // Terminal Alerts
|
|
|
|
//
|
|
// Validating ...
|
|
forceHasSwing = false; // Force Blocks to Have Swing
|
|
forceOBBarType = false; // Force Block Has Reversal Bar
|
|
forceOBFVGBarType = false; // Force FVG Has Same Bars
|
|
forceHasFLiquidity = false; // Force Blocks to Have Following Liquidity
|
|
forceHasRLiquidity = false; // Force Blocks to Have Reversal Liquidity
|
|
validateGapSequence = false; // Validate Block's Gap Sequence
|
|
validateBlockEdgeBreakout = false; // Validate Block's Edge Breakout
|
|
|
|
//
|
|
// Filtering ...
|
|
filterBasedOnPV = false; // Filter Based on Peak and Vale
|
|
filterBasedOnSar = false; // Filter Based on Sar
|
|
filterBasedOnRSI = false; // Filter Based on RSI
|
|
filterBasedOnADX = false; // Filter Based on ADX
|
|
filterBasedOnATR = false; // Filter Based on ATR
|
|
filterBasedOnTrend = false; // Filter Based on Trend
|
|
filterBasedOnDelta = false; // Filter Based on Delta
|
|
filterBasedOnVolume = false; // Filter Based on Volume
|
|
filterBasedOnSignalBar = false; // Filter Based on Signal Bar
|
|
filterBasedOnHKSignalBar = false; // Filter Based on Hiken Ashi Signal Bar
|
|
|
|
//
|
|
// Alert ...
|
|
alertPrefix = ""; // Alert Prefix
|
|
logAlerts = false; // Log Alerts
|
|
pushAlerts = false; // Push Alerts
|
|
mailAlerts = false; // Mail Alerts
|
|
terminalAlerts = false; // Terminal Alerts
|
|
|
|
"", // Validating ...
|
|
mInputs.forceHasSwing,
|
|
mInputs.forceOBBarType,
|
|
mInputs.forceOBFVGBarType,
|
|
mInputs.forceHasFLiquidity,
|
|
mInputs.forceHasRLiquidity,
|
|
mInputs.validateGapSequence,
|
|
mInputs.validateBlockEdgeBreakout,
|
|
"", // Filtering ...
|
|
mInputs.filterBasedOnPV,
|
|
mInputs.filterBasedOnSar,
|
|
mInputs.filterBasedOnRSI,
|
|
mInputs.filterBasedOnADX,
|
|
mInputs.filterBasedOnATR,
|
|
mInputs.filterBasedOnTrend,
|
|
mInputs.filterBasedOnDelta,
|
|
mInputs.filterBasedOnVolume,
|
|
mInputs.filterBasedOnSignalBar,
|
|
mInputs.filterBasedOnHKSignalBar,
|
|
"", // Alerts ...
|
|
mInputs.alertPrefix,
|
|
mInputs.logAlerts,
|
|
mInputs.pushAlerts,
|
|
mInputs.mailAlerts,
|
|
mInputs.terminalAlerts,
|
|
|
|
//
|
|
// Validating ...
|
|
input group "Validating";
|
|
input bool forceHasSwing = false; // Force Blocks to Have Swing
|
|
input bool forceObBarType = false; // Force Block Has Reversal Bar
|
|
input bool forceOBFVGBarType = false; // Force FVG Has Same Bars
|
|
input bool forceHasFLiquidity = false; // Force Blocks to Have Following Liquidity
|
|
input bool forceHasRLiquidity = false; // Force Blocks to Have Reversal Liquidity
|
|
input bool validateGapSequence = false; // Validate Block's Gap Sequence
|
|
input bool validateBlockEdgeBreakout = false; // Validate Block's Edge Breakout
|
|
|
|
//
|
|
// Filtering ...
|
|
input group "Filtering";
|
|
input bool filterBasedOnPV = false; // Filter Based on Peak and Vale
|
|
input bool filterBasedOnSar = false; // Filter Based on Sar
|
|
input bool filterBasedOnRSI = false; // Filter Based on RSI
|
|
input bool filterBasedOnADX = false; // Filter Based on ADX
|
|
input bool filterBasedOnATR = false; // Filter Based on ATR
|
|
input bool filterBasedOnTrend = false; // Filter Based on Trend
|
|
input bool filterBasedOnDelta = false; // Filter Based on Delta
|
|
input bool filterBasedOnVolume = false; // Filter Based on Volume
|
|
input bool filterBasedOnSignalBar = false; // Filter Based on Signal Bar
|
|
input bool filterBasedOnHKSignalBar = false; // Filter Based on Hiken Ashi Signal Bar
|
|
|
|
//
|
|
// Alert ...
|
|
input group "Alerts";
|
|
input string mAlertPrefix = ""; // Alert Prefix
|
|
input bool _logAlerts = false; // Log Alerts
|
|
input bool _pushAlerts = false; // Push Alerts
|
|
input bool _mailAlerts = false; // Mail Alerts
|
|
input bool _terminalAlerts = false; // Terminal Alerts
|
|
|
|
|
|
//
|
|
// Set Validators ...
|
|
eaInputs.forceHasSwing = eaForceHasSwing;
|
|
eaInputs.forceOBBarType = eaForceOBBarType;
|
|
eaInputs.forceOBFVGBarType = eaForceOBFVGBarType;
|
|
eaInputs.forceHasFLiquidity = eaForceHasFLiquidity;
|
|
eaInputs.forceHasRLiquidity = eaForceHasRLiquidity;
|
|
eaInputs.validateGapSequence = eaValidateGapSequence;
|
|
eaInputs.validateBlockEdgeBreakout = eaValidateBlockEdgeBreakout;
|
|
|
|
//
|
|
// Set Filters ...
|
|
eaInputs.filterBasedOnPV = eaFilterBasedOnPV;
|
|
eaInputs.filterBasedOnSar = eaFilterBasedOnSar;
|
|
eaInputs.filterBasedOnRSI = eaFilterBasedOnRSI;
|
|
eaInputs.filterBasedOnADX = eaFilterBasedOnADX;
|
|
eaInputs.filterBasedOnATR = eaFilterBasedOnATR;
|
|
eaInputs.filterBasedOnTrend = eaFilterBasedOnTrend;
|
|
eaInputs.filterBasedOnDelta = eaFilterBasedOnDelta;
|
|
eaInputs.filterBasedOnVolume = eaFilterBasedOnVolume;
|
|
eaInputs.filterBasedOnSignalBar = eaFilterBasedOnSignalBar;
|
|
eaInputs.filterBasedOnHKSignalBar = eaFilterBasedOnHKSignalBar;
|
|
|
|
//
|
|
// Alerts ...
|
|
eaInputs.alertPrefix = eaTag;
|
|
eaInputs.logAlerts = false; // eaLogAlerts;
|
|
eaInputs.pushAlerts = false; // eaMailAlerts;
|
|
eaInputs.mailAlerts = false; // eaPushAlerts;
|
|
eaInputs.terminalAlerts = false; // eaTerminalAlerts;
|
|
|
|
|
|
|
|
//
|
|
// TODO: Remove this ...
|
|
// Temparory Testing Configs ...
|
|
// validations.maxAllowedRange = 200;
|
|
// validations.forceHasSwing = true;
|
|
// validations.forceFVGBarType = true;
|
|
// validations.forceOBBarType = true;
|
|
// validations.validateGapSequence = true;
|
|
// validations.validateBlockEdgeBreakout = true;
|
|
// validations.liquidityLoopback = 144;
|
|
// validations.forceHasFLiquidity = true;
|
|
// validations.forceHasRLiquidity = true;
|
|
// validations.minAllowedBlockLength = 7;
|
|
|
|
//
|
|
// TODO: Remove this ...
|
|
// filters.bosLoopback = 0;
|
|
// filters.filterBasedOnPV = true;
|
|
// filters.filterBasedOnSar = true;
|
|
// filters.forceSarSwitched = false;
|
|
// filters.forceSarOnBothSide = true;
|
|
// filters.forceSarHasBreakout = true;
|
|
// filters.forceSarHasReversalSide = false;
|
|
// filters.filterBasedOnRSI = false;
|
|
// filters.forceHasRSITrending = false;
|
|
// filters.forceHasRSIVPattern = false;
|
|
// filters.forceHasRSICrossing = false;
|
|
// filters.filterBasedOnADX = true;
|
|
// filters.forceHasADXTrending = false;
|
|
// filters.forceHasADXCrossing = true;
|
|
// filters.filterBasedOnATR = true;
|
|
// filters.forceHasATRTrending = true;
|
|
// filters.forceHasATRBreakout = true;
|
|
// filters.filterBasedOnTrend = false;
|
|
// filters.forceHasTrendDir = false;
|
|
// filters.forceHasTrendPlace = false;
|
|
// filters.forceHasTrendChange = false;
|
|
// filters.forceHasTrendTrending = false;
|
|
// filters.forceHasTrendRejection = false;
|
|
// filters.forceHasTrendLineInside = false;
|
|
// filters.forceHasTrendDirOnBothSide = false;
|
|
// filters.filterBasedOnDelta = false;
|
|
// filters.filterBasedOnVolume = false;
|
|
// filters.filterBasedOnSignalBar = true;
|
|
// filters.filterBasedOnHKSignalBar = true;
|