781 lines
17 KiB
Plaintext
781 lines
17 KiB
Plaintext
// //
|
|
// // Now we Have to Detect Spike Breake Ruls ...
|
|
// // for Bullish: bar.low goes Below of pBar.low ...
|
|
// // for Bearish: bar.high goes Above of pBar.high ...
|
|
// for (int i = toIDX; i > pBarIndex; i--)
|
|
// {
|
|
// //
|
|
// // Initialize iBar ...
|
|
// result = iBar.Init(
|
|
// bar.symbol,
|
|
// bar.period,
|
|
// i //
|
|
// );
|
|
// result =
|
|
// result &&
|
|
// iBar.GetPreviousBar(iPBar);
|
|
// if (result)
|
|
// {
|
|
// //
|
|
// if (isBullish)
|
|
// {
|
|
// result = iBar.low < iPBar.low;
|
|
// }
|
|
// else if (isBearish)
|
|
// {
|
|
// result = iBar.high > iPBar.high;
|
|
// }
|
|
|
|
// //
|
|
// if (result)
|
|
// {
|
|
// break;
|
|
// }
|
|
// }
|
|
|
|
// //
|
|
// iBar.Clean();
|
|
// iPBar.Clean();
|
|
// }
|
|
// if (!result)
|
|
// {
|
|
// //
|
|
// ob.Clean();
|
|
// fvg.Clean();
|
|
// box.Clean();
|
|
// pBar.Clean();
|
|
// iBar.Clean();
|
|
// iPBar.Clean();
|
|
// swingBar.Clean();
|
|
// liquidity.Clean();
|
|
|
|
// //
|
|
// return result;
|
|
// }
|
|
|
|
// //
|
|
// // Update Box ...
|
|
// if (isBullish)
|
|
// {
|
|
// box.upper = MathMax(box.upper, iBar.GetDown());
|
|
// }
|
|
// else if (isBearish)
|
|
// {
|
|
// box.lower = MathMin(box.lower, iBar.GetUp());
|
|
// }
|
|
|
|
bool IsTrigger(
|
|
XOHCL &bar,
|
|
XBoxZone &box,
|
|
XBoxZone &ob,
|
|
XBoxZone &fvg,
|
|
XBoxZone &liquidity,
|
|
XOHCL &swingBar,
|
|
int loopback = 10,
|
|
int hlDistance = 300,
|
|
double maxAlowedRange = 0.0,
|
|
bool forceOBOppositBar = true,
|
|
bool forceFVGBarType = true,
|
|
bool forceSwingBar = true,
|
|
bool forceGapBarBreakout = true,
|
|
bool forceCheckBarsSequence = true,
|
|
bool lookingEntry = false,
|
|
bool forceLiquidity = true,
|
|
bool forceLiquidityUsed = true,
|
|
bool forceEntryBar = true,
|
|
bool forceEntryBarPower = true
|
|
//
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize Args ...
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
loopback = NormalizeInt(loopback, 5);
|
|
|
|
//
|
|
// Validate Args ...
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
XOHCL iBar;
|
|
XOHCL iPBar;
|
|
int barIndex;
|
|
int pBarIndex;
|
|
ENUM_X_DIRECTION iDir;
|
|
|
|
//
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
barIndex = bar.Index();
|
|
pBarIndex = pBar.Index();
|
|
|
|
//
|
|
// Loopback to Find a Block ...
|
|
for (int i = pBarIndex; i < pBarIndex + loopback; i++)
|
|
{
|
|
//
|
|
// Inital IBar ...
|
|
result = iBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
i //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Detect Block ...
|
|
result = IsOB(
|
|
iBar,
|
|
ob,
|
|
forceFVGBarType,
|
|
forceOBOppositBar //
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
// Validate Block Last Bars ...
|
|
if (forceOBOppositBar)
|
|
{
|
|
//
|
|
XOHCL fromBar;
|
|
XOHCL fromBarPrev;
|
|
result = ob.FromBar(fromBar);
|
|
result =
|
|
result &&
|
|
fromBar.GetPreviousBar(fromBarPrev);
|
|
result =
|
|
result &&
|
|
(ob.IsBullish()
|
|
? fromBarPrev.IsBearish()
|
|
: fromBarPrev.IsBullish());
|
|
if (result)
|
|
{
|
|
//
|
|
// Detect FVG ...
|
|
result = IsFVG(
|
|
iBar,
|
|
fvg,
|
|
forceFVGBarType //
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
box.Clone(ob);
|
|
box.type = "XTRG";
|
|
box.from = fromBarPrev.time;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
fromBar.Clean();
|
|
fromBarPrev.Clean();
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
iBar.Clean();
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Filter Using Max Allowed Range ...
|
|
if (maxAlowedRange > 0)
|
|
{
|
|
//
|
|
result = box.GetRange() <= (maxAlowedRange * GetPoints(bar.symbol));
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate Gap Bar ...
|
|
if (forceGapBarBreakout)
|
|
{
|
|
//
|
|
// We Have to Check Gap Bar's Breakout ...
|
|
result = fvg.ToBar(iBar);
|
|
result =
|
|
result &&
|
|
iBar.GetPreviousBar(iPBar);
|
|
result =
|
|
result &&
|
|
(box.IsBullish()
|
|
? iPBar.close > ob.upper
|
|
: iPBar.close < ob.lower);
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Validate HH LL Distance ...
|
|
if (hlDistance > 0)
|
|
{
|
|
//
|
|
result = ob.FromBar(iBar);
|
|
if (result)
|
|
{
|
|
//
|
|
double ll = iBar.FindLowest(iBar.Index() + hlDistance, MODE_LOW);
|
|
double hh = iBar.FindHighest(iBar.Index() + hlDistance, MODE_HIGH);
|
|
|
|
//
|
|
result =
|
|
ll > 0 &&
|
|
hh > 0 &&
|
|
ob.upper < hh &&
|
|
ob.lower > ll;
|
|
}
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
int toIDX = box.ToIndex();
|
|
int fromIDX = box.FromIndex();
|
|
bool isBullish = box.IsBullish();
|
|
bool isBearish = box.IsBearish();
|
|
|
|
//
|
|
// We Have to Make sure Bars until Spikes Closed ...
|
|
// for Bullish: bars must Close Above box.upper ...
|
|
// for Bearish: bars must Close Below box.lower ...
|
|
for (int i = pBarIndex; i < toIDX; i++)
|
|
{
|
|
//
|
|
// Initialize iBar ...
|
|
result = iBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
i //
|
|
);
|
|
result =
|
|
result &&
|
|
(isBullish
|
|
? iBar.close > box.upper
|
|
: iBar.close < box.lower);
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
iBar.Clean();
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detect Swing Bar ...
|
|
int swingBarIDX = -1;
|
|
int swingLoopback = fromIDX - pBarIndex;
|
|
if (isBullish)
|
|
{
|
|
//
|
|
// Looking for Swing Low ...
|
|
swingBarIDX = pBar.FindLowestIndex(swingLoopback, MODE_LOW);
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
//
|
|
// Looking for Swing High ...
|
|
swingBarIDX = pBar.FindHighestIndex(swingLoopback, MODE_LOW);
|
|
}
|
|
result = IsValidIndex(swingBarIDX);
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Initialize Swing Bar ...
|
|
result = swingBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
swingBarIDX //
|
|
);
|
|
if (forceSwingBar)
|
|
{
|
|
//
|
|
result =
|
|
result &&
|
|
IsSimpleSwing(
|
|
swingBar,
|
|
iDir //
|
|
) &&
|
|
iDir == fvg.dir;
|
|
}
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Update Trigger Box ...
|
|
if (isBullish)
|
|
{
|
|
box.lower = MathMin(box.lower, swingBar.GetDown());
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
box.upper = MathMin(box.upper, swingBar.GetUp());
|
|
}
|
|
|
|
//
|
|
// Validating Bar Sequence ...
|
|
if (forceCheckBarsSequence)
|
|
{
|
|
//
|
|
// Now we Have to Check Spike from Swing Bar Next till Current Bar ...
|
|
// To Validate Highs and Lows ...
|
|
for (int i = pBarIndex; i < pBarIndex + (swingBarIDX - pBarIndex) - 1; i++)
|
|
{
|
|
//
|
|
// Initialize iBar ...
|
|
result = iBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
i //
|
|
);
|
|
result =
|
|
result &&
|
|
iBar.GetPreviousBar(iPBar);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Since we Go Backward Bars from Current Bar ...
|
|
// for Bullish: each Bar Low Must over Prev Bar Low ...
|
|
// for Bearish: each Bar High Must Under Prev Bar High ...
|
|
if (isBullish)
|
|
{
|
|
//
|
|
result =
|
|
result &&
|
|
iBar.low > iPBar.low;
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
//
|
|
result =
|
|
result &&
|
|
iBar.high < iPBar.high;
|
|
}
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
}
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = pBar.time;
|
|
|
|
//
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
}
|
|
|
|
//
|
|
toIDX = box.ToIndex();
|
|
fromIDX = box.FromIndex();
|
|
|
|
//
|
|
// Liquidity ...
|
|
if (forceLiquidity)
|
|
{
|
|
//
|
|
// Checking Swing Bar is Liquidity ...
|
|
result = IsRejected(
|
|
swingBar,
|
|
iDir,
|
|
true, // Force Bar Type ...
|
|
true // Foce Fibo Pressure ...
|
|
) &&
|
|
iDir == fvg.dir;
|
|
if (result)
|
|
{
|
|
//
|
|
// Filling Liquidity ...
|
|
liquidity.dir = iDir;
|
|
liquidity.to = box.to;
|
|
liquidity.type = "XLQ";
|
|
liquidity.from = swingBar.time;
|
|
liquidity.symbol = swingBar.symbol;
|
|
liquidity.period = swingBar.period;
|
|
liquidity.upper = isBullish
|
|
? swingBar.GetDown()
|
|
: swingBar.high;
|
|
liquidity.lower = isBullish
|
|
? swingBar.low
|
|
: swingBar.GetUp();
|
|
|
|
//
|
|
result = liquidity.IsValid();
|
|
}
|
|
result = liquidity.IsValid();
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Liquidity Usage ...
|
|
if (forceLiquidityUsed)
|
|
{
|
|
//
|
|
// now We have to Ensure Detected Liqudity is Used ...
|
|
toIDX = box.ToIndex();
|
|
fromIDX = liquidity.FromIndex();
|
|
for (int i = fromIDX - 1; i >= toIDX; i--)
|
|
{
|
|
//
|
|
// Initialize iBar ...
|
|
result = iBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
i //
|
|
);
|
|
result =
|
|
result &&
|
|
(isBullish
|
|
? iBar.low < liquidity.upper
|
|
: iBar.high > liquidity.lower);
|
|
if (result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Looking for Entry ...
|
|
if (lookingEntry)
|
|
{
|
|
//
|
|
// Entry Bar ...
|
|
if (forceEntryBar)
|
|
{
|
|
//
|
|
// Validate Bar is Not Opposit Powered Bar ...
|
|
|
|
//
|
|
// Momentum ...
|
|
bool isMomentum = IsMomentum(
|
|
bar,
|
|
iDir,
|
|
1 //
|
|
);
|
|
bool isBullishMomentum =
|
|
isMomentum &&
|
|
IsBullish(iDir);
|
|
bool isBearishMomentum =
|
|
isMomentum &&
|
|
IsBearish(iDir);
|
|
|
|
//
|
|
// Engulfed ...
|
|
bool isEngulfed = IsEngulfed(
|
|
bar,
|
|
iDir //
|
|
);
|
|
bool isBullishEngulfed =
|
|
isEngulfed &&
|
|
IsBullish(iDir);
|
|
bool isBearishEngulfed =
|
|
isEngulfed &&
|
|
IsBearish(iDir);
|
|
|
|
//
|
|
// Rejected ...
|
|
bool isRejected = IsRejected(
|
|
bar,
|
|
iDir,
|
|
false,
|
|
true //
|
|
);
|
|
bool isBullishRejected =
|
|
isRejected &&
|
|
IsBullish(iDir);
|
|
bool isBearishRejected =
|
|
isRejected &&
|
|
IsBearish(iDir);
|
|
|
|
//
|
|
bool isBullishPowered =
|
|
isBullishMomentum ||
|
|
isBullishEngulfed ||
|
|
isBullishRejected;
|
|
|
|
//
|
|
bool isBearishPowered =
|
|
isBearishMomentum ||
|
|
isBearishEngulfed ||
|
|
isBearishRejected;
|
|
|
|
//
|
|
// Make Sure Entry Bar is a Valid Bar ...
|
|
result =
|
|
isBullish
|
|
? !isBearishPowered && (!forceEntryBarPower
|
|
? true
|
|
: isBullishPowered)
|
|
: !isBullishPowered && (!forceEntryBarPower
|
|
? true
|
|
: isBearishPowered);
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Entry Bar Sequences ...
|
|
if (forceCheckBarsSequence)
|
|
{
|
|
//
|
|
// if Sequences is Important ...
|
|
// we have to detect sequence Breaker Bar ...
|
|
result =
|
|
result &&
|
|
(isBullish
|
|
? bar.low < pBar.low
|
|
: bar.high > pBar.high);
|
|
}
|
|
|
|
//
|
|
// Validate Bar Close ...
|
|
result =
|
|
result &&
|
|
(isBullish
|
|
? bar.close > box.lower
|
|
: bar.close < box.upper);
|
|
}
|
|
|
|
//
|
|
if (!lookingEntry)
|
|
{
|
|
result = fvg.to == pBar.time;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
iBar.Clean();
|
|
pBar.Clean();
|
|
iPBar.Clean();
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
swingBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|