apply new mechanism for validating anf filtering ...

This commit is contained in:
2025-05-29 01:13:31 +03:30
parent b41552a18c
commit 04d11702fe
5 changed files with 1019 additions and 354 deletions
+629 -53
View File
@@ -219,9 +219,22 @@ struct XTriggerBlockFilters
bool forceHasRSICrossing; // RSI Must Has Crossing Levels ...
//
bool forceHasADXTrending; // ADX Must Trending ...
bool forceHasADXTrending; // ADX Must Has Trending ...
bool forceHasADXCrossing; // ADX Must Has Crossing +DI/-DI ...
//
bool forceHasATRTrending; // ATR Must Has Trending ...
bool forceHasATRBreakout; // ATR Must Has Breakout ...
//
bool forceHasTrendDir; // TREND Must Has Following Direction ...
bool forceHasTrendPlace; // TREND Place Based Filtering ...
bool forceHasTrendChange; // TREND Change Filtering ...
bool forceHasTrendTrending; // TREND Must Has Trending ...
bool forceHasTrendRejection; // TREND Line Must Rejected ...
bool forceHasTrendLineInside; // TREND Line has Inside ...
bool forceHasTrendDirOnBothSide; // TREND Must Has Following Direction in Both Side ...
//
// Constructor(s) ...
XTriggerBlockFilters()
@@ -266,6 +279,19 @@ struct XTriggerBlockFilters
forceHasADXTrending = false;
forceHasADXCrossing = false;
//
forceHasATRTrending = false;
forceHasATRBreakout = false;
//
forceHasTrendDir = false;
forceHasTrendPlace = false;
forceHasTrendChange = false;
forceHasTrendTrending = false;
forceHasTrendRejection = false;
forceHasTrendLineInside = false;
forceHasTrendDirOnBothSide = false;
//
ZeroMemory(this);
}
@@ -429,20 +455,6 @@ bool DetectTriggerBlock1(
iBar.Clean();
}
//
// 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;
//
// Apply Validations ...
if (result)
@@ -465,23 +477,6 @@ bool DetectTriggerBlock1(
}
}
//
// 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;
//
// Apply Filtering ...
if (result)
@@ -1648,11 +1643,589 @@ bool FilterTriggerBlock(
//
result = has;
}
}
//
// Filter Based On ATR Band ...
if (result &&
filters.filterBasedOnATR)
{
//
// Here We Can Apply ATR Filters ...
// Since ATR Filters must be Check on OB Bars ...
// we Have to Loop back Based on OB Bars to Detect Conditions ...
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
//
// Filter Using ATR Trending ...
if (result &&
filters.forceHasATRTrending)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iATRUpper = helper.GetATRUpper(i);
double iPATRUpper = helper.GetATRUpper(i + 1);
//
double iATRLower = helper.GetATRLower(i);
double iPATRLower = helper.GetATRLower(i + 1);
//
bool isATRUp =
iATRLower > iPATRLower;
//
bool isATRDown =
iATRUpper < iPATRUpper;
//
has = isBullish
? isATRUp
: isATRDown;
if (has)
{
break;
}
}
//
result = has;
}
//
// Filter Using ATR Breakout ...
if (result &&
filters.forceHasATRBreakout)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iATRUpper = helper.GetATRUpper(i);
double iATRLower = helper.GetATRLower(i);
//
has = isBullish
? triggerBlock.ob.lower < iATRLower
: triggerBlock.ob.upper > iATRUpper;
if (has)
{
break;
}
}
//
result = has;
}
}
//
// Filter Based On Trend ...
if (result &&
filters.filterBasedOnTrend)
{
//
toIDX = triggerBlock.fvg.ToIndex();
fromIDX = triggerBlock.fvg.FromIndex();
//
// Filter Using Trend Direction ...
if (result &&
filters.forceHasTrendDir)
{
//
result =
result &&
isBullish
? conditions.isTrendBullish
: conditions.isTrendBearish;
}
//
// Filter Using Trend Direction On Both Side ...
if (result &&
filters.forceHasTrendDirOnBothSide)
{
//
// Side To ...
result =
result &&
isBullish
? conditions.isTrendBullish
: conditions.isTrendBearish;
//
// Side From ...
int sFIDX = triggerBlock.ob.FromIndex();
double sFTrendState = helper.GetTrendState(sFIDX);
result =
result &&
isBullish
? sFTrendState > 0
: sFTrendState < 0;
}
//
// Filter Using Trend Change ...
if (result &&
filters.forceHasTrendChange)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iTrendState = helper.GetTrendState(i);
double iPTrendState = helper.GetTrendState(i + 1);
//
bool isTrendSwitchedToBullish =
iTrendState > 0 &&
iPTrendState <= 0;
//
bool isTrendSwitchedToBearish =
iTrendState < 0 &&
iPTrendState >= 0;
//
has =
isBullish
? isTrendSwitchedToBullish
: isTrendSwitchedToBearish;
if (has)
{
break;
}
}
//
result = has;
}
//
// Filter Using Trend Trending ...
if (result &&
filters.forceHasTrendTrending)
{
//
result =
result &&
(isBullish
? conditions.trendBuffer[cIDX] > conditions.trendBuffer[pIDX]
: conditions.trendBuffer[cIDX] < conditions.trendBuffer[pIDX]);
}
//
// Filter Using Trend Rejection ...
if (result &&
filters.forceHasTrendRejection)
{
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
for (int i = toIDX; i < fromIDX; i++)
{
//
// Initialize iBar ...
has = iBar.Init(
conditions.symbol,
conditions.period,
i //
);
//
// Read Trend Value ...
double iTrend = helper.GetTrend(i);
//
bool isTrendBullishRejected =
has &&
iBar.low < iTrend &&
iBar.GetDown() > iTrend;
//
bool isTrendBearishRejected =
has &&
iBar.high > iTrend &&
iBar.GetUp() < iTrend;
//
has =
has &&
(isBullish
? isTrendBullishRejected
: isTrendBearishRejected);
if (has)
{
break;
}
}
//
result = has;
}
//
// Filter Using Trend Inside ...
if (result &&
filters.forceHasTrendLineInside)
{
//
result =
result &&
conditions.trendBuffer[cIDX] > triggerBlock.ob.lower &&
conditions.trendBuffer[cIDX] < triggerBlock.ob.upper;
}
//
// Filter Using Trend Place ...
if (result &&
filters.forceHasTrendPlace)
{
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
double mult =
isBullish
? 1
: -1;
double edge = isBullish
? triggerBlock.ob.lower
: triggerBlock.ob.upper;
double factor = edge + (mult * (triggerBlock.ob.GetRange() / 4));
for (int i = toIDX; i < fromIDX; i++)
{
//
double iTrend = helper.GetTrend(i);
//
has =
isBullish
? factor >= iTrend
: factor <= iTrend;
if (has)
{
break;
}
}
//
result = has;
}
}
//
// Filter Using Delta ...
if (result &&
filters.filterBasedOnDelta)
{
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iDelta = helper.GetDelta(i);
double iPDelta = helper.GetDelta(i + 1);
//
double iDeltaSignal = helper.GetDeltaSignal(i);
double iPDeltaSignal = helper.GetDeltaSignal(i + 1);
//
bool isDeltaUp =
iDelta > iPDelta;
//
bool isDeltaDown =
iDelta < iPDelta;
//
bool isDeltaSignalUp =
iDeltaSignal > iPDeltaSignal;
//
bool isDeltaSignalDown =
iDeltaSignal < iPDeltaSignal;
//
bool isDeltaCrossedOverSignal =
iDelta > iDeltaSignal &&
iPDelta <= iPDeltaSignal;
//
bool isDeltaCrossedUnderSignal =
iDelta < iDeltaSignal &&
iPDelta >= iPDeltaSignal;
//
has =
isBullish
? (isDeltaUp &&
isDeltaSignalUp &&
isDeltaCrossedOverSignal)
: (isDeltaDown &&
isDeltaSignalDown &&
isDeltaCrossedUnderSignal);
if (has)
{
break;
}
}
//
result = has;
}
//
// Filter Using Volume ...
if (result &&
filters.filterBasedOnVolume)
{
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iBullVolume = helper.GetBullishVolume(i);
double iPBullVolume = helper.GetBullishVolume(i + 1);
//
double iBullVolumeSignal = helper.GetBullishVolumeSignal(i);
double iPBullVolumeSignal = helper.GetBullishVolumeSignal(i + 1);
//
double iBearVolume = helper.GetBearishVolume(i);
double iPBearVolume = helper.GetBearishVolume(i + 1);
//
double iBearVolumeSignal = helper.GetBearishVolumeSignal(i);
double iPBearVolumeSignal = helper.GetBearishVolumeSignal(i + 1);
//
bool isBullVolumeUp =
iBullVolume > iPBullVolume;
//
bool isBullVolumeSignalUp =
iBullVolumeSignal > iPBullVolumeSignal;
//
bool isBearVolumeUp =
iBearVolume > iPBearVolume;
//
bool isBearVolumeSignalUp =
iBearVolumeSignal > iPBearVolumeSignal;
//
bool isVolumeSwitchedToBullish =
iBullVolumeSignal > iBearVolumeSignal &&
iPBullVolumeSignal <= iPBearVolumeSignal;
//
bool isVolumeSwitchedToBearish =
iBearVolumeSignal > iBullVolumeSignal &&
iPBearVolumeSignal <= iPBullVolumeSignal;
//
has =
isBullish
? (isBullVolumeUp &&
isBullVolumeSignalUp &&
isVolumeSwitchedToBullish)
: (isBearVolumeUp &&
isBearVolumeSignalUp &&
isVolumeSwitchedToBearish);
if (has)
{
break;
}
}
//
result = has;
}
//
// Filter Using Signal Bar ...
if (result &&
filters.filterBasedOnSignalBar)
{
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
//
double iSOpen = helper.GetSBarOpen(toIDX);
double iPSOpen = helper.GetSBarOpen(toIDX + 1);
//
double iSClose = helper.GetSBarClose(toIDX);
double iPSClose = helper.GetSBarClose(toIDX + 1);
//
double iSPow = MathAbs(iSOpen - iSClose);
double iPSPow = MathAbs(iPSOpen - iPSClose);
//
result =
result &&
iSPow > iPSPow &&
(isBullish
? iSClose > iSOpen
: iSClose < iSOpen);
//
// Now Looking for Dir Change ...
if (result)
{
Print("Filter Passed ...");
//
for (int i = toIDX; i < fromIDX; i++)
{
//
iSOpen = helper.GetSBarOpen(toIDX);
iPSOpen = helper.GetSBarOpen(toIDX + 1);
//
iSClose = helper.GetSBarClose(toIDX);
iPSClose = helper.GetSBarClose(toIDX + 1);
//
bool isSBullish =
iSClose > iSOpen;
//
bool isPSBullish =
iPSClose > iPSOpen;
//
bool isSBearish =
iSClose < iSOpen;
//
bool isPSBearish =
iPSClose < iPSOpen;
//
bool isSSwitchedToBullish =
isSBullish &&
!isPSBullish;
//
bool isSSwitchedToBearish =
isSBearish &&
!isPSBearish;
//
has =
isBullish
? isSSwitchedToBullish
: isSSwitchedToBearish;
if (has)
{
break;
}
}
//
result = has;
}
}
//
// Filter Using Signal Bar ...
if (result &&
filters.filterBasedOnHKSignalBar)
{
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
//
double iSOpen = helper.GetHKSBarOpen(toIDX);
double iPSOpen = helper.GetHKSBarOpen(toIDX + 1);
//
double iSClose = helper.GetHKSBarClose(toIDX);
double iPSClose = helper.GetHKSBarClose(toIDX + 1);
//
double iSPow = MathAbs(iSOpen - iSClose);
double iPSPow = MathAbs(iPSOpen - iPSClose);
//
result =
result &&
iSPow > iPSPow &&
(isBullish
? iSClose > iSOpen
: iSClose < iSOpen);
//
// Now Looking for Dir Change ...
if (result)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
iSOpen = helper.GetHKSBarOpen(toIDX);
iPSOpen = helper.GetHKSBarOpen(toIDX + 1);
//
iSClose = helper.GetHKSBarClose(toIDX);
iPSClose = helper.GetHKSBarClose(toIDX + 1);
//
bool isSBullish =
iSClose > iSOpen;
//
bool isPSBullish =
iPSClose > iPSOpen;
//
bool isSBearish =
iSClose < iSOpen;
//
bool isPSBearish =
iPSClose < iPSOpen;
//
bool isSSwitchedToBullish =
isSBullish &&
!isPSBullish;
//
bool isSSwitchedToBearish =
isSBearish &&
!isPSBearish;
//
has =
isBullish
? isSSwitchedToBullish
: isSSwitchedToBearish;
if (has)
{
break;
}
}
//
result = has;
}
}
@@ -2370,28 +2943,31 @@ bool DrawTriggerBlock(
return result;
}
//
XTriggerBlock _trigger = trigger;
//
// Update To ...
bool canUpdateTo = IsValid(to);
if (canUpdateTo)
{
//
trigger.trigger.to = to;
trigger.rLiquidity.to = to;
trigger.fLiquidity.to = to;
_trigger.trigger.to = to;
_trigger.rLiquidity.to = to;
_trigger.fLiquidity.to = to;
}
//
bool isBullish = trigger.IsBullish();
bool isBullish = _trigger.IsBullish();
//
// Draw OB ...
if (trigger.ob.IsValid())
if (_trigger.ob.IsValid())
{
//
XCBoxObject *iOBObj;
result = drawer.DrawBox(
trigger.ob,
_trigger.ob,
iOBObj //
);
if (result)
@@ -2425,12 +3001,12 @@ bool DrawTriggerBlock(
//
// Draw FVG ...
if (trigger.fvg.IsValid())
if (_trigger.fvg.IsValid())
{
//
XCBoxObject *iFVGObj;
result = drawer.DrawBox(
trigger.fvg,
_trigger.fvg,
iFVGObj //
);
if (result)
@@ -2464,12 +3040,12 @@ bool DrawTriggerBlock(
//
// Draw Trigger ...
if (trigger.trigger.IsValid())
if (_trigger.trigger.IsValid())
{
//
XCBoxObject *iTriggerObj;
result = drawer.DrawBox(
trigger.trigger,
_trigger.trigger,
iTriggerObj //
);
if (result)
@@ -2506,12 +3082,12 @@ bool DrawTriggerBlock(
//
// Reversla Liquidity ...
if (trigger.rLiquidity.IsValid())
if (_trigger.rLiquidity.IsValid())
{
//
XCBoxObject *iLiqObj;
result = drawer.DrawBox(
trigger.rLiquidity,
_trigger.rLiquidity,
iLiqObj //
);
if (result)
@@ -2529,12 +3105,12 @@ bool DrawTriggerBlock(
//
// Following Liquidity ...
if (trigger.fLiquidity.IsValid())
if (_trigger.fLiquidity.IsValid())
{
//
XCBoxObject *iLiqObj;
result = drawer.DrawBox(
trigger.fLiquidity,
_trigger.fLiquidity,
iLiqObj //
);
if (result)
@@ -2552,22 +3128,22 @@ bool DrawTriggerBlock(
//
// Draw Swing Bar ...
if (trigger.swingBar.IsValid())
if (_trigger.swingBar.IsValid())
{
//
color swingColor =
trigger.fvg.IsBullish()
_trigger.fvg.IsBullish()
? clrAqua
: clrMagenta;
ENUM_X_PRICE swingPType =
trigger.fvg.IsBullish()
_trigger.fvg.IsBullish()
? X_PRICE_LOW
: X_PRICE_HIGH;
//
XCBarArrowObject *swingObj;
result = drawer.CreateBarArrow(
trigger.swingBar,
_trigger.swingBar,
swingObj,
swingPType,
159,
@@ -2589,7 +3165,7 @@ bool DrawTriggerBlock(
//
// Draw RR of Signal ...
if (_drawSignals &&
trigger.signal.IsValid() &&
_trigger.signal.IsValid() &&
rrZoneLength > 0)
{
//
@@ -2598,7 +3174,7 @@ bool DrawTriggerBlock(
result = iRRObj.Create(
drawer.ChartIdentification(),
drawer.SubWindowIdentification(),
trigger.signal,
_trigger.signal,
rrZoneLength //
);
if (result)