This commit is contained in:
2025-05-20 21:48:12 +03:30
parent 587d208823
commit 70876676f5
7 changed files with 5904 additions and 1417 deletions
+305 -452
View File
@@ -26,6 +26,44 @@
// //
// Definitions ... // Definitions ...
//
// Extensions ...
void FillLiquidity(
XOHCL &lBar,
ENUM_X_DIRECTION lDir,
XBoxZone &lq,
datetime to //
)
{
//
// Normalize Args ...
lq.Clean();
to = NormalizeTime(to);
//
// Validate Args ...
bool has = lBar.IsValid() &&
HasDirection(lDir);
if (!has)
{
return;
}
//
lq.to = to;
lq.dir = lDir;
lq.type = "XLQ";
lq.from = lBar.time;
lq.symbol = lBar.symbol;
lq.period = lBar.period;
lq.upper = IsBullish(lDir)
? lBar.GetDown()
: lBar.high;
lq.lower = IsBullish(lDir)
? lBar.low
: lBar.GetUp();
}
// //
// Implementations ... // Implementations ...
class XCBarAnalyser : public XCBase class XCBarAnalyser : public XCBase
@@ -2040,20 +2078,45 @@ class XCBarAnalyser : public XCBase
return result; return result;
} }
/**
* Check a Bar is a Trigger Box or Not ...
*
* @param bar: XOHCL instance Referernce, Specified Start Bar to Check ...
* @param trigger: XBoxZone instance Reference, Holds Detected Trigger Bar ...
* @param ob: XBoxZone instance Reference, Holds Detected Trigger Bar's OB ...
* @param fvg: XBoxZone instance Reference, Holds Detected Trigger Bar's FVG ...
* @param rLiquidity: XBoxZone instance Reference, Holds Detected Trigger Bar's Reversal Side Liquidity ...
* @param fLiquidity: XBoxZone instance Reference, Holds Detected Trigger Bar's Following Side Liquidity ...
* @param swingBar: XOHCL instance Referernce, Holds Detected Trigger Bar's Swing ...
* @param loopback: int, Loopback Bars Count ...
* @param maxAllowedRange: double, Max Allowed Trigger's OB Range ...
* @param minAllowedBlockEdgeLength: int, Min Allowed Block Edge Validation Length ...
* @param forceOBOppositBar: bool, Force OB to Start by Opposite Bar ...
* @param forceFVGBarType: bool, Force FVG to Has Same Bar Type ...
* @param forceGapBarBreakout: bool, Force Gap Bar Breakout OB Edge ...
* @param forceHasSwingBar: bool, Force Has Swing Bar ...
* @param forceHasLiquidity: bool, Force Has Following Liquidity ...
* @param forceHasReversalLiquidity: bool, Force Has Reversal Liquidity ...
*
* @return ( bool )
*/
bool IsTrigger( bool IsTrigger(
XOHCL &bar, XOHCL &bar,
XBoxZone &box, XBoxZone &trigger,
XBoxZone &ob, XBoxZone &ob,
XBoxZone &fvg, XBoxZone &fvg,
XBoxZone &liquidity, XBoxZone &rLiquidity,
XBoxZone &fLiquidity,
XOHCL &swingBar, XOHCL &swingBar,
int loopback = 10, int loopback = 10,
bool forceLiquidity = true, double maxAllowedRange = 0.0,
bool forceLiquidityUsed = true, int minAllowedBlockEdgeLength = 0,
bool forceEntryBar = true, bool forceOBOppositBar = true,
bool forceEntryBarPower = true, bool forceFVGBarType = true,
bool forceFVGBarType = false, bool forceGapBarBreakout = true,
bool forceOBTwoBar = false // bool forceHasSwingBar = true,
bool forceHasLiquidity = true,
bool forceHasReversalLiquidity = true //
) )
{ {
// //
@@ -2063,9 +2126,10 @@ class XCBarAnalyser : public XCBase
// Normalize Args ... // Normalize Args ...
ob.Clean(); ob.Clean();
fvg.Clean(); fvg.Clean();
box.Clean(); trigger.Clean();
swingBar.Clean(); swingBar.Clean();
liquidity.Clean(); rLiquidity.Clean();
fLiquidity.Clean();
loopback = NormalizeInt(loopback, 5); loopback = NormalizeInt(loopback, 5);
// //
@@ -2077,263 +2141,171 @@ class XCBarAnalyser : public XCBase
} }
// //
XOHCL pBar; // Previous of Provided Bar ... XOHCL pBar;
XOHCL iBar; XOHCL tmpBar;
XOHCL iPBar; XOHCL tmpPBar;
int barIndex; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
int pBarIndex;
ENUM_X_DIRECTION iDir;
// //
result = bar.GetPreviousBar(pBar); result = bar.GetPreviousBar(pBar);
if (!result)
{
//
ob.Clean();
fvg.Clean();
box.Clean();
pBar.Clean();
iBar.Clean();
iPBar.Clean();
swingBar.Clean();
liquidity.Clean();
// //
return result; // Detect Base Order Block ...
} result =
result &&
// //
barIndex = bar.Index(); // Order Block Detection ...
pBarIndex = pBar.Index(); IsOB(
pBar,
//
// 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, ob,
forceFVGBarType, forceFVGBarType,
forceOBTwoBar // forceOBOppositBar //
); ) &&
if (result)
{
// //
// Validate Block Last Bars ... // Gap Detection ...
XOHCL fromBar; IsFVG(
XOHCL fromBarPrev; pBar,
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, fvg,
forceFVGBarType // forceFVGBarType //
); );
if (result) if (result)
{ {
// //
box.Clone(ob); trigger = ob;
box.type = "XTRG"; trigger.type = "XTRG";
box.from = fromBarPrev.time;
break;
}
} }
// //
fromBar.Clean(); // Reading Requirements ...
fromBarPrev.Clean();
}
// //
iBar.Clean(); double points = GetPoints(bar.symbol);
}
iBar.Clean();
// //
// Validate Block Detected ... bool isBullish = ob.IsBullish();
result = box.IsValid(); bool isBearish = ob.IsBearish();
if (!result)
//
int toIDX = trigger.ToIndex();
int fromIDX = trigger.FromIndex();
//
// Validate Gaps Bar Breakeout ...
if (result &&
forceGapBarBreakout)
{ {
// //
ob.Clean(); // Extract Gap Bar ...
fvg.Clean(); tmpBar.Clean();
box.Clean(); tmpPBar.Clean();
pBar.Clean(); result =
iBar.Clean(); //
iPBar.Clean(); // Retrieve Bars ...
swingBar.Clean(); fvg.ToBar(tmpBar) &&
liquidity.Clean(); tmpBar.GetPreviousBar(tmpPBar) &&
//
// Validate Gap Bar is Momentum Bar ...
IsMomentum(
tmpPBar,
iDir,
1 //
) &&
iDir == fvg.dir &&
//
// Validate ...
(isBullish
? tmpPBar.close > ob.upper
: tmpPBar.close < ob.lower);
// //
return result; tmpBar.Clean();
tmpPBar.Clean();
} }
// //
int toIDX = box.ToIndex(); // Validate Range ...
int fromIDX = box.FromIndex(); if (result &&
bool isBullish = box.IsBullish(); maxAllowedRange > 0)
bool isBearish = box.IsBearish(); {
//
double range = ob.GetRange();
result = range <= (maxAllowedRange * points);
}
// //
// Detect Swing Bar ... // Validating Swing Bar ...
int swingBarIDX = -1; if (result &&
int swingLoopback = fromIDX - pBarIndex; forceHasSwingBar)
{
//
int swingIDX = -1;
result = ob.FromBar(tmpBar);
if (result)
{
//
// Detect Swing Bar Index ...
if (isBullish) if (isBullish)
{ {
// swingIDX = tmpBar.FindLowestIndex(loopback, MODE_LOW);
// Looking for Swing Low ...
swingBarIDX = pBar.FindLowestIndex(swingLoopback, MODE_LOW);
} }
else if (isBearish) else if (isBearish)
{ {
// swingIDX = tmpBar.FindHighestIndex(loopback, MODE_HIGH);
// Looking for Swing High ...
swingBarIDX = pBar.FindHighestIndex(swingLoopback, MODE_LOW);
} }
result = IsValidIndex(swingBarIDX); result = IsValidIndex(swingIDX);
if (!result) if (result)
{ {
//
ob.Clean();
fvg.Clean();
box.Clean();
pBar.Clean();
iBar.Clean();
iPBar.Clean();
swingBar.Clean();
liquidity.Clean();
//
return result;
}
// //
// Initialize Swing Bar ... // Initialize Swing Bar ...
result = swingBar.Init( result = swingBar.Init(
bar.symbol, bar.symbol,
bar.period, bar.period,
swingBarIDX // swingIDX //
); );
if (!result)
{
//
ob.Clean();
fvg.Clean();
box.Clean();
pBar.Clean();
iBar.Clean();
iPBar.Clean();
swingBar.Clean();
liquidity.Clean();
//
return result;
} }
// //
// Update Trigger Box ... // Update Trigger Block based on Swing Bar ...
result = swingBar.IsValid();
if (result)
{
//
// Update From ...
trigger.from = ((datetime)MathMin((int)trigger.from, (int)swingBar.time));
//
// Update Edge ...
if (isBullish) if (isBullish)
{ {
box.lower = MathMin(box.lower, swingBar.GetDown()); trigger.lower = MathMin(trigger.lower, swingBar.GetDown());
} }
else if (isBearish) else if (isBearish)
{ {
box.upper = MathMin(box.upper, swingBar.GetUp()); trigger.upper = MathMax(trigger.upper, swingBar.GetUp());
}
}
} }
// //
// Now we Have to Check Spike from Swing Bar Next till Current Bar ... tmpBar.Clean();
// To Validate Highs and Lows ... }
for (int i = pBarIndex; i < pBarIndex + (swingBarIDX - pBarIndex) - 1; i++)
//
// Validate Min Block Edge ...
if (result &&
minAllowedBlockEdgeLength > 0)
{
//
fromIDX = trigger.FromIndex();
if (result)
{
//
// Looping Back ...
for (int i = fromIDX; i < fromIDX + minAllowedBlockEdgeLength; i++)
{ {
// //
// Initialize i Bar ... // Initialize i Bar ...
result = iBar.Init( result = tmpBar.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 = iBar.low > iPBar.low;
}
else if (isBearish)
{
result = iBar.high < iPBar.high;
}
if (!result)
{
break;
}
//
iBar.Clean();
iPBar.Clean();
}
iBar.Clean();
iPBar.Clean();
if (!result)
{
//
ob.Clean();
fvg.Clean();
box.Clean();
pBar.Clean();
iBar.Clean();
iPBar.Clean();
swingBar.Clean();
liquidity.Clean();
//
return result;
}
//
// 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.symbol,
bar.period, bar.period,
i // i //
@@ -2341,241 +2313,62 @@ class XCBarAnalyser : public XCBase
result = result =
result && result &&
(isBullish (isBullish
? iBar.close > box.upper ? tmpBar.low > trigger.lower
: iBar.close < box.lower); : tmpBar.high > trigger.upper);
//
if (!result) if (!result)
{ {
break; break;
} }
// //
iBar.Clean(); tmpBar.Clean();
} }
iBar.Clean(); result = tmpBar.IsValid();
if (!result)
{
//
ob.Clean();
fvg.Clean();
box.Clean();
pBar.Clean();
iBar.Clean();
iPBar.Clean();
swingBar.Clean();
liquidity.Clean();
// //
return result; // Update Trigger Block ...
if (result)
{
trigger.from = ((datetime)(MathMin((int)trigger.from, (int)tmpBar.time)));
}
} }
// //
// Now we Have to Detect Spike Breake Ruls ... tmpBar.Clean();
// for Bullish: bar.low goes Below of pBar.low ...
// for Bearish: bar.high goes Above of pBar.high ...
if (isBullish)
{
result = bar.low < pBar.low;
}
else if (isBearish)
{
result = bar.high > pBar.high;
}
if (!result)
{
//
ob.Clean();
fvg.Clean();
box.Clean();
pBar.Clean();
iBar.Clean();
iPBar.Clean();
swingBar.Clean();
liquidity.Clean();
//
return result;
} }
// //
// Update Box ... // Validating Liquidity ...
if (isBullish) if (result &&
{ (forceHasLiquidity ||
box.upper = MathMax(box.upper, bar.GetDown()); forceHasReversalLiquidity))
}
else if (isBearish)
{
box.lower = MathMin(box.lower, bar.GetUp());
}
box.to = bar.time;
//
toIDX = box.ToIndex();
fromIDX = box.FromIndex();
//
// Liquidity ...
if (forceLiquidity)
{ {
// //
// Now we Have to Detect Liquidity Zone ... // Try to Detect Liquidity ...
for (int i = fromIDX; i < fromIDX + loopback; i++) toIDX = ob.ToIndex();
for (int i = toIDX; i < toIDX + (loopback * 10); i++)
{ {
// //
// Initialize iBar // Initialize i Bar ...
result = iBar.Init( result = tmpBar.Init(
bar.symbol, bar.symbol,
bar.period, bar.period,
i // i //
); );
result = if (!result)
{
break;
}
//
// Detect Liquidity ...
bool isRejected =
result && result &&
IsRejected( IsRejected(
iBar, tmpBar,
iDir, iDir,
false, // Force Bar Type ... false, // Force Bar Type ...
true // Force Fibo Pressure ... true // Force Fibo Pressure ...
) &&
iDir == box.dir &&
(isBullish
? iBar.low < box.lower
: iBar.high > box.upper);
if (result)
{
//
// Filling Liquidity ...
liquidity.dir = iDir;
liquidity.to = box.to;
liquidity.type = "XLQ";
liquidity.from = iBar.time;
liquidity.symbol = iBar.symbol;
liquidity.period = iBar.period;
liquidity.upper = isBullish
? iBar.GetDown()
: iBar.high;
liquidity.lower = isBullish
? iBar.low
: iBar.GetUp();
//
result = liquidity.IsValid();
if (result)
{
break;
}
}
//
iBar.Clean();
}
iBar.Clean();
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;
}
}
}
//
// 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 = bool isBullishRejected =
isRejected && isRejected &&
@@ -2585,52 +2378,108 @@ class XCBarAnalyser : public XCBase
IsBearish(iDir); IsBearish(iDir);
// //
bool isBullishPowered = // Validate Liquidities ...
isBullishMomentum || if (isBullish)
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(); if (isBullishRejected &&
fvg.Clean(); forceHasLiquidity &&
box.Clean(); !fLiquidity.IsValid() &&
pBar.Clean(); tmpBar.low < trigger.lower)
iBar.Clean(); {
iPBar.Clean(); //
swingBar.Clean(); // Filling Following Liquidity ...
liquidity.Clean(); FillLiquidity(
tmpBar,
trigger.dir,
fLiquidity,
trigger.to //
);
}
// //
return result; if (isBearishRejected &&
!rLiquidity.IsValid() &&
forceHasReversalLiquidity &&
tmpBar.high > trigger.upper)
{
//
// Filling Revrsal Liquidity ...
FillLiquidity(
tmpBar,
Opposit(trigger.dir),
rLiquidity,
trigger.to //
);
} }
} }
else if (isBearish)
{
//
if (isBearishRejected &&
forceHasLiquidity &&
!fLiquidity.IsValid() &&
tmpBar.high > trigger.upper)
{
//
// Filling Following Liquidity ...
FillLiquidity(
tmpBar,
trigger.dir,
fLiquidity,
trigger.to //
);
}
//
if (isBullishRejected &&
!rLiquidity.IsValid() &&
forceHasReversalLiquidity &&
tmpBar.low < trigger.lower)
{
//
// Filling Reversal Liquidity ...
FillLiquidity(
tmpBar,
Opposit(trigger.dir),
rLiquidity,
trigger.to //
);
}
}
//
if ((!forceHasLiquidity
? true
: fLiquidity.IsValid()) &&
(!forceHasReversalLiquidity
? true
: rLiquidity.IsValid()))
{
break;
}
//
tmpBar.Clean();
}
tmpBar.Clean();
//
result = (!forceHasLiquidity
? true
: fLiquidity.IsValid()) &&
(!forceHasReversalLiquidity
? true
: rLiquidity.IsValid());
}
// //
// Cleanup Resources ... // Cleanup Resources ...
// //
iBar.Clean();
pBar.Clean(); pBar.Clean();
iPBar.Clean(); tmpBar.Clean();
swingBar.Clean(); tmpPBar.Clean();
// //
if (!result) if (!result)
@@ -2638,9 +2487,13 @@ class XCBarAnalyser : public XCBase
// //
ob.Clean(); ob.Clean();
fvg.Clean(); fvg.Clean();
box.Clean(); trigger.Clean();
swingBar.Clean(); swingBar.Clean();
liquidity.Clean(); rLiquidity.Clean();
fLiquidity.Clean();
//
return result;
} }
// //
+17 -1
View File
@@ -426,7 +426,8 @@ class XCBarArrowObject : public XCBaseObject
int window, int window,
int arrow, int arrow,
XOHCL &bar, XOHCL &bar,
ENUM_X_PRICE priceType // ENUM_X_PRICE priceType,
double threshold = 5 //
) )
{ {
// //
@@ -448,6 +449,21 @@ class XCBarArrowObject : public XCBaseObject
datetime time = bar.time; datetime time = bar.time;
double price = bar.GetPrice(priceType); double price = bar.GetPrice(priceType);
//
if (threshold > 0)
{
//
double thresholdPrice = threshold * GetPoints(bar.symbol);
if (priceType == X_PRICE_HIGH)
{
price += thresholdPrice;
}
else if (priceType == X_PRICE_LOW)
{
price -= thresholdPrice;
}
}
// //
result = mArrow.Create( result = mArrow.Create(
chart_id, chart_id,
+26
View File
@@ -28,6 +28,32 @@
// //
// Definitions ... // Definitions ...
//
// Extensions ...
void AddObjects(
CArrayObj *&source,
CArrayObj &dest //
)
{
//
bool has = source != NULL &&
source.Total() > 0;
if (!has)
{
return;
}
//
for (int i = 0; i < source.Total(); i++)
{
dest.Add(source.At(i));
}
}
//
// Implementations ...
class XCPOIDrawer : public XCBase class XCPOIDrawer : public XCBase
{ {
// //
+780
View File
@@ -0,0 +1,780 @@
// //
// // 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;
}
File diff suppressed because it is too large Load Diff
+55 -114
View File
@@ -13,6 +13,7 @@
// Include Common Library ... // Include Common Library ...
#include "../Libraries/x-saherelm.common.lib.mq5" #include "../Libraries/x-saherelm.common.lib.mq5"
#include "../XCAEA/Helpers/xcaea.helper.mq5" #include "../XCAEA/Helpers/xcaea.helper.mq5"
#include "../XCAEA/Libraries/xcaea.trigger.block.lib.mq5"
// //
// Variables ... // Variables ...
@@ -20,6 +21,7 @@ XCAEAInputs eaInputs;
XCXCAEAHelper *eaHelper; XCXCAEAHelper *eaHelper;
XBarTracker eaBarTraker; XBarTracker eaBarTraker;
//
CArrayObj eaObjects; CArrayObj eaObjects;
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
@@ -44,6 +46,7 @@ int OnInit()
// //
// we Can make Show all requirements here ... // we Can make Show all requirements here ...
eaInputs.caInputs.showSar = true;
// //
eaHelper = new XCXCAEAHelper(); eaHelper = new XCXCAEAHelper();
@@ -67,14 +70,14 @@ int OnInit()
void OnDeinit(const int reason) void OnDeinit(const int reason)
{ {
// //
eaObjects.Clear(); // eaObjects.Clear();
// //
eaBarTraker.Clean(); eaBarTraker.Clean();
// //
// delete eaHelper; delete eaHelper;
// ZeroMemory(eaHelper); ZeroMemory(eaHelper);
} }
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
@@ -120,126 +123,67 @@ void OnTick()
} }
// //
// Here Do What we Want ... // Define Trigger Block ...
XOHCL swingBar; XTriggerBlock tb;
XBoxZone ob; XCAEATriggerBlockConfiguration tbConfig;
XBoxZone fvg;
XBoxZone trigger; //
XBoxZone liquidity; // Configure Detector ...
has = eaHelper
.barAnalyser //
.IsTrigger( // Validation ...
cBar, tbConfig.maxAllowedRange = 0.0;
trigger, tbConfig.minAllowedBlockEdgeLength = 7;
ob,
fvg, //
liquidity, // Validation ...
swingBar, tbConfig.forceFVGBarType = true;
tbConfig.forceHasSwingBar = true;
tbConfig.forceOBOppositBar = true;
tbConfig.forceHasLiquidity = false;
tbConfig.forceGapBarBreakout = true;
tbConfig.forceHasReversalLiquidity = true;
//
// Filters ...
tbConfig.filterBasedOnSar = true;
tbConfig.filterBasedOnADX = true;
tbConfig.filterBasedOnRSI = true;
tbConfig.filterBasedOnTrend = true;
tbConfig.filterBasedOnScores = true;
tbConfig.filterBasedOnVolumes = true;
//
// Do Detection ...
has = DetectTriggerBlock(
tb,
eaHelper,
tbConfig,
zBar.Index(),
10 // 10 //
); );
if (has) if (has)
{ {
// //
bool isBullish = trigger.IsBullish(); CArrayObj *tObjects;
tObjects = new CArrayObj();
// //
// ob.to = zBar.time; has = DrawTriggerBlock(
// fvg.to = zBar.time; tb,
trigger.to = zBar.time; tObjects,
liquidity.to = zBar.time; eaHelper,
zBar.time //
//
// Draw OB ...
XCBoxObject *iOBObj;
has = eaHelper.poiDrawer.DrawBox(
ob,
iOBObj //
); );
if (has) if (has)
{ {
eaObjects.Add(iOBObj); AddObjects(tObjects, eaObjects);
}
ZeroMemory(iOBObj);
//
// Draw FVG ...
XCBoxObject *iFVGObj;
has = eaHelper.poiDrawer.DrawBox(
fvg,
iFVGObj //
);
if (has)
{
//
// Style Object ...
color clr =
isBullish
? clrAqua
: clrMagenta;
iFVGObj.BoxWidth(2);
iFVGObj.BoxColor(clr);
iFVGObj.BoxStyle(STYLE_SOLID);
//
// Store Object ...
eaObjects.Add(iFVGObj);
}
ZeroMemory(iFVGObj);
//
// Draw Trigger ...
XCBoxObject *iTriggerObj;
has = eaHelper.poiDrawer.DrawBox(
trigger,
iTriggerObj //
);
if (has)
{
eaObjects.Add(iTriggerObj);
}
ZeroMemory(iTriggerObj);
//
// Draw Liquidity ...
XCBoxObject *iLiqObj;
has = eaHelper.poiDrawer.DrawBox(
liquidity,
iLiqObj //
);
if (has)
{
eaObjects.Add(iLiqObj);
}
ZeroMemory(iLiqObj);
//
// Draw Swing Bar ...
color swingColor =
isBullish
? clrAqua
: clrMagenta;
ENUM_X_PRICE swingPType =
isBullish
? X_PRICE_LOW
: X_PRICE_HIGH;
//
XCBarArrowObject *swingObj;
has = eaHelper.poiDrawer.CreateBarArrow(
swingBar,
swingObj,
swingPType,
159,
swingColor //
);
if (has)
{
eaObjects.Add(swingObj);
} }
// //
Print("Trigger Box Detected ..."); Print("Trigger Block Detected ...");
} }
tb.Clean();
// //
// Do What we Want ... // Do What we Want ...
@@ -250,11 +194,8 @@ void OnTick()
// Cleanup Resources ... // Cleanup Resources ...
// //
ob.Clean(); tb.Clean();
fvg.Clean();
zBar.Clean(); zBar.Clean();
cBar.Clean(); cBar.Clean();
trigger.Clean(); tbConfig.Clean();
swingBar.Clean();
liquidity.Clean();
} }
File diff suppressed because it is too large Load Diff