Files
MQL5Data/Classes/x-saherelm.x-bar.analyser.class.mq5
T
2025-10-19 01:00:24 +03:30

3454 lines
78 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class Library
// --------------------------------------
// Name: XPOI
// Description: Bar Analysing ...
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://www.saherelm.ir"
#property version "1.00"
#property strict
//
// Imports ...
#include "../Classes/x-saherelm.base.class.mq5"
#include "../Libraries/x-saherelm.x-poi.lib.mq5"
//
// 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 ...
class XCBarAnalyser : public XCBase
{
//
public:
//
//
// Constructor(s) ...
void XCBarAnalyser()
{
}
//
// Deconstructor ...
void ~XCBarAnalyser()
{
}
//
// Getter(s) / Setter(s) ...
//
// Providers ...
/**
* Calculate Loopback Data for Specific Bar ...
*
* @param index: Integer, Bar Current Index ...
* @param start: Integer, Start of Loopback ...
* @param end: Integer, End of Loopback ...
* @param count: Integer, Number of Calculating Bars ...
* @param bar: XOHCL instance, Specified Bar ...
* @param loopback: Integer, Loopback Length ...
* @return ( bool )
*/
bool CalculateLoopbackData(
int &index,
int &start,
int &end,
int &count,
XOHCL &bar,
int loopback = 1 //
)
{
//
bool result = false;
//
if (loopback < 1)
{
loopback = 1;
}
//
index = -1;
start = -1;
end = -1;
count = -1;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
index = bar.Index();
start = index + 1;
end = start + loopback;
count = end - start;
result = count >= 1;
if (!result)
{
return result;
}
//
return result;
}
/**
* Retrieve Loopback HH & LL Data ...
*
* @param hhIDX: Integer, HH Index ...
* @param hh: Double, HH Value ...
* @param llIDX: Integer, LL Index ...
* @param ll: Double, LL Value ...
* @param bar: XOHCL instance ...
* @param loopback: Integer, Loopback Length ...
*
* @return ( bool )
*/
bool CalculateLoopbackHLData(
int &hhIDX,
double &hh,
int &llIDX,
double &ll,
XOHCL &bar,
int loopback //
)
{
//
bool result = false;
//
if (loopback < 1)
{
loopback = 1;
}
//
int index = -1;
int start = -1;
int end = -1;
int count = -1;
result = CalculateLoopbackData(
index,
start,
end,
count,
bar,
loopback //
);
if (!result)
{
return result;
}
//
hhIDX = iHighest(
bar.symbol,
bar.period,
MODE_HIGH,
count,
start //
);
result = IsValidIndex(hhIDX);
if (!result)
{
return result;
}
//
llIDX = iLowest(
bar.symbol,
bar.period,
MODE_LOW,
count,
start //
);
result = IsValidIndex(llIDX);
if (!result)
{
return result;
}
//
hh = iHigh(
bar.symbol,
bar.period,
hhIDX //
);
ll = iLow(
bar.symbol,
bar.period,
llIDX //
);
//
return result;
}
/**
* Fill Prices ...
*
* @param prices: double collection
* @param bar: XOHCL instance reference, Provides Start ...
* @param loopback: int, Specified How Many Bars Process ...
* @param type: ENUM_X_PRICE member, Specified Price Type ...
*
* @return ( bool )
*/
int FillPrice(
double &prices[],
XOHCL &bar,
int loopback = 14,
ENUM_X_PRICE type = X_PRICE_CLOSE //
)
{
//
int result = 0;
//
Clean(prices);
//
loopback = NormalizeInt(loopback, 1);
//
bool has = IsValid(type) &&
bar.IsValid();
if (!has)
{
return result;
}
//
string symbol = bar.symbol;
ENUM_TIMEFRAMES period = bar.period;
//
// Calculate Loopback Data ...
int index = -1;
int start = -1;
int end = -1;
int count = -1;
has = CalculateLoopbackData(
index,
start,
end,
count,
bar,
loopback //
);
if (!has)
{
return result;
}
//
for (int i = start; i < end; i++)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
symbol,
period,
i //
);
if (!isInited)
{
//
iBar.Clean();
continue;
}
//
double iPrice = iBar.GetPrice(type);
//
isInited = NotEmptyZero(iPrice);
if (isInited)
{
//
Add(
iPrice,
prices //
);
}
//
iBar.Clean();
}
//
result = ArraySize(prices);
has = result == count;
if (!has)
{
//
Clean(prices);
}
//
ArrayReverse(prices);
//
return result;
}
/**
* Calculate Price Range ...
*
* @param ranges: double Collection, Calculated Ranges ...
* @param bar: XOHCL instance Reference, Start Bar ...
* @param forceBody: bool, Force to Calculate Range using Body ...
* @param forceDiff: bool, Force to Calculate Range using Onl Price Diff ...
* @param loopback: int, loopback period for Range Calculations ...
*
* @return ( int )
*/
int GetPriceRange(
double &ranges[],
XOHCL &bar,
bool forceBody = false,
bool forceDiff = false,
int loopback = 14 //
)
{
//
int result = 0;
//
Clean(ranges);
//
loopback = NormalizeInt(loopback, 1);
//
if (!bar.IsValid())
{
return result;
}
//
bool has = false;
//
// Select Uppers Prices ...
double uppers[];
int uppersCount = 0;
if (forceBody)
{
//
has = FillPrice(
uppers,
bar,
loopback,
X_PRICE_UP //
);
}
else
{
//
has = FillPrice(
uppers,
bar,
loopback,
X_PRICE_HIGH //
);
}
if (has)
{
uppersCount = ArraySize(uppers);
}
//
// Select Lower Prices ...
double lowers[];
int lowersCount = 0;
if (forceBody)
{
//
has = FillPrice(
lowers,
bar,
loopback,
X_PRICE_DOWN //
);
}
else
{
//
has = FillPrice(
lowers,
bar,
loopback,
X_PRICE_LOW //
);
}
if (has)
{
lowersCount = ArraySize(lowers);
}
//
// Validate Filled Prices ...
has =
IsValidSize(uppersCount) &&
IsValidSize(lowersCount) &&
uppersCount == lowersCount;
if (!has)
{
//
Clean(uppers);
Clean(lowers);
//
return result;
}
//
for (int i = 0; i < uppersCount; i++)
{
//
double iDiff = uppers[i] - lowers[i];
double iValue =
forceDiff
? iDiff
: lowers[i] + iDiff;
//
Add(
iValue,
ranges //
);
}
//
result = ArraySize(ranges);
ArrayReverse(ranges);
//
// Cleanup Resources ...
//
Clean(uppers);
Clean(lowers);
//
return result;
}
/**
* Retrieve Price Velocities ...
*
* @param velocities: double Collection, Price Velocities ...
* @param bar: XOHCL instance Reference, Start Bar ...
* @param type: ENUM_X_PRICE member ...
* @param loopback: int, loopback period for Calculations ...
*
* @return ( int )
*/
int GetPriceVelocity(
double &velocities[],
XOHCL &bar,
ENUM_X_PRICE type = X_PRICE_CLOSE,
int loopback = 14 //
)
{
//
int result = 0;
//
Clean(velocities);
loopback = NormalizeInt(loopback, 1);
//
result = IsValid(type) &&
bar.IsValid();
//
int to = bar.Index();
int from = to + loopback;
for (int i = to; i < from; i++)
{
//
double iPrice = GetAppliedPrice(
bar.symbol,
bar.period,
i,
type //
);
//
double pPrice = GetAppliedPrice(
bar.symbol,
bar.period,
i + 1,
type //
);
//
double iVelocity = MathAbs(iPrice - pPrice);
Add(
iVelocity,
velocities //
);
}
//
result = ArraySize(velocities);
//
return result;
}
/**
* Calculate Price Change Percent ...
*
* @param bar: XOHCL instance Reference, Start Bar ...
* @param type: ENUM_X_PRICE member, Specified Price Type ...
* @param loopback: int, loopback period for Range Calculated ...
*
* @return ( double )
*/
double GetPriceChangeRate(
XOHCL &bar,
ENUM_X_PRICE type = X_PRICE_MEDIAN,
int loopback = 14 //
)
{
//
double result = 0;
//
bool has = false;
//
loopback = NormalizeInt(loopback, 1);
//
has =
bar.IsValid() &&
IsValid(type);
if (!has)
{
return result;
}
//
XOHCL oldBar;
has = oldBar.Init(
bar.symbol,
bar.period,
bar.Index() + loopback //
);
if (!has)
{
//
oldBar.Clean();
//
return result;
}
double newPrice = bar.GetPrice(type);
double oldPrice = oldBar.GetPrice(type);
//
result = ((newPrice - oldPrice) / oldPrice) / 100;
//
oldBar.Clean();
//
return result;
}
/**
* Detect Range Block ...
*/
bool DetectRangeBlocks(
XOHCL &bar,
XBoxZone &upper,
XBoxZone &lower,
int loopback = 288,
ENUM_SERIESMODE upperRangeUpperMode = MODE_HIGH,
ENUM_SERIESMODE upperRangeLowerMode = MODE_LOW,
ENUM_SERIESMODE lowerRangeUpperMode = MODE_HIGH,
ENUM_SERIESMODE lowerRangeLowerMode = MODE_LOW //
)
{
//
bool result = false;
//
// Normalize Args ...
upper.Clean();
lower.Clean();
loopback = NormalizeInt(loopback, 10);
//
// Validate Args ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
XOHCL iBar;
result = iBar.Init(
bar.symbol,
bar.period,
bar.Index() + loopback //
);
if (!result)
{
//
iBar.Clean();
//
return result;
}
//
double hhUpper = iBar.FindHighest(loopback, upperRangeUpperMode);
double hhLower = iBar.FindHighest(loopback, upperRangeLowerMode);
//
double llUpper = iBar.FindLowest(loopback, lowerRangeUpperMode);
double llLower = iBar.FindLowest(loopback, lowerRangeLowerMode);
//
double bhhUpper = bar.FindHighest(iBar.Index() - bar.Index(), upperRangeUpperMode);
double bhhLower = bar.FindHighest(iBar.Index() - bar.Index(), upperRangeLowerMode);
//
double bllUpper = bar.FindLowest(iBar.Index() - bar.Index(), lowerRangeUpperMode);
double bllLower = bar.FindLowest(iBar.Index() - bar.Index(), lowerRangeLowerMode);
//
hhUpper = MathMax(hhUpper, bhhUpper);
hhLower = MathMax(hhLower, bhhLower);
//
llUpper = MathMin(llUpper, bllUpper);
llLower = MathMin(llLower, bllLower);
//
datetime from = GetBarTime(
iBar.symbol,
iBar.period,
iBar.Index() + loopback //
);
//
upper.from = from;
upper.type = "XRNG";
upper.to = bar.time;
upper.upper = hhUpper;
upper.lower = hhLower;
upper.symbol = iBar.symbol;
upper.period = iBar.period;
upper.dir = X_DIRECTION_BEARISH;
//
lower.from = from;
lower.type = "XRNG";
lower.to = bar.time;
lower.upper = llUpper;
lower.lower = llLower;
lower.symbol = iBar.symbol;
lower.period = iBar.period;
lower.dir = X_DIRECTION_BULLISH;
//
result = upper.IsValid() &&
lower.IsValid();
if (!result)
{
//
iBar.Clean();
upper.Clean();
lower.Clean();
}
//
iBar.Clean();
//
return result;
}
/**
* Calculate Specified Bars Range Volume ...
*
* @param bar: XOHCL instance reference ...
* @param bullishVolume: double
* @param bearishVolume: double
* @param loopback: int
*
* @return ( bool )
*/
bool CalculateRangeVolume(
XOHCL &bar,
double &bullishVolume,
double &bearishVolume,
int loopback = 5 //
)
{
//
bool result = false;
//
// Normalize Args ...
bullishVolume = 0;
bearishVolume = 0;
loopback = NormalizeInt(loopback, 3);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
XOHCL iBar;
bool has = false;
int start = bar.Index();
int end = start + loopback;
for (int i = start; i <= end; i++)
{
//
iBar.Clean();
has = iBar.Init(
bar.symbol,
bar.period,
i //
);
if (!has)
{
//
iBar.Clean();
//
break;
}
//
bool isBullish = iBar.IsBullish();
bool isBearish = iBar.IsBearish();
//
if (isBullish)
{
bullishVolume += (double)iBar.volume;
}
else if (isBearish)
{
bearishVolume += (double)iBar.volume;
}
else
{
//
bullishVolume += (double)iBar.volume;
bearishVolume += (double)iBar.volume;
}
//
iBar.Clean();
}
//
result = iBar.IsValid();
//
iBar.Clean();
//
return result;
}
/**
* Detect Same Bars ...
*
* @param bar: XOHCL instance, Start Bar ...
* @param dir: ENUM_X_DIRECTION member, Holds Result Direction ...
* @param index: Integer, Holds Result Index ...
* @param sameBars: Iteger, Required Same Bar ...
*
* @return ( bool )
*/
bool HasSameBars(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int &index,
int sameBars = 3 //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
//
if (sameBars < 1)
{
sameBars = 1;
}
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
index = bar.Index() + 1;
bool canContinue = true;
int sameBullishBarsFounded = 0;
int sameBearishBarsFounded = 0;
bool canContinueForBullish = true;
bool canContinueForBearish = true;
while (canContinue)
{
//
XOHCL iBar;
result = iBar.Init(
bar.symbol,
bar.period,
index //
);
if (!result)
{
break;
}
//
bool isBullish = iBar.IsBullish();
bool isBearish = iBar.IsBearish();
result = isBullish ||
isBearish;
if (!result)
{
break;
}
//
if (isBullish)
{
//
sameBullishBarsFounded++;
canContinueForBearish = false;
}
else if (isBearish)
{
//
sameBearishBarsFounded++;
canContinueForBullish = false;
}
else
{
//
sameBullishBarsFounded = 0;
sameBearishBarsFounded = 0;
canContinueForBullish = false;
canContinueForBearish = false;
}
//
result = canContinueForBullish ||
canContinueForBearish;
if (!result)
{
break;
}
//
canContinueForBullish =
canContinueForBullish &&
sameBullishBarsFounded > 0;
//
canContinueForBearish =
canContinueForBearish &&
sameBearishBarsFounded > 0;
//
canContinue =
canContinueForBullish ||
canContinueForBearish;
if (canContinue)
{
index++;
}
}
//
bool hasBullishSameBars =
sameBullishBarsFounded >= sameBars;
//
bool hasBearishSameBars =
sameBearishBarsFounded >= sameBars;
//
result = hasBullishSameBars ||
hasBearishSameBars;
if (!result)
{
return result;
}
//
index--;
//
dir =
hasBullishSameBars
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
return result;
}
/**
* Check Fibonacci Level 382 Pressure ...
*
* @param bar: XOHCL instance ...
* @param dir: ENUM_X_DIRECTION member ...
*
* @return ( bool )
*/
bool HasFiboPressure(
XOHCL &bar,
ENUM_X_DIRECTION forDir,
ENUM_X_FIBO_LEVELS level //
)
{
//
bool result = false;
//
result = bar.IsValid() &&
HasDirection(forDir);
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(forDir);
bool isBearish = IsBearish(forDir);
//
double fiboLevelValue = GetFibonacciLevel(
bar.high,
bar.low,
level,
forDir //
);
//
bool isBullishPressured =
isBullish &&
bar.GetDown() > fiboLevelValue;
bool isBearishPressured =
isBearish &&
bar.GetUp() < fiboLevelValue;
//
result = isBullishPressured ||
isBearishPressured;
//
return result;
}
/**
* Detect Big Price Change Happens or not ...
*
* @param bar: XOHCL instance reference, Start Bar ...
* @param dir: ENUM_X_DIRECTION member, Event Direction ...
* @param rootIDX: int, Root of Momentum Index ...
* @param type: ENUM_X_PRICE member, Price Type ...
* @param forcBodyInRange: bool, Use Body in Range Detection ...
* @param rangeExtendMultiplier: double, a Multiplier for Checking Price Range ...
*
* @return ( bool )
*/
bool IsSharp(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int &rootIDX,
ENUM_X_PRICE type = X_PRICE_CLOSE,
bool forcBodyInRange = true,
double rangeExtendMultiplier = 2.0 //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
rangeExtendMultiplier = NormalizeDouble(rangeExtendMultiplier, 1);
//
result =
bar.IsValid() &&
IsValid(type);
if (!result)
{
return result;
}
//
double minPriceChangePercent = 0;
int loopback = GetPeriodSharpData(
minPriceChangePercent,
bar.period //
);
//
// Retrieve Price Change Percent ...
double priceChangePercent = GetPriceChangeRate(
bar,
type,
loopback //
);
//
// Velocities ...
double velocities[];
int velocitiesCount = GetPriceVelocity(
velocities,
bar,
type,
loopback //
);
double velocitiesAvg = GetAverage(velocities);
double oldPrice = GetAppliedPrice(
bar.symbol,
bar.period,
bar.Index() + loopback,
type //
);
double newPrice = bar.GetPrice(type);
double currVelocity = MathAbs(oldPrice - newPrice);
//
// Calculate HH and LL ...
//
double hh = 0;
double ll = 0;
int hhIDX = -1;
int llIDX = -1;
result = CalculateLoopbackHLData(
hhIDX,
hh,
llIDX,
ll,
bar,
loopback //
);
result =
result &&
ll > 0 &&
hh > ll &&
IsValidIndex(llIDX) &&
IsValidIndex(hhIDX);
if (!result)
{
return result;
}
//
int hhDiff = (hhIDX - bar.Index());
int llDiff = (llIDX - bar.Index());
//
// Bool Get Boundary Direction ...
//
// Check Price Change Rate ...
//
bool isBullish =
//
hhDiff <= 1 &&
llIDX > hhIDX &&
priceChangePercent > 0 &&
priceChangePercent >= minPriceChangePercent &&
currVelocity > (velocitiesAvg * rangeExtendMultiplier)
//
;
//
bool isBearish =
//
llDiff <= 1 &&
hhIDX > llIDX &&
priceChangePercent < 0 &&
MathAbs(priceChangePercent) >= minPriceChangePercent &&
currVelocity > (velocitiesAvg * rangeExtendMultiplier)
//
;
//
result = isBullish ||
isBearish;
if (result)
{
//
rootIDX =
isBullish
? llIDX
: hhIDX;
//
dir = isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
}
//
return result;
}
//
// Actions ...
/**
* Check a Bar is End of an OrderBlock Bar or Not ...
*
* @param bar: XOHCL ...
* @param box: XBoxZone ...
* @param forceFVGBarType: bool, Force all Bars must be Same as Direction ...
* @param forceOBTwoBar: bool, Force Two Bars of OB Start must be InDirection ...
*
* @return ( bool )
*/
bool IsOB(
XOHCL &bar,
XBoxZone &box,
bool forceFVGBarType = false,
bool forceOBTwoBar = false //
)
{
//
bool result = false;
//
box.Clean();
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Check Bar Must be FVG ...
result = IsFVG(
bar,
box,
forceFVGBarType //
);
if (!result)
{
//
box.Clean();
//
return result;
}
//
box.type = "XOB";
//
bool isBullish = box.IsBullish();
bool isBearish = box.IsBearish();
//
// Order Block Includes an FVG which Starts by atleast One
// or More Indirectional Bars ...
XOHCL fvgLastBar;
XOHCL fvgLastBarPrev;
XOHCL fvgLastBarPrev2;
//
int barIndex = bar.Index();
int fvgLastBarIndex = barIndex + 3;
result = fvgLastBar.Init(
bar.symbol,
bar.period,
fvgLastBarIndex //
);
result =
result &&
fvgLastBar.GetPreviousBar(fvgLastBarPrev);
result =
result &&
fvgLastBarPrev.GetPreviousBar(fvgLastBarPrev2);
if (!result)
{
//
box.Clean();
fvgLastBar.Clean();
fvgLastBarPrev.Clean();
fvgLastBarPrev2.Clean();
//
return result;
}
//
// Check FVG Last Bar ...
//
bool isBullishBlock =
isBullish &&
(fvgLastBar.IsBearish() ||
(fvgLastBar.IsBullish() &&
fvgLastBarPrev.IsBearish()));
//
bool isBearishBlock =
isBearish &&
(fvgLastBar.IsBullish() ||
(fvgLastBar.IsBearish() &&
fvgLastBarPrev.IsBullish()));
//
// Update Box ...
//
if (isBullishBlock ||
isBearishBlock)
{
//
box.from = fvgLastBar.time;
//
box.lower = MathMin(box.lower, fvgLastBar.low);
box.upper = MathMax(box.upper, fvgLastBar.high);
}
//
// Apply Force Two Bar ...
if (forceOBTwoBar)
{
//
isBullishBlock =
isBullishBlock &&
fvgLastBarPrev.IsBearish();
//
isBearishBlock =
isBearishBlock &&
fvgLastBarPrev.IsBullish();
//
// Update Box ...
if (isBullishBlock ||
isBearishBlock)
{
//
box.from = fvgLastBarPrev.time;
box.lower = MathMin(box.lower, fvgLastBarPrev.low);
box.upper = MathMax(box.upper, fvgLastBarPrev.high);
}
}
//
result = isBullishBlock ||
isBearishBlock;
if (!result)
{
//
box.Clean();
fvgLastBar.Clean();
fvgLastBarPrev.Clean();
//
return result;
}
//
result = box.IsValid();
//
// Cleanup Resources ...
//
fvgLastBar.Clean();
fvgLastBarPrev.Clean();
//
return result;
}
/**
* Check a Bar is End of an FVG Bar or Not ...
*
* @param bar: XOHCL ...
* @param box: XBoxZone ...
* @param forceType: bool, Force all Bars must be Same as Direction ...
*
* @return ( bool )
*/
bool IsFVG(
XOHCL &bar,
XBoxZone &box,
bool forceType = false //
)
{
//
bool result = false;
//
box.Clean();
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
XOHCL pBar;
XOHCL p2Bar;
result = bar.GetPreviousBar(pBar);
result = result &&
pBar.GetPreviousBar(p2Bar);
if (!result)
{
//
pBar.Clean();
p2Bar.Clean();
//
return result;
}
//
bool isBullish = p2Bar.high < bar.low;
bool isBearish = p2Bar.low > bar.high;
//
result = isBullish ||
isBearish;
//
// Apply Force Type ...
if (result)
{
//
if (isBullish)
{
//
result =
bar.IsBullish() &&
pBar.IsBullish() &&
p2Bar.IsBullish();
}
else if (isBearish)
{
//
result =
bar.IsBearish() &&
pBar.IsBearish() &&
p2Bar.IsBearish();
}
}
//
if (result)
{
//
box.to = bar.time;
box.from = p2Bar.time;
box.symbol = bar.symbol;
box.period = bar.period;
box.dir = isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
box.upper = isBullish
? bar.low
: p2Bar.low;
box.lower = isBullish
? p2Bar.high
: bar.high;
box.type = "XFVG";
}
//
pBar.Clean();
p2Bar.Clean();
//
result = box.IsValid();
//
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(
XOHCL &bar,
XBoxZone &trigger,
XBoxZone &ob,
XBoxZone &fvg,
XBoxZone &rLiquidity,
XBoxZone &fLiquidity,
XOHCL &swingBar,
int loopback = 10,
double maxAllowedRange = 0.0,
int minAllowedBlockEdgeLength = 0,
bool forceOBOppositBar = true,
bool forceFVGBarType = true,
bool forceGapBarBreakout = true,
bool forceHasSwingBar = true,
bool forceHasLiquidity = true,
bool forceHasReversalLiquidity = true //
)
{
//
bool result = false;
//
// Normalize Args ...
ob.Clean();
fvg.Clean();
trigger.Clean();
swingBar.Clean();
rLiquidity.Clean();
fLiquidity.Clean();
loopback = NormalizeInt(loopback, 5);
//
// Validate Args ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
XOHCL pBar;
XOHCL tmpBar;
XOHCL tmpPBar;
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
//
result = bar.GetPreviousBar(pBar);
//
// Detect Base Order Block ...
result =
result &&
//
// Order Block Detection ...
IsOB(
pBar,
ob,
forceFVGBarType,
forceOBOppositBar //
) &&
//
// Gap Detection ...
IsFVG(
pBar,
fvg,
forceFVGBarType //
);
if (result)
{
//
trigger = ob;
trigger.type = "XTRG";
}
//
// Reading Requirements ...
//
double points = GetPoints(bar.symbol);
//
bool isBullish = ob.IsBullish();
bool isBearish = ob.IsBearish();
//
int toIDX = trigger.ToIndex();
int fromIDX = trigger.FromIndex();
//
// Validate Gaps Bar Breakeout ...
if (result &&
forceGapBarBreakout)
{
//
// Extract Gap Bar ...
tmpBar.Clean();
tmpPBar.Clean();
result =
//
// Retrieve Bars ...
fvg.ToBar(tmpBar) &&
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);
//
tmpBar.Clean();
tmpPBar.Clean();
}
//
// Validate Range ...
if (result &&
maxAllowedRange > 0)
{
//
double range = ob.GetRange();
result = range <= (maxAllowedRange * points);
}
//
// Validating Swing Bar ...
if (result &&
forceHasSwingBar)
{
//
int swingIDX = -1;
result = ob.FromBar(tmpBar);
if (result)
{
//
// Detect Swing Bar Index ...
if (isBullish)
{
swingIDX = tmpBar.FindLowestIndex(loopback, MODE_LOW);
}
else if (isBearish)
{
swingIDX = tmpBar.FindHighestIndex(loopback, MODE_HIGH);
}
result = IsValidIndex(swingIDX);
if (result)
{
//
// Initialize Swing Bar ...
result = swingBar.Init(
bar.symbol,
bar.period,
swingIDX //
);
}
//
// 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)
{
trigger.lower = MathMin(trigger.lower, swingBar.GetDown());
}
else if (isBearish)
{
trigger.upper = MathMax(trigger.upper, swingBar.GetUp());
}
}
}
//
tmpBar.Clean();
}
//
// 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 ...
result = tmpBar.Init(
bar.symbol,
bar.period,
i //
);
result =
result &&
(isBullish
? tmpBar.low > trigger.lower
: tmpBar.high > trigger.upper);
if (!result)
{
break;
}
//
tmpBar.Clean();
}
result = tmpBar.IsValid();
//
// Update Trigger Block ...
if (result)
{
trigger.from = ((datetime)(MathMin((int)trigger.from, (int)tmpBar.time)));
}
}
//
tmpBar.Clean();
}
//
// Validating Liquidity ...
if (result &&
(forceHasLiquidity ||
forceHasReversalLiquidity))
{
//
// Try to Detect Liquidity ...
toIDX = ob.ToIndex();
for (int i = toIDX; i < toIDX + (loopback * 10); i++)
{
//
// Initialize i Bar ...
result = tmpBar.Init(
bar.symbol,
bar.period,
i //
);
if (!result)
{
break;
}
//
// Detect Liquidity ...
bool isRejected =
result &&
IsRejected(
tmpBar,
iDir,
false, // Force Bar Type ...
true // Force Fibo Pressure ...
);
bool isBullishRejected =
isRejected &&
IsBullish(iDir);
bool isBearishRejected =
isRejected &&
IsBearish(iDir);
//
// Validate Liquidities ...
if (isBullish)
{
//
if (isBullishRejected &&
forceHasLiquidity &&
!fLiquidity.IsValid() &&
tmpBar.low < trigger.lower)
{
//
// Filling Following Liquidity ...
FillLiquidity(
tmpBar,
trigger.dir,
fLiquidity,
trigger.to //
);
}
//
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 ...
//
pBar.Clean();
tmpBar.Clean();
tmpPBar.Clean();
//
if (!result)
{
//
ob.Clean();
fvg.Clean();
trigger.Clean();
swingBar.Clean();
rLiquidity.Clean();
fLiquidity.Clean();
//
return result;
}
//
return result;
}
//
// Candlestick ...
/**
* Check Specified Bar is Doji Pattern or not ...
*
* @param bar: XOHCL instance reference, Specified Bar to Check ...
* @param dir: ENUM_X_DIRECTION member, Specified Direction ...
* @param shadowMultiplier: double, Specified Shadow Multiplier ...
*
* @return ( bool )
*/
bool IsDoji(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
double shadowMultiplier = 1.5 //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
shadowMultiplier = NormalizeDouble(shadowMultiplier, 1.5, 3);
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
double body = bar.GetBody();
double range = bar.GetRange();
//
result =
body > 0 &&
range > 0
? (body / range < 0.1)
: false;
if (result)
{
//
dir =
bar.GetLowShadow() >= (bar.GetHighShadow() * shadowMultiplier)
? X_DIRECTION_BULLISH
: bar.GetHighShadow() >= (bar.GetLowShadow() * shadowMultiplier)
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
//
result = HasDirection(dir);
}
//
return result;
}
/**
* Check Specified Bar is Swing or not ...
*
* @param bar: XOHCL instance reference, Specified Bar to Check ...
* @param dir: ENUM_X_DIRECTION member, Specified Direction ...
* @param loopback: int, Specified Loopback ...
*
* @return ( bool )
*/
bool IsSwing(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int loopback = 7 //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
loopback = NormalizeInt(loopback, 1);
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
XOHCL pBar;
result = bar.GetPreviousBar(pBar);
if (!result)
{
//
pBar.Clean();
return result;
}
//
XOHCL ppBar;
result = pBar.GetPreviousBar(ppBar);
if (!result)
{
//
pBar.Clean();
ppBar.Clean();
return result;
}
//
bool isBullish =
//
pBar.low < bar.low &&
pBar.low < ppBar.low &&
bar.GetDown() > pBar.low
//
;
//
bool isBearish =
//
pBar.high > bar.high &&
pBar.high > ppBar.high &&
bar.GetUp() < pBar.high
//
;
//
result = isBullish ||
isBearish;
if (result)
{
//
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
ppBar.Clean();
int pBarIDX = pBar.Index();
for (int i = pBarIDX + 1; i < pBarIDX + loopback; i++)
{
//
bool has = ppBar.Init(
pBar.symbol,
pBar.period,
i //
);
//
isBullish =
has &&
isBullish &&
pBar.low < ppBar.low;
//
isBearish =
has &&
isBearish &&
pBar.high > ppBar.high;
}
//
result = isBullish ||
isBearish;
if (!result)
{
dir = X_DIRECTION_NONE;
}
}
//
// Cleanup Resources ...
//
pBar.Clean();
ppBar.Clean();
//
return result;
}
/**
* Check Specified Bar's Prev Bar is Simple Swing or not ...
*
* @param bar: XOHCL instance reference, Specified Bar to it's Prev Check ...
* @param dir: ENUM_X_DIRECTION member, Specified Direction ...
*
* @return ( bool )
*/
bool IsSimpleSwing(
XOHCL &bar,
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
//
// Valdate Args ...
result = bar.IsValid();
//
// Reading Requirements ...
XOHCL cBar;
XOHCL pBar;
XOHCL p2Bar;
result =
bar.GetPreviousBar(cBar);
result =
result &&
cBar.GetPreviousBar(pBar);
result =
result &&
pBar.GetPreviousBar(p2Bar);
if (!result)
{
//
cBar.Clean();
pBar.Clean();
p2Bar.Clean();
//
return result;
}
//
// Now we Have to Check pBar is Swing Low or High ...
//
bool isPBarSwingLow =
pBar.low < cBar.low &&
pBar.low < p2Bar.low;
//
bool isPBarSwingHigh =
pBar.high > cBar.high &&
pBar.high > p2Bar.high;
//
result = isPBarSwingLow ||
isPBarSwingHigh;
if (result)
{
//
dir = isPBarSwingLow
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
}
//
// Cleanup Resourses ...
//
cBar.Clean();
pBar.Clean();
p2Bar.Clean();
//
return result;
}
/**
* Check Specified Bar is Hammer Pattern or not ...
*
* @param bar: XOHCL instance reference, Specified Bar to Check ...
* @param dir: ENUM_X_DIRECTION member, Specified Direction ...
* @param bodyMultiplier: double, Specified Body Multiplier ...
*
* @return ( bool )
*/
bool IsHammer(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
double bodyMultiplier = 2.0 //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
bodyMultiplier = NormalizeDouble(bodyMultiplier, 1.5, 3);
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
double body = bar.GetBody();
double lShadow = bar.GetLowShadow();
double hShadow = bar.GetHighShadow();
//
bool isBullish =
hShadow < body &&
lShadow > (bodyMultiplier * body);
//
bool isBearish =
lShadow < body &&
hShadow > (bodyMultiplier * body);
//
result = isBullish ||
isBearish;
if (result)
{
//
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
}
//
return result;
}
/**
* Check Specified Bar is Engulfed Prev Bar or not ...
*
* @param bar: XOHCL instance reference, Specified Bar to Check ...
* @param dir: ENUM_X_DIRECTION member, Specified Direction ...
*
* @return ( bool )
*/
bool IsEngulfed(
XOHCL &bar,
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
XOHCL pBar;
result = bar.GetPreviousBar(pBar);
if (!result)
{
//
pBar.Clean();
return result;
}
//
result = bar.GetBody() > pBar.GetBody();
if (!result)
{
//
pBar.Clean();
return result;
}
//
bool isBullish =
bar.IsBullish() &&
pBar.IsBearish() &&
bar.GetDown() <= pBar.GetDown() &&
bar.GetUp() > pBar.GetUp();
//
bool isBearish =
bar.IsBearish() &&
pBar.IsBullish() &&
bar.GetUp() >= pBar.GetUp() &&
bar.GetDown() < pBar.GetDown();
//
result = isBullish ||
isBearish;
if (result)
{
//
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
}
//
// Cleanup Resources ...
//
pBar.Clean();
//
return result;
}
/**
* Check Specified Bar is Momentum Bar or not ...
*
* @param bar: XOHCL instance reference, Specified Bar to Check ...
* @param dir: ENUM_X_DIRECTION member, Specified Direction ...
* @param forceBarType: bool, Force Apply Bar Type ...
* @param forceFiboPressure: bool, Force Apply Bar Type ...
*
* @return ( bool )
*/
bool IsRejected(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
bool forceBarType = true,
bool forceFiboPressure = true //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
XOHCL pBar;
result = bar.GetPreviousBar(pBar);
if (!result)
{
//
pBar.Clean();
return result;
}
//
bool isBullish =
//
bar.low < pBar.low &&
bar.GetShadows() > bar.GetBody() &&
bar.GetLowShadow() > bar.GetBody() &&
bar.GetLowShadow() > bar.GetHighShadow()
//
;
//
bool isBearish =
//
bar.high > pBar.high &&
bar.GetShadows() > bar.GetBody() &&
bar.GetHighShadow() > bar.GetBody() &&
bar.GetHighShadow() > bar.GetLowShadow()
//
;
//
result = isBullish ||
isBearish;
if (!result)
{
//
pBar.Clean();
return result;
}
//
// Check Force Type ...
if (forceBarType)
{
//
isBullish =
isBullish &&
bar.IsBullish();
//
isBearish =
isBearish &&
bar.IsBearish();
//
result = isBullish ||
isBearish;
if (!result)
{
//
pBar.Clean();
return result;
}
}
//
// Check Force Fibo Pressure ...
if (forceFiboPressure)
{
//
bool hasBullishFiboPressure =
HasFiboPressure(
bar,
X_DIRECTION_BULLISH,
X_FIBO_LEVEL_236 //
);
//
bool hasBearishFiboPressure =
HasFiboPressure(
bar,
X_DIRECTION_BEARISH,
X_FIBO_LEVEL_236 //
);
//
isBullish =
isBullish &&
hasBullishFiboPressure;
//
isBearish =
isBearish &&
hasBearishFiboPressure;
}
//
result = isBullish ||
isBearish;
if (result)
{
//
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
}
//
pBar.Clean();
//
return result;
}
/**
* Check Specified Bar is Momentum Bar or not ...
*
* @param bar: XOHCL instance reference, Specified Bar to Check ...
* @param dir: ENUM_X_DIRECTION member, Specified Direction ...
* @param loopback: int, Specified Loopback ...
*
* @return ( bool )
*/
bool IsMomentum(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int loopback = 2 //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
loopback = NormalizeInt(loopback, 1);
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
XOHCL pBar;
result = bar.GetPreviousBar(pBar);
if (!result)
{
//
pBar.Clean();
return result;
}
//
// Calculate HH and LL ...
double hh = 0;
double ll = 0;
int hhIDX = -1;
int llIDX = -1;
result = CalculateLoopbackHLData(
hhIDX,
hh,
llIDX,
ll,
bar,
loopback // s
);
result =
result &&
ll > 0 &&
hh > ll &&
IsValidIndex(llIDX) &&
IsValidIndex(hhIDX);
if (!result)
{
//
pBar.Clean();
return result;
}
//
bool isBullish =
bar.low > ll &&
bar.close >= hh &&
bar.IsBullish() &&
bar.low > pBar.low &&
bar.high > pBar.high &&
bar.GetBody() > pBar.GetBody() &&
bar.GetRange() > pBar.GetRange() &&
bar.GetShadows() < pBar.GetShadows();
//
bool isBearish =
bar.high < hh &&
bar.close <= ll &&
bar.IsBearish() &&
bar.low < pBar.low &&
bar.high < pBar.high &&
bar.GetBody() > pBar.GetBody() &&
bar.GetRange() > pBar.GetRange() &&
bar.GetShadows() < pBar.GetShadows();
//
result = isBullish ||
isBearish;
if (result)
{
//
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
}
//
pBar.Clean();
//
return result;
}
/**
* Check Specified Bar is Pullback or not ...
*
* @param bar: XOHCL instance reference, Specified Bar to Check ...
* @param dir: ENUM_X_DIRECTION member, Specified Direction ...
* @param loopback: int, Specified Loopback ...
* @param forceBody: bool, Force Using Body ...
*
* @return ( bool )
*/
bool IsPullback(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int loopback = 3,
bool forceBody = false //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
loopback = NormalizeInt(loopback, 3);
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Check Bar Must Engulfed ...
result = IsEngulfed(
bar,
dir //
);
if (!result)
{
return result;
}
//
// Calculate HH and LL ...
double hh = 0;
double ll = 0;
int hhIDX = -1;
int llIDX = -1;
result = CalculateLoopbackHLData(
hhIDX,
hh,
llIDX,
ll,
bar,
loopback //
);
result =
result &&
ll > 0 &&
hh > ll &&
IsValidIndex(llIDX) &&
IsValidIndex(hhIDX);
if (!result)
{
return result;
}
//
bool isBullish =
bar.high > hh &&
bar.low > ll;
//
bool isBearish =
bar.high < hh &&
bar.low < ll;
//
result = isBullish ||
isBearish;
if (result)
{
//
if (forceBody)
{
//
isBullish =
isBullish &&
bar.GetUp() > hh &&
bar.GetDown() > ll &&
llIDX == bar.Index() + 1;
//
isBearish =
isBearish &&
bar.GetUp() < hh &&
bar.GetDown() < ll &&
hhIDX == bar.Index() + 1;
//
result = isBullish ||
isBearish;
}
//
if (result)
{
//
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
}
}
//
return result;
}
/**
* Check Specified Bar is Sequence Edge Breaker Bar or not ...
*
* @param bar: XOHCL instance reference, Specified Bar to Check ...
* @param dir: ENUM_X_DIRECTION member, Holds Founded Direction ...
* @param loopback: int, Specified Loopback ...
*
* @return ( bool )
*/
bool IsSeqBreakEdge(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int loopback = 3 //
)
{
//
bool result = false;
//
// Normalize Args ...
dir = X_DIRECTION_NONE;
loopback = NormalizeInt(loopback, 3);
//
// Validate Args ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
bool isBullish = false;
bool isBearish = false;
//
// Check Has Sequence or not ...
XOHCL pBar;
XOHCL iBar;
XOHCL iPBar;
bool has = false;
int index = bar.Index();
int start = index + 1;
int end = start + loopback - 1;
bool hasBullishSeq = true;
bool hasBearishSeq = true;
for (int i = start; i < end; i++)
{
//
// Initialize Indexed Bar(s) ...
has = iBar.Init(
bar.symbol,
bar.period,
i //
);
has =
has &&
iBar.GetPreviousBar(iPBar);
//
// Bullish Sequence ...
if (hasBullishSeq)
{
//
hasBullishSeq =
has &&
iBar.low > iPBar.low;
}
//
// Bearish Sequence ...
if (hasBearishSeq)
{
//
hasBearishSeq =
has &&
iBar.high < iPBar.high;
}
//
if (!hasBullishSeq &&
!hasBearishSeq)
{
break;
}
//
iBar.Clean();
iPBar.Clean();
}
iBar.Clean();
iPBar.Clean();
//
// Check a Sequence Detect ...
result = hasBullishSeq ||
hasBearishSeq;
if (!result)
{
//
pBar.Clean();
iBar.Clean();
iPBar.Clean();
//
return result;
}
//
// Retrieve Previous Bar ...
result = bar.GetPreviousBar(pBar);
//
// Now we Have Ensure has a Sequence ...
//
isBullish =
result &&
hasBearishSeq &&
bar.high > pBar.high;
//
isBearish =
result &&
hasBullishSeq &&
bar.low < pBar.low;
//
// Summarizing Result ...
result = isBullish ||
isBearish;
if (result)
{
//
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
}
//
// Cleanup Resources ...
pBar.Clean();
iBar.Clean();
iPBar.Clean();
//
return result;
}
/**
* Check Specified Bar is Sequence Type Breaker Bar or not ...
*
* @param bar: XOHCL instance reference, Specified Bar to Check ...
* @param dir: ENUM_X_DIRECTION member, Holds Founded Direction ...
* @param loopback: int, Specified Loopback ...
*
* @return ( bool )
*/
bool IsSeqBreakType(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int loopback = 3 //
)
{
//
bool result = false;
//
// Normalize Args ...
dir = X_DIRECTION_NONE;
loopback = NormalizeInt(loopback, 3);
//
// Validate Args ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
bool isBullish = false;
bool isBearish = false;
//
// Check Has Sequence or not ...
XOHCL iBar;
bool has = false;
int index = bar.Index();
int start = index + 1;
int end = start + loopback;
bool hasBullishSeq = true;
bool hasBearishSeq = true;
for (int i = start; i < end; i++)
{
//
// Initialize Indexed Bar(s) ...
has = iBar.Init(
bar.symbol,
bar.period,
i //
);
//
// Bullish Sequence ...
if (hasBullishSeq)
{
//
hasBullishSeq =
has &&
iBar.IsBullish();
}
//
// Bearish Sequence ...
if (hasBearishSeq)
{
//
hasBearishSeq =
has &&
iBar.IsBearish();
}
//
if (!hasBullishSeq &&
!hasBearishSeq)
{
break;
}
//
iBar.Clean();
}
iBar.Clean();
//
// Check a Sequence Detect ...
result = hasBullishSeq ||
hasBearishSeq;
if (!result)
{
//
iBar.Clean();
//
return result;
}
//
// Now we Have Ensure has a Sequence ...
//
isBullish =
result &&
hasBearishSeq &&
bar.IsBullish();
//
isBearish =
result &&
hasBullishSeq &&
bar.IsBearish();
//
// Summarizing Result ...
result = isBullish ||
isBearish;
if (result)
{
//
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
}
//
// Cleanup Resources ...
iBar.Clean();
//
return result;
}
/**
* Check Specified Bar is Fully Sequence Breker Bar or not ...
*
* @param bar: XOHCL instance reference, Specified Bar to Check ...
* @param dir: ENUM_X_DIRECTION member, Holds Founded Direction ...
* @param loopback: int, Specified Loopback ...
*
* @return ( bool )
*/
bool IsSeqBreak(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int loopback = 3 //
)
{
//
bool result = false;
//
// Normalize Args ...
dir = X_DIRECTION_NONE;
loopback = NormalizeInt(loopback, 3);
//
// Validate Args ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Check Seq Edge ...
ENUM_X_DIRECTION seqEdgeDir;
bool isSeqEdgeBreaked = IsSeqBreakEdge(
bar,
seqEdgeDir //
);
//
// Check Seq Type ...
ENUM_X_DIRECTION seqTypeDir;
bool isSeqTypeBreaked = IsSeqBreakType(
bar,
seqTypeDir //
);
//
// Check Result ...
result = isSeqEdgeBreaked &&
isSeqTypeBreaked &&
seqEdgeDir == seqTypeDir;
if (result)
{
dir = seqEdgeDir;
}
//
return result;
}
//
//
//
/**
* Check a Bar is Valid for Specified Direction of Positions ...
*
* @param bar: XOHCL instance, Start Bar ...
* @param dir: ENUM_X_DIRECTION member, Provide Direction ...
*
* @return ( bool )
*/
bool IsValidForTrigger(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
bool allowCond1 = true,
bool allowCond2 = true,
bool allowCond3 = true,
bool allowCond4 = true,
bool allowCond5 = true,
bool allowCond6 = true,
bool allowCond7 = true //
)
{
//
bool result = false;
//
// Normalize Args ...
dir = X_DIRECTION_NONE;
//
// Validate Args ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Prepare Requirements ...
XOHCL pBar;
XOHCL p2Bar;
int loopback = 3;
bool isBullish = false;
bool isBearish = false;
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
//
// Retrieve Bar's Prev ...
result = bar.GetPreviousBar(pBar);
result = result &&
pBar.GetPreviousBar(p2Bar);
//
// Handle Detect Trigger Bar ...
if (result)
{
//
// Check States ...
//
// Rejected ...
bool isRejected = IsRejected(
pBar,
iDir,
false, // Force Type ...
true // Force Fibo Pressure ...
);
bool isBullishRejected =
isRejected &&
IsBullish(iDir);
bool isBearishRejected =
isRejected &&
IsBearish(iDir);
//
// Simple Rejected ...
bool isSimpleRejected = IsRejected(
pBar,
iDir,
false, // Force Type ...
false // Force Fibo Pressure ...
);
bool isSimpleBullishRejected =
isSimpleRejected &&
IsBullish(iDir);
bool isSimpleBearishRejected =
isSimpleRejected &&
IsBearish(iDir);
//
// Full Directional Rejection ...
bool isFullRejected = IsRejected(
pBar,
iDir,
true, // Force Type ...
true // Force Fibo Pressure ...
);
bool isFullBullishRejected =
isFullRejected &&
IsBullish(iDir);
bool isFullBearishRejected =
isRejected &&
IsBearish(iDir);
//
// Engulfed ...
bool isEngulfed = IsEngulfed(
pBar,
iDir //
);
bool isBullishEngulfed =
isEngulfed &&
IsBullish(iDir);
bool isBearishEngulfed =
isEngulfed &&
IsBearish(iDir);
//
// Momentum ...
bool isMomentum = IsMomentum(
pBar,
iDir //
);
bool isBullishMomentum =
isMomentum &&
IsBullish(iDir);
bool isBearishMomentum =
isMomentum &&
IsBearish(iDir);
//
// Simple Swing ...
bool isSwing = IsSimpleSwing(
pBar,
iDir //
);
bool isBullishSwing =
isSwing &&
IsBullish(iDir);
bool isBearishSwing =
isSwing &&
IsBearish(iDir);
//
// Full Swing ...
bool isFullSwing = IsSwing(
pBar,
iDir,
5 //
);
bool isFullBullishSwing =
isFullSwing &&
IsBullish(iDir);
bool isFullBearishSwing =
isFullSwing &&
IsBearish(iDir);
//
// Sequence Breaker ...
bool isSeqBreak = IsSeqBreak(
pBar,
iDir,
3 //
);
bool isBullishSeqBreak =
isSeqBreak &&
IsBullish(iDir);
bool isBearishSeqBreak =
isSeqBreak &&
IsBearish(iDir);
//
// Now we have to Combine Conditions ...
//
// Cond 1 ...
bool isBullishCond1 = false;
bool isBearishCond1 = false;
if (allowCond1)
{
//
// Bullish ...
isBullishCond1 =
//
isFullBullishRejected
//
;
//
// Bearish ...
isBearishCond1 =
//
isFullBearishRejected
//
;
}
//
// Cond 2 ...
bool isBullishCond2 = false;
bool isBearishCond2 = false;
if (allowCond2)
{
//
// Bullish ...
isBullishCond2 =
//
isBullishSwing &&
isBullishRejected
//
;
//
// Bearish ...
isBearishCond2 =
//
isBearishSwing &&
isBearishRejected
//
;
}
//
// Cond 3 ...
bool isBullishCond3 = false;
bool isBearishCond3 = false;
if (allowCond3)
{
//
// Bullish ...
isBullishCond3 =
//
isBullishSwing &&
(isBullishRejected ||
isBullishEngulfed ||
isBullishMomentum)
//
;
//
// Bearish ...
isBearishCond3 =
//
isBearishSwing &&
(isBearishRejected ||
isBearishEngulfed ||
isBearishMomentum)
//
;
}
//
// Cond 4 ...
bool isBullishCond4 = false;
bool isBearishCond4 = false;
if (allowCond4)
{
//
// Bullish ...
isBullishCond4 =
//
isBullishSwing &&
isBullishSeqBreak &&
(isBullishRejected ||
isBullishEngulfed ||
isBullishMomentum)
//
;
//
// Bearish ...
isBearishCond4 =
//
isBearishSwing &&
isBearishSeqBreak &&
(isBearishRejected ||
isBearishEngulfed ||
isBearishMomentum)
//
;
}
//
// Cond 5 ...
bool isBullishCond5 = false;
bool isBearishCond5 = false;
if (allowCond5)
{
//
// Bullish ...
isBullishCond5 =
//
isFullBullishSwing &&
(isBullishRejected ||
isBullishEngulfed ||
isBullishMomentum)
//
;
//
// Bearish ...
isBearishCond5 =
//
isFullBearishSwing &&
(isBearishRejected ||
isBearishEngulfed ||
isBearishMomentum)
//
;
}
//
// Cond 6 ...
bool isBullishCond6 = false;
bool isBearishCond6 = false;
if (allowCond6)
{
//
// Bullish ...
isBullishCond6 =
//
p2Bar.IsBearish() &&
pBar.IsBullish() &&
pBar.low < p2Bar.low &&
pBar.high > p2Bar.high &&
pBar.GetDown() <= p2Bar.GetDown() &&
(isBullishEngulfed ||
isBullishMomentum ||
isSimpleBullishRejected)
//
;
//
// Bearish ...
isBearishCond6 =
//
p2Bar.IsBullish() &&
pBar.IsBearish() &&
pBar.high > p2Bar.high &&
pBar.low < p2Bar.low &&
pBar.GetUp() >= p2Bar.GetUp() &&
(isBearishEngulfed ||
isBearishMomentum ||
isSimpleBearishRejected)
//
;
}
//
// Cond 7 ...
bool isBullishCond7 = false;
bool isBearishCond7 = false;
if (allowCond7)
{
//
// Bullish ...
isBullishCond7 =
//
p2Bar.IsBearish() &&
pBar.IsBullish() &&
pBar.low < p2Bar.low &&
pBar.high > p2Bar.high &&
pBar.GetUp() >= p2Bar.GetUp()
//
;
//
// Bearish ...
isBearishCond7 =
//
p2Bar.IsBullish() &&
pBar.IsBearish() &&
pBar.high > p2Bar.high &&
pBar.low < p2Bar.low &&
pBar.GetDown() <= p2Bar.GetDown()
//
;
}
//
// Summarizie Result ...
//
isBullish =
//
isBullishCond1 ||
isBullishCond2 ||
isBullishCond3 ||
isBullishCond4 ||
isBullishCond5 ||
isBullishCond6 ||
isBullishCond7
//
;
//
isBearish =
//
isBearishCond1 ||
isBearishCond2 ||
isBearishCond3 ||
isBearishCond4 ||
isBearishCond5 ||
isBearishCond6 ||
isBearishCond7
//
;
}
//
// Summarize Result ...
result = (isBullish &&
!isBearish) ||
(isBearish &&
!isBullish);
if (result)
{
//
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
}
//
// Cleanup Resources ...
pBar.Clean();
p2Bar.Clean();
//
return result;
}
//
protected:
//
//
private:
//
//
// Props ...
//
// Actions ...
//
};
//