Files
xMQL5/BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-poi.detector.class.mq5
T
2025-05-08 14:17:59 +03:30

3402 lines
75 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Indicator
// -------------------------------------------------
// Name: XCXCAEAPOIDetector ...
// Description: Class for XCAEA POI Detector ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm Class for XCAEA POI Detector"
#property strict
//
// Imports ...
#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5"
#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5"
#include "../Helpers/xcaea.helper.mq5"
//
// Definitions ...
//
enum ENUM_XCA_PIVOTS
{
XCA_NONE, // None
XCA_PEAK, // Peak
XCA_VALE, // Vale
XCA_FVG_BULL, // FVGBull
XCA_FVG_BEAR, // FVGBear
XCA_RSI_COOS, // RSICOOS
XCA_RSI_CUOB, // RSICUOB
XCA_TREND_BULL, // TrendBull
XCA_TREND_BEAR, // TrendBear
};
//
bool IsValid(ENUM_XCA_PIVOTS value)
{
//
bool result = false;
//
result = value != XCA_NONE;
//
return result;
}
//
string ToString(ENUM_XCA_PIVOTS value)
{
//
string result = NULL;
//
result = EnumToString(value);
//
return result;
}
//
ENUM_X_DIRECTION GetDirection(ENUM_XCA_PIVOTS value)
{
//
ENUM_X_DIRECTION result = X_DIRECTION_NONE;
//
switch (value)
{
//
case XCA_VALE:
case XCA_FVG_BULL:
case XCA_RSI_COOS:
case XCA_TREND_BULL:
result = X_DIRECTION_BULLISH;
break;
//
case XCA_PEAK:
case XCA_FVG_BEAR:
case XCA_RSI_CUOB:
case XCA_TREND_BEAR:
result = X_DIRECTION_BEARISH;
break;
}
//
return result;
}
//
string GetBoxType(ENUM_XCA_PIVOTS value)
{
//
string result = NULL;
//
switch (value)
{
//
case XCA_VALE:
case XCA_PEAK:
case XCA_RSI_COOS:
case XCA_RSI_CUOB:
result = ToString(value);
break;
//
case XCA_FVG_BULL:
case XCA_FVG_BEAR:
result = "XCA_FVG";
break;
//
case XCA_TREND_BULL:
case XCA_TREND_BEAR:
result = "XCA_TREND";
break;
}
//
return result;
}
//
ENUM_XCA_PIVOTS GetPivotType(XBoxZone &value)
{
//
ENUM_XCA_PIVOTS result = XCA_NONE;
//
bool has = value.IsValid();
if (!has)
{
return result;
}
//
bool isPeak = value.type == GetBoxType(XCA_PEAK) &&
value.dir == GetDirection(XCA_PEAK);
bool isVale = value.type == GetBoxType(XCA_VALE) &&
value.dir == GetDirection(XCA_VALE);
bool isFVGBull = value.type == GetBoxType(XCA_FVG_BULL) &&
value.dir == GetDirection(XCA_FVG_BULL);
bool isFVGBear = value.type == GetBoxType(XCA_FVG_BEAR) &&
value.dir == GetDirection(XCA_FVG_BEAR);
bool isRSICrossedOverOS = value.type == GetBoxType(XCA_RSI_COOS) &&
value.dir == GetDirection(XCA_RSI_COOS);
bool isRSICrossedUnderOB = value.type == GetBoxType(XCA_RSI_CUOB) &&
value.dir == GetDirection(XCA_RSI_CUOB);
bool isTrendBullish = value.type == GetBoxType(XCA_TREND_BULL) &&
value.dir == GetDirection(XCA_TREND_BULL);
bool isTrendBearish = value.type == GetBoxType(XCA_TREND_BEAR) &&
value.dir == GetDirection(XCA_TREND_BEAR);
//
if (isPeak)
{
result = XCA_PEAK;
}
else if (isVale)
{
result = XCA_VALE;
}
else if (isFVGBull)
{
result = XCA_FVG_BULL;
}
else if (isFVGBear)
{
result = XCA_FVG_BEAR;
}
else if (isRSICrossedOverOS)
{
result = XCA_RSI_COOS;
}
else if (isRSICrossedUnderOB)
{
result = XCA_RSI_CUOB;
}
else if (isTrendBullish)
{
result = XCA_TREND_BULL;
}
else if (isTrendBearish)
{
result = XCA_TREND_BEAR;
}
//
return result;
}
//
int ExtractPivots(
XBoxZone &extracted[],
ENUM_XCA_PIVOTS type,
XBoxZone &source[] //
)
{
//
int result = 0;
//
Clean(extracted);
//
bool has =
IsValid(type) &&
HasChild(source);
if (!has)
{
return result;
}
//
int count = ArraySize(source);
for (int i = 0; i < count; i++)
{
//
XBoxZone iBox = source[i];
//
ENUM_XCA_PIVOTS iType = GetPivotType(iBox);
//
has = iType == type;
if (has)
{
//
AddRef(
iBox,
extracted //
);
}
//
iBox.Clean();
}
//
result = ArraySize(extracted);
//
return result;
}
//
bool IsFakeBreakeout(
XBoxZone &pivot,
XCXCAEAHelper *helper,
int barIndex = 0 //
)
{
//
bool result = false;
//
barIndex = NormalizeInt(barIndex, 0);
//
result = pivot.IsValid();
if (!result)
{
return result;
}
//
int fromIDX = pivot.FromIndex();
result = barIndex < fromIDX;
if (!result)
{
return result;
}
//
bool isBullish = pivot.IsBullish();
//
// Retrieve Required Bars ...
XOHCL cBar;
XOHCL pBar;
XOHCL p2Bar;
XOHCL p3Bar;
result = cBar.Init(
pivot.symbol,
pivot.period,
barIndex //
);
result = result &&
cBar.GetPreviousBar(pBar);
result = result &&
pBar.GetPreviousBar(p2Bar);
result = result &&
p2Bar.GetPreviousBar(p3Bar);
if (!result)
{
//
cBar.Clean();
pBar.Clean();
p2Bar.Clean();
p3Bar.Clean();
//
return result;
}
//
// Bars Conditions ...
//
ENUM_X_DIRECTION cBarDir;
//
// Hammer ...
bool isCBarHammer = helper
.barAnalyser
.IsHammer(
cBar,
cBarDir //
);
bool isCBarBullishHammer =
isCBarHammer &&
IsBullish(cBarDir);
bool isCBarBearishHammer =
isCBarHammer &&
IsBearish(cBarDir);
//
// Rejected ...
bool isCBarRejected = helper
.barAnalyser
.IsRejected(
cBar,
cBarDir,
false, // Force Type ...
true // Force Fibo Pressure ...
);
bool isCBarBullishRejected =
isCBarRejected &&
IsBullish(cBarDir);
bool isCBarBearishRejected =
isCBarRejected &&
IsBearish(cBarDir);
//
// Engulfed ...
bool isCBarEngulfed = helper
.barAnalyser
.IsEngulfed(
cBar,
cBarDir //
);
bool isCBarBullishEngulfed =
isCBarEngulfed &&
IsBullish(cBarDir);
bool isCBarBearishEngulfed =
isCBarEngulfed &&
IsBearish(cBarDir);
//
// Momentum ...
bool isCBarMomentum = helper
.barAnalyser
.IsMomentum(
cBar,
cBarDir,
1 //
);
bool isCBarBullishMomentum =
isCBarMomentum &&
IsBullish(cBarDir);
bool isCBarBearishMomentum =
isCBarMomentum &&
IsBearish(cBarDir);
//
bool isCBarHasBullishPower = isCBarBullishRejected ||
isCBarBullishEngulfed ||
isCBarBullishMomentum;
//
bool isCBarHasBearishPower = isCBarBearishRejected ||
isCBarBearishEngulfed ||
isCBarBearishMomentum;
//
bool isBarPowerfull =
isBullish
? isCBarHasBullishPower
: isCBarHasBearishPower;
//
double breakPrice =
isBullish
? pivot.lower
: pivot.upper;
//
// CBar Must Go back InSide Box ...
bool isBarInside =
cBar.GetUp() > breakPrice &&
cBar.GetDown() < breakPrice &&
cBar.GetDirection() == pivot.dir;
//
result =
//
// Bar Must Inside Pivot ...
isBarInside &&
//
// Bar Must Has Required Direction Power ...
isBarPowerfull
//
;
//
cBar.Clean();
pBar.Clean();
p2Bar.Clean();
p3Bar.Clean();
//
return result;
}
//
struct XCAPivot
{
//
// Props ...
datetime to;
double value;
string symbol;
datetime from;
double reserve;
ENUM_XCA_PIVOTS type;
ENUM_TIMEFRAMES period;
//
double values[];
//
// Constructor ...
XCAPivot()
{
Clean();
}
//
// Tools ...
/**
* Cleanup ...
*/
void Clean()
{
//
value = 0;
to = NULL;
reserve = 0;
from = NULL;
symbol = NULL;
period = NULL;
type = XCA_NONE;
//
Clean(values);
//
ZeroMemory(this);
}
/**
* Validate ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
from < to &&
value != 0 &&
IsValid(to) &&
IsValid(from) &&
IsValid(type) &&
IsValid(symbol) &&
IsValid(period);
//
return result;
}
/**
* Check a Model is Same as this or not ...
*
* @param pivot: XCAPivot ...
*
* @return ( bool )
*/
bool IsSameAs(XCAPivot &pivot)
{
//
bool result = false;
//
result =
IsValid() &&
pivot.IsValid();
if (!result)
{
return result;
}
//
result =
to == pivot.to &&
from == pivot.from &&
type == pivot.type &&
value == pivot.value &&
symbol == pivot.symbol &&
period == pivot.period;
//
return result;
}
/**
* Retrieve To Index ...
*
* @param forPeriod: ENUM_TIMEFRAMES, Specified Period ...
*
* @return ( int )
*/
int ToIndex(
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
int result = -1;
//
if (!IsValid())
{
return result;
}
//
if (!IsValid(forPeriod))
{
forPeriod = period;
}
//
result = GetBarIndex(
symbol,
forPeriod,
to //
);
//
return result;
}
/**
* Retrieve From Index ...
*
* @param forPeriod: ENUM_TIMEFRAMES, Specified Period ...
*
* @return ( int )
*/
int FromIndex(
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
int result = -1;
//
if (!IsValid())
{
return result;
}
//
if (!IsValid(forPeriod))
{
forPeriod = period;
}
//
result = GetBarIndex(
symbol,
forPeriod,
from //
);
//
return result;
}
/**
* Retrieve Age of Pivot ...
*
* @param forPeriod: ENUM_TIMEFRAMES, Specified Period ...
*
* @return ( int )
*/
int GetAge(
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
if (!IsValid(forPeriod))
{
forPeriod = period;
}
//
int toIDX = ToIndex(forPeriod);
int fromIDX = FromIndex(forPeriod);
//
result = fromIDX - toIDX;
//
return result;
}
/**
* Converts Pivot to Box ...
*
* @param box: XBoxZone instance reference ...
*
* @return ( bool )
*/
bool AsBox(
XBoxZone &box //
)
{
//
bool result = false;
//
box.Clean();
//
result = IsValid();
if (!result)
{
return result;
}
//
ENUM_X_DIRECTION iDir = GetDirection(type);
//
result = HasDirection(iDir);
if (!result)
{
return result;
}
//
bool isBullish =
IsBullish(iDir) &&
value < reserve;
//
bool isBearish =
IsBearish(iDir) &&
value > reserve;
//
result = isBullish ||
isBearish;
if (!result)
{
return result;
}
//
box.to = to;
box.dir = iDir;
box.from = from;
box.symbol = symbol;
box.period = period;
//
string typeStr = GetBoxType(type);
box.type = typeStr;
//
box.upper =
isBullish
? reserve
: value;
box.lower =
isBullish
? value
: reserve;
//
result = box.IsValid();
if (!result)
{
box.Clean();
}
//
return result;
}
//
};
//
// Implementations ...
class XCXCAEAPOIDetector : public XCBase
{
//
// Public ...
public:
//
// Props ...
//
// Pivot Verifications and Max Allowed Holding Items ...
int maxAllowedPivots; // Max Allowed Holding Pibots ...
int pivotVerifications; // Pivots Verifications ...
int pivotDetectionLoopbac; // Pivots Detection Loopback ...
double ticksDividerInPoints; // Ticks and Volume Detection Divider in Point ...
//
// TREND ...
XBoxZone trendPivotP; // Prev Pivot of Market Trend ...
XBoxZone trendPivotC; // Current Pivot of Market Trend ...
ENUM_X_DIRECTION trendDir; // Trend Direction ...
//
// Breaked Pivots ...
XBoxZone invalidPivots[];
//
// Constructors ...
XCXCAEAPOIDetector(
XCXCAEAHelper *_helper //
)
{
//
helper = _helper;
drawer = new XCPOIDrawer();
barAnalyser = new XCBarAnalyser();
//
Default();
}
//
// De Constructors ...
~XCXCAEAPOIDetector()
{
//
CleanPivots();
//
ZeroMemory(helper);
ZeroMemory(drawer);
ZeroMemory(barAnalyser);
}
//
// Properties ...
//
// Tools ...
//
virtual void Default()
{
//
// COMMON ...
//
maxAllowedPivots = 50;
pivotVerifications = 5;
ticksDividerInPoints = 15;
pivotDetectionLoopbac = 100;
//
// PV ...
//
detectPeakPivots = false;
detectValePivots = false;
//
maxAllowedPVLifetime = 0;
applySwingsOnPVPivots = false;
selectRejectedPVPivots = false;
selectEngulfedPVPivots = false;
selectPVWhichStartByFVG = false;
applySupportAndResistanceOnPVPivots = false;
//
// FVG ...
//
detectFVGBullishPivots = false;
detectFVGBearishPivots = false;
//
selectSameBarFVGs = false;
maxAllowedFVGLifetime = 0;
validateFVGUsingPV = false;
applyPVToFVGBoundary = false;
selectRejectedFVGPivots = false;
selectEngulfedFVGPivots = false;
validateFVGUsingManalyser = false;
applyLastBarToFVGBoundary = false;
selectOnlyFVGWhichHasIndirectionalLastBar = false;
//
// TREND ...
//
detectTrendBullishPivots = false;
detectTrendBearishPivots = false;
//
}
//
void Detect(
int barIndex = 0 //
)
{
//
if (barIndex < 0)
{
barIndex = 0;
}
//
int loopback = pivotDetectionLoopbac;
loopback = NormalizeInt(loopback, 50);
//
int idx = -1;
int count = 0;
bool has = false;
//
int zIDX = 0;
int cIDX = zIDX + 1;
int pIDX = cIDX + 1;
int p2IDX = pIDX + 1;
int p3IDX = p2IDX + 1;
//
newPeakPivotDetected = false;
newValePivotDetected = false;
newFVGBullishPivotDetected = false;
newFVGBearishPivotDetected = false;
newTrendBullishPivotDetected = false;
newTrendBearishPivotDetected = false;
//
int index = barIndex;
int start = index;
int end = index + loopback;
while (start < end)
{
//
// Retrieve Conditions ...
XCAEAConditions conditions;
has = helper.GetConditions(
conditions,
start,
10 //
);
if (!has)
{
conditions.Clean();
continue;
}
//
// Retrieve Bars ...
XOHCL zBar;
XOHCL cBar;
XOHCL pBar;
XOHCL p2Bar;
has = zBar.Init(
conditions.symbol,
conditions.period,
start //
);
has =
has &&
zBar.GetPreviousBar(cBar);
has =
has &&
cBar.GetPreviousBar(pBar);
has =
has &&
pBar.GetPreviousBar(p2Bar);
if (!has)
{
//
zBar.Clean();
cBar.Clean();
pBar.Clean();
p2Bar.Clean();
conditions.Clean();
//
continue;
}
//
// Checking Pivots ...
//
// PV ...
//
// PEAK ...
if (detectPeakPivots)
{
//
newPeakPivotDetected = DetectPeakAndValePivot(
barIndex,
X_DIRECTION_BEARISH,
zBar,
cBar,
pBar,
p2Bar,
conditions //
);
}
//
// VALE ...
if (detectValePivots)
{
//
newValePivotDetected = DetectPeakAndValePivot(
barIndex,
X_DIRECTION_BULLISH,
zBar,
cBar,
pBar,
p2Bar,
conditions //
);
}
//
// FVG ...
//
// Bullish ...
if (detectFVGBullishPivots)
{
//
newFVGBullishPivotDetected = DetectFVGPivot(
barIndex,
X_DIRECTION_BULLISH,
zBar,
cBar,
pBar,
p2Bar,
conditions //
);
}
//
// Bearish ...
if (detectFVGBearishPivots)
{
//
newFVGBearishPivotDetected = DetectFVGPivot(
barIndex,
X_DIRECTION_BEARISH,
zBar,
cBar,
pBar,
p2Bar,
conditions //
);
}
//
// TREND ...
//
// Bullish ...
if (detectTrendBullishPivots)
{
//
newTrendBullishPivotDetected = DetectTrendPivot(
barIndex,
X_DIRECTION_BULLISH,
zBar,
cBar,
pBar,
p2Bar,
conditions //
);
}
//
// Bearish ...
if (detectTrendBearishPivots)
{
//
newTrendBearishPivotDetected = DetectTrendPivot(
barIndex,
X_DIRECTION_BEARISH,
zBar,
cBar,
pBar,
p2Bar,
conditions //
);
}
//
// Others ...
//
start++;
//
zBar.Clean();
cBar.Clean();
pBar.Clean();
p2Bar.Clean();
conditions.Clean();
}
//
SortPivots();
}
//
void Validate(
XBoxZone &unavailables[],
int barIndex = 0 //
)
{
//
// Implement Validation Senarios ...
//
// PV ...
ValidatePeakValePivots(
unavailables,
barIndex //
);
//
// FVG ...
ValidateFVGPivots(
unavailables,
barIndex //
);
//
// TREND ...
ValidateTrendPivots(
unavailables,
barIndex //
);
//
SortPivots();
}
//
int FillPivots(
XBoxZone &pivots[],
ENUM_X_DIRECTION forDir = X_DIRECTION_ALL //
)
{
//
int result = 0;
//
Clean(pivots);
//
if (forDir == X_DIRECTION_NONE)
{
return result;
}
//
int count = 0;
bool has = false;
//
bool canFillBullish =
forDir == X_DIRECTION_ALL ||
forDir == X_DIRECTION_BULLISH;
//
bool canFillBearish =
forDir == X_DIRECTION_ALL ||
forDir == X_DIRECTION_BEARISH;
//
// Bullish ...
if (canFillBullish)
{
//
Copy(
valePivots,
pivots,
false //
);
//
Copy(
fvgBullishPivots,
pivots,
false //
);
//
Copy(
trendBullishPivots,
pivots,
false //
);
}
//
// Bearish ...
if (canFillBearish)
{
//
Copy(
peakPivots,
pivots,
false //
);
//
Copy(
fvgBearishPivots,
pivots,
false //
);
//
Copy(
trendBearishPivots,
pivots,
false //
);
}
//
result = ArraySize(pivots);
//
return result;
}
//
// Pivots ...
//
// INVALID Pivots ...
//
bool HasInvalidPivots()
{
return HasChild(invalidPivots);
}
//
int CountInvalidPivots()
{
return ArraySize(invalidPivots);
}
//
// PV ...
//
int maxAllowedPVLifetime; // Max Allowed PV Life ...
bool applySwingsOnPVPivots; // Apply Swings on PV Pivots ...
bool selectRejectedPVPivots; // Select Rejected PV Pivots ...
bool selectEngulfedPVPivots; // Select Engulfed PV Pivots ...
bool selectPVWhichStartByFVG; // Select PV Pivots Which Starts by FVG ...
bool applySupportAndResistanceOnPVPivots; // Apply Support and Resistance on PV Pivots ...
//
bool DetectPeakAndValePivot(
int barIndex,
ENUM_X_DIRECTION forDir,
XOHCL &zBar,
XOHCL &cBar,
XOHCL &pBar,
XOHCL &p2Bar,
XCAEAConditions &conditions //
)
{
//
bool result = false;
//
// Checking Direction ...
result = HasDirection(forDir);
if (!result)
{
return result;
}
//
bool forBullish = IsBullish(forDir);
bool forBearish = IsBearish(forDir);
//
// Check Allowed ...
result =
forBullish
? detectValePivots
: detectPeakPivots;
if (!result)
{
return result;
}
//
// Validate Args ...
result =
//
barIndex >= 0 &&
zBar.IsValid() &&
cBar.IsValid() &&
pBar.IsValid() &&
p2Bar.IsValid()
//
;
if (!result)
{
return result;
}
//
// Define Requirements ...
//
int zIDX = 0;
int cIDX = zIDX + 1;
int pIDX = cIDX + 1;
int p2IDX = pIDX + 1;
//
datetime cTime = zBar.time;
string symbol = zBar.symbol;
ENUM_TIMEFRAMES period = zBar.period;
double points = GetPoints(symbol);
//
// Reading Conditional Values ...
//
// PEAK ...
double zPeak = conditions.peakBuffer[zIDX];
double cPeak = conditions.peakBuffer[cIDX];
double pPeak = conditions.peakBuffer[pIDX];
double p2Peak = conditions.peakBuffer[p2IDX];
//
// PEAK Golden ...
double zPeakGolden = conditions.peakGoldenBuffer[zIDX];
double cPeakGolden = conditions.peakGoldenBuffer[cIDX];
double pPeakGolden = conditions.peakGoldenBuffer[pIDX];
double p2PeakGolden = conditions.peakGoldenBuffer[p2IDX];
//
// VALE ...
double zVale = conditions.valeBuffer[zIDX];
double cVale = conditions.valeBuffer[cIDX];
double pVale = conditions.valeBuffer[pIDX];
double p2Vale = conditions.valeBuffer[p2IDX];
//
// VALE Golden ...
double zValeGolden = conditions.valeGoldenBuffer[zIDX];
double cValeGolden = conditions.valeGoldenBuffer[cIDX];
double pValeGolden = conditions.valeGoldenBuffer[pIDX];
double p2ValeGolden = conditions.valeGoldenBuffer[p2IDX];
//
// SWING High ..
double zSwingHigh = conditions.swingHighBuffer[zIDX];
double cSwingHigh = conditions.swingHighBuffer[cIDX];
double pSwingHigh = conditions.swingHighBuffer[pIDX];
double p2SwingHigh = conditions.swingHighBuffer[p2IDX];
//
// SWING Low ...
double zSwingLow = conditions.swingLowBuffer[zIDX];
double cSwingLow = conditions.swingLowBuffer[cIDX];
double pSwingLow = conditions.swingLowBuffer[pIDX];
double p2SwingLow = conditions.swingLowBuffer[p2IDX];
//
// SUPPORT ...
double zSupport = conditions.supportBuffer[zIDX];
double cSupport = conditions.supportBuffer[cIDX];
double pSupport = conditions.supportBuffer[pIDX];
double p2Support = conditions.supportBuffer[p2IDX];
//
// RESISTANCE ...
double zResistance = conditions.resistanceBuffer[zIDX];
double cResistance = conditions.resistanceBuffer[cIDX];
double pResistance = conditions.resistanceBuffer[pIDX];
double p2Resistance = conditions.resistanceBuffer[p2IDX];
//
// Detecting Bar Conditions ...
//
ENUM_X_DIRECTION cBarDir;
//
// Rejected ...
bool isCBarRejected = helper
.barAnalyser
.IsRejected(
cBar,
cBarDir,
false, // Force Type ...
false // Force Fibo Pressure ...
);
//
bool isCBarBullishRejected =
forBullish &&
isCBarRejected &&
IsBullish(cBarDir);
bool isCBarBearishRejected =
forBearish &&
isCBarRejected &&
IsBearish(cBarDir);
//
bool isPBarRejected = helper
.barAnalyser
.IsRejected(
pBar,
cBarDir,
false, // Force Type ...
false // Force Fibo Pressure ...
);
bool isPBarBullishRejected =
forBullish &&
isPBarRejected &&
IsBullish(cBarDir);
bool isPBarBearishRejected =
forBearish &&
isPBarRejected &&
IsBearish(cBarDir);
//
bool isBarBullishRejected =
forBullish &&
(isCBarBullishRejected ||
isPBarBullishRejected);
//
bool isBarBearishRejected =
forBearish &&
(isCBarBearishRejected ||
isPBarBearishRejected);
//
// Engulfed ...
bool isCBarEngulfed = helper
.barAnalyser
.IsEngulfed(
cBar,
cBarDir //
);
bool isCBarBullishEngulfed =
forBullish &&
isCBarEngulfed &&
IsBullish(cBarDir);
bool isCBarBearishEngulfed =
forBearish &&
isCBarEngulfed &&
IsBearish(cBarDir);
//
bool isPBarEngulfed = helper
.barAnalyser
.IsEngulfed(
pBar,
cBarDir //
);
bool isPBarBullishEngulfed =
forBullish &&
isPBarEngulfed &&
IsBullish(cBarDir);
bool isPBarBearishEngulfed =
forBearish &&
isPBarEngulfed &&
IsBearish(cBarDir);
//
bool isBarBullishEngulfed =
forBullish &&
(isCBarBullishEngulfed ||
isPBarBullishEngulfed);
//
bool isBarBearishEngulfed =
forBearish &&
(isCBarBearishEngulfed ||
isPBarBearishEngulfed);
//
// Prepare Conditinal Conditions ...
//
// PEAK ...
//
bool isPeakSameLast = cPeak == pPeak;
bool isPeakSameLastPrev = pPeak == p2Peak;
//
if (applySwingsOnPVPivots)
{
//
isPeakSameLast =
isPeakSameLast &&
cSwingHigh == cPeak &&
cSwingHigh == pSwingHigh;
//
isPeakSameLastPrev =
isPeakSameLastPrev &&
pSwingHigh == pPeak &&
pSwingHigh == p2SwingHigh;
}
//
if (applySupportAndResistanceOnPVPivots)
{
//
isPeakSameLast =
isPeakSameLast &&
cResistance == cPeak &&
cResistance == pResistance;
//
isPeakSameLastPrev =
isPeakSameLastPrev &&
pResistance == pPeak &&
pResistance == p2Resistance;
}
//
bool isPeakSwitchedToSameLast = isPeakSameLast &&
!isPeakSameLastPrev;
bool isPeakFinishedFromSameLast = !isPeakSameLast &&
isPeakSameLastPrev;
//
// VALE ...
//
bool isValeSameLast = cVale == pVale;
bool isValeSameLastPrev = pVale == p2Vale;
//
if (applySwingsOnPVPivots)
{
//
isValeSameLast =
isValeSameLast &&
cSwingLow == cVale &&
cSwingLow == pSwingLow;
//
isValeSameLastPrev =
isValeSameLastPrev &&
pSwingLow == pVale &&
pSwingLow == p2SwingLow;
}
//
if (applySupportAndResistanceOnPVPivots)
{
//
isValeSameLast =
isValeSameLast &&
cSupport == cVale &&
cSupport == pSupport;
//
isValeSameLastPrev =
isValeSameLastPrev &&
pSupport == pVale &&
pSupport == p2Support;
}
//
bool isValeSwitchedToSameLast = isValeSameLast &&
!isValeSameLastPrev;
bool isValeFinishedFromSameLast = !isValeSameLast &&
isValeSameLastPrev;
//
// Summarizing Conditions ...
//
result = false;
//
bool hasStartCondition =
//
forBullish
? isValeFinishedFromSameLast
: isPeakFinishedFromSameLast
//
;
//
bool hasContinuationCondition =
//
forBullish
? isValeSameLast
: isPeakSameLast
//
;
//
bool hasEndCondition =
//
forBullish
? isValeSwitchedToSameLast
: isPeakSwitchedToSameLast
//
;
//
// Apply Validations ...
if (hasEndCondition)
{
//
bool hasSelectionType = selectRejectedPVPivots ||
selectEngulfedPVPivots;
//
bool isPVRejected =
forBullish
? (isBarBullishRejected &&
selectRejectedPVPivots)
: (isBarBearishRejected &&
selectRejectedPVPivots);
//
bool isPVEngulfed =
forBullish
? (isBarBullishEngulfed &&
selectEngulfedPVPivots)
: (isBarBearishEngulfed &&
selectEngulfedPVPivots);
//
bool isBarPassed =
!hasSelectionType
? true
: isPVRejected ||
isPVEngulfed;
//
hasEndCondition =
isBarPassed &&
hasEndCondition;
if (!hasEndCondition)
{
//
// VALE ...
if (forBullish)
{
valePivot.Clean();
}
//
// PEAK ...
if (forBearish)
{
peakPivot.Clean();
}
}
}
//
//
//
//
// ReInstance Pivot ...
if (hasStartCondition)
{
//
// VALE ...
if (forBullish)
{
//
valePivot.Clean();
//
valePivot.type = XCA_VALE;
valePivot.symbol = symbol;
valePivot.period = period;
//
valePivot.to = pBar.time;
valePivot.from = pBar.time;
valePivot.value = pVale;
valePivot.reserve = pValeGolden;
}
//
// PEAK ...
if (forBearish)
{
//
peakPivot.Clean();
//
peakPivot.type = XCA_PEAK;
peakPivot.symbol = symbol;
peakPivot.period = period;
//
peakPivot.to = pBar.time;
peakPivot.from = pBar.time;
peakPivot.value = pPeak;
peakPivot.reserve = pPeakGolden;
}
}
//
// Calculate and Fill Pivot Requirements ...
if (hasContinuationCondition)
{
//
// VALE ...
if (forBullish)
{
//
valePivot.from = pBar.time;
//
valePivot.reserve =
valePivot.reserve == 0
? pValeGolden
: MathMin(valePivot.reserve, pValeGolden);
}
//
// PEAK ...
if (forBearish)
{
//
peakPivot.from = pBar.time;
//
peakPivot.reserve =
peakPivot.reserve == 0
? pPeakGolden
: MathMax(peakPivot.reserve, pPeakGolden);
}
}
//
// End up Pivot and Store it ...
if (hasEndCondition)
{
//
// VALE ...
if (forBullish)
{
//
result =
valePivot.IsValid() &&
valePivot.GetAge() >= pivotVerifications;
if (result)
{
//
XBoxZone iBox;
result = valePivot.AsBox(iBox);
if (result)
{
//
newPeakPivotDetected = AddBox(
iBox,
valePivots //
);
}
//
iBox.Clean();
}
//
valePivot.Clean();
}
//
// PEAK ...
if (forBearish)
{
//
result =
peakPivot.IsValid() &&
peakPivot.GetAge() >= pivotVerifications;
if (result)
{
//
XBoxZone iBox;
result = peakPivot.AsBox(iBox);
if (result)
{
//
newPeakPivotDetected = AddBox(
iBox,
peakPivots //
);
}
//
iBox.Clean();
}
//
peakPivot.Clean();
}
}
//
return result;
}
//
void ValidatePeakValePivots(
XBoxZone &unavailables[],
int barIndex = 0 //
)
{
//
bool has = false;
//
bool applyLifetimeValidating = maxAllowedPVLifetime > 0;
//
// PEAK ...
has = HasPeakPivots();
if (has)
{
//
ApplyValidationOnBoxes(
peakPivots,
unavailables,
barIndex //
);
//
if (applyLifetimeValidating)
{
//
ApplyLifeTimeValidationOnBoxes(
peakPivots,
maxAllowedPVLifetime,
barIndex //
);
}
}
//
// VALE ...
has = HasValePivots();
if (has)
{
//
ApplyValidationOnBoxes(
valePivots,
unavailables,
barIndex //
);
//
if (applyLifetimeValidating)
{
//
ApplyLifeTimeValidationOnBoxes(
valePivots,
maxAllowedPVLifetime,
barIndex //
);
}
}
}
//
// PEAK ...
//
XCAPivot peakPivot;
bool detectPeakPivots;
XBoxZone peakPivots[];
bool newPeakPivotDetected;
//
bool HasPeakPivots()
{
return HasChild(peakPivots);
}
//
int CountPeakPivots()
{
return ArraySize(peakPivots);
}
//
// VALE ...
//
XCAPivot valePivot;
bool detectValePivots;
XBoxZone valePivots[];
bool newValePivotDetected;
//
bool HasValePivots()
{
return HasChild(valePivots);
}
//
int CountValePivots()
{
return ArraySize(valePivots);
}
//
// FVG ...
//
bool selectSameBarFVGs; // Select FVGs which has Same Type Bars ...
bool validateFVGUsingPV; // Detect FVG Type Two ( Validating Using PV ) ...
int maxAllowedFVGLifetime; // Max Allowed FVG Life ...
bool applyPVToFVGBoundary; // Apply PV to FVG Boundary ...
bool selectRejectedFVGPivots; // Select Rejected FVG Pivots ...
bool selectEngulfedFVGPivots; // Select Engulfed FVG Pivots ...
bool validateFVGUsingManalyser; // Detect FVG Type One ( Validating Using MAnalyser ) ...
bool applyLastBarToFVGBoundary; // Apply Last Bar to FVG Boundary ...
bool selectOnlyFVGWhichHasIndirectionalLastBar; // Select Only FVGs which has Indirectionsl Last Bar, uses to Order Block ...
//
bool DetectFVGPivot(
int barIndex,
ENUM_X_DIRECTION forDir,
XOHCL &zBar,
XOHCL &cBar,
XOHCL &pBar,
XOHCL &p2Bar,
XCAEAConditions &conditions //
)
{
//
bool result = false;
//
// Checking Direction ...
result = HasDirection(forDir);
if (!result)
{
return result;
}
//
bool forBullish = IsBullish(forDir);
bool forBearish = IsBearish(forDir);
//
// Check Allowed ...
result =
forBullish
? detectFVGBullishPivots
: detectFVGBearishPivots;
if (!result)
{
return result;
}
//
// Validate Args ...
result =
//
barIndex >= 0 &&
zBar.IsValid() &&
cBar.IsValid() &&
pBar.IsValid() &&
p2Bar.IsValid()
//
;
if (!result)
{
return result;
}
//
// Define Requirements ...
//
int zIDX = 0;
int cIDX = zIDX + 1;
int pIDX = cIDX + 1;
int p2IDX = pIDX + 1;
//
datetime cTime = zBar.time;
string symbol = zBar.symbol;
ENUM_TIMEFRAMES period = zBar.period;
double points = GetPoints(symbol);
//
// Reading Conditional Values ...
//
// PEAK ...
double zPeak = conditions.peakBuffer[zIDX];
double cPeak = conditions.peakBuffer[cIDX];
double pPeak = conditions.peakBuffer[pIDX];
double p2Peak = conditions.peakBuffer[p2IDX];
//
// VALE ...
double zVale = conditions.valeBuffer[zIDX];
double cVale = conditions.valeBuffer[cIDX];
double pVale = conditions.valeBuffer[pIDX];
double p2Vale = conditions.valeBuffer[p2IDX];
//
// MANALYSER ...
//
// MAH ...
double zMAH = conditions.mahBuffer[zIDX];
double cMAH = conditions.mahBuffer[cIDX];
double pMAH = conditions.mahBuffer[pIDX];
double p2MAH = conditions.mahBuffer[p2IDX];
//
// MAL ...
double zMAL = conditions.malBuffer[zIDX];
double cMAL = conditions.malBuffer[cIDX];
double pMAL = conditions.malBuffer[pIDX];
double p2MAL = conditions.malBuffer[p2IDX];
//
// MAC ...
double zMAC = conditions.macBuffer[zIDX];
double cMAC = conditions.macBuffer[cIDX];
double pMAC = conditions.macBuffer[pIDX];
double p2MAC = conditions.macBuffer[p2IDX];
//
// Detecting Bar Conditions ...
//
ENUM_X_DIRECTION p2BarDir;
//
// Rejected ...
bool isP2BarRejected = helper
.barAnalyser
.IsRejected(
p2Bar,
p2BarDir,
false, // Force Type ...
true // Force Fibo Pressure ...
);
bool isP2BarBullishRejected =
isP2BarRejected &&
IsBullish(p2BarDir);
bool isP2BarBearishRejected =
isP2BarRejected &&
IsBearish(p2BarDir);
//
// Engulfed ...
bool isP2BarEngulfed = helper
.barAnalyser
.IsEngulfed(
p2Bar,
p2BarDir //
);
bool isP2BarBullishEngulfed =
isP2BarEngulfed &&
IsBullish(p2BarDir);
bool isP2BarBearishEngulfed =
isP2BarEngulfed &&
IsBearish(p2BarDir);
//
// Prepare Conditinal Conditions ...
//
// Default FVG Detection ...
XBoxZone fvgBox;
bool isFVG = barAnalyser.IsFVG(
cBar,
fvgBox //
);
bool isBullishFVG =
isFVG &&
forBullish &&
fvgBox.IsBullish();
bool isBearishFVG =
isFVG &&
forBearish &&
fvgBox.IsBearish();
//
// Summarizing Conditions ...
//
result = false;
//
bool hasStartCondition = false;
bool hasContinuationCondition = false;
bool hasEndCondition = isBullishFVG ||
isBearishFVG;
//
// Apply all Filtering ...
if (hasEndCondition)
{
//
XOHCL p3Bar;
p2Bar.GetPreviousBar(p3Bar);
//
bool isFVGValid = true;
//
// Validate FVG Using Manalyser ...
bool isManalyserValid = false;
if (validateFVGUsingManalyser)
{
//
isManalyserValid =
hasEndCondition &&
(forBullish
? fvgBox.upper <= cMAL
: fvgBox.lower >= cMAH);
}
//
// Validate FVG Using PV ...
bool isPVValid = false;
if (validateFVGUsingPV)
{
//
isPVValid =
hasEndCondition &&
(forBullish
? (p2Peak < pPeak ||
pPeak < cPeak)
: (p2Vale > pVale ||
pVale > cVale));
}
//
// Select Pure FVG ...
bool isPureFVGValid =
!validateFVGUsingPV &&
!validateFVGUsingManalyser;
//
// Summarise Validation ...
isFVGValid =
isPVValid ||
isPureFVGValid ||
isManalyserValid;
//
bool isFVGBarPassed = false;
//
// Select Same Bars FVGs ...
bool isFVGHasSameBar = true;
if (selectSameBarFVGs)
{
//
isFVGHasSameBar =
forBullish
? (cBar.IsBullish() &&
pBar.IsBullish() &&
p2Bar.IsBullish())
: (cBar.IsBearish() &&
pBar.IsBearish() &&
p2Bar.IsBearish());
isFVGBarPassed =
isFVGBarPassed ||
isFVGHasSameBar;
}
//
// Select Rejected FVG ...
bool isFVGRejected = true;
if (selectRejectedFVGPivots)
{
//
isFVGRejected =
(forBullish
? isP2BarBullishRejected
: isP2BarBearishRejected);
isFVGBarPassed =
isFVGBarPassed ||
isFVGRejected;
}
//
// Select Engulfed FVG ...
bool isFVGEngulfed = true;
if (selectEngulfedFVGPivots)
{
//
isFVGEngulfed =
(forBullish
? isP2BarBullishEngulfed
: isP2BarBearishEngulfed);
isFVGBarPassed =
isFVGBarPassed ||
isFVGEngulfed;
}
//
// Select Only FVGs Which Has Indirectional Last Bar ...
bool isFVGHasIndirectionalStart = true;
if (selectOnlyFVGWhichHasIndirectionalLastBar)
{
//
isFVGHasIndirectionalStart =
p3Bar.IsValid() &&
(forBullish
? p3Bar.IsBearish()
: p3Bar.IsBullish());
isFVGBarPassed =
isFVGBarPassed ||
isFVGHasIndirectionalStart;
}
//
// Summarise Bar Pass ...
isFVGBarPassed =
(selectSameBarFVGs ||
selectRejectedFVGPivots ||
selectEngulfedFVGPivots ||
selectOnlyFVGWhichHasIndirectionalLastBar)
? isFVGBarPassed
: true;
//
hasEndCondition = isFVGValid &&
isFVGBarPassed;
//
// Apply Boundary ...
if (hasEndCondition)
{
//
double iValue =
forBullish
? fvgBox.upper
: fvgBox.lower;
//
if (applyPVToFVGBoundary)
{
//
fvgBox.upper =
forBullish
? fvgBox.upper
: cPeak;
//
fvgBox.lower =
forBullish
? cVale
: fvgBox.lower;
}
//
if (applyLastBarToFVGBoundary)
{
//
fvgBox.lower = MathMin(p3Bar.low, fvgBox.lower);
fvgBox.upper = MathMax(p3Bar.high, fvgBox.upper);
}
}
//
p3Bar.Clean();
}
//
// ReInstance Pivot ...
if (hasStartCondition)
{
//
}
//
// Calculate and Fill Pivot Requirements ...
if (hasContinuationCondition)
{
//
}
//
// End up Pivot and Store it ...
if (hasEndCondition)
{
//
XBoxZone iBox;
XCAPivot iPivot;
//
iPivot.to = fvgBox.to;
iPivot.from = fvgBox.from;
iPivot.symbol = fvgBox.symbol;
iPivot.period = fvgBox.period;
iPivot.type = forBullish
? XCA_FVG_BULL
: XCA_FVG_BEAR;
iPivot.value = forBullish
? fvgBox.lower
: fvgBox.upper;
iPivot.reserve = forBullish
? fvgBox.upper
: fvgBox.lower;
//
result = iPivot.IsValid();
if (result)
{
//
result = iPivot.AsBox(iBox);
if (result)
{
//
if (forBullish)
{
//
result = AddBox(
iBox,
fvgBullishPivots //
);
}
else
{
//
result = AddBox(
iBox,
fvgBearishPivots //
);
}
}
}
//
iBox.Clean();
iPivot.Clean();
}
//
return result;
}
//
void ValidateFVGPivots(
XBoxZone &unavailables[],
int barIndex = 0 //
)
{
//
bool has = false;
//
bool applyLifetimeValidating = maxAllowedFVGLifetime > 0;
//
// Bullish ...
has = HasFVGBullishPivots();
if (has)
{
//
ApplyValidationOnBoxes(
fvgBullishPivots,
unavailables,
barIndex //
);
//
if (applyLifetimeValidating)
{
//
ApplyLifeTimeValidationOnBoxes(
fvgBullishPivots,
maxAllowedFVGLifetime,
barIndex //
);
}
}
//
// Bearish ...
has = HasFVGBearishPivots();
if (has)
{
//
ApplyValidationOnBoxes(
fvgBearishPivots,
unavailables,
barIndex //
);
//
if (applyLifetimeValidating)
{
//
ApplyLifeTimeValidationOnBoxes(
fvgBearishPivots,
maxAllowedFVGLifetime,
barIndex //
);
}
}
}
//
// FVG Bullish Pivots ...
//
bool detectFVGBullishPivots;
XBoxZone fvgBullishPivots[];
bool newFVGBullishPivotDetected;
//
bool HasFVGBullishPivots()
{
return HasChild(fvgBullishPivots);
}
//
int CountFVGBullishPivots()
{
return ArraySize(fvgBullishPivots);
}
//
// FVG Bearish Pivots ...
//
bool detectFVGBearishPivots;
XBoxZone fvgBearishPivots[];
bool newFVGBearishPivotDetected;
//
bool HasFVGBearishPivots()
{
return HasChild(fvgBearishPivots);
}
//
int CountFVGBearishPivots()
{
return ArraySize(fvgBearishPivots);
}
//
// TREND ...
//
int maxAllowedTrendLifetime; // Max Allowed Trend Life ...
//
bool DetectTrendPivot(
int barIndex,
ENUM_X_DIRECTION forDir,
XOHCL &zBar,
XOHCL &cBar,
XOHCL &pBar,
XOHCL &p2Bar,
XCAEAConditions &conditions //
)
{
//
bool result = false;
//
// Checking Direction ...
result = HasDirection(forDir);
if (!result)
{
return result;
}
//
bool forBullish = IsBullish(forDir);
bool forBearish = IsBearish(forDir);
//
// Check Allowed ...
result =
forBullish
? detectTrendBullishPivots
: detectTrendBearishPivots;
if (!result)
{
return result;
}
//
// Validate Args ...
result =
//
barIndex >= 0 &&
zBar.IsValid() &&
cBar.IsValid() &&
pBar.IsValid() &&
p2Bar.IsValid()
//
;
if (!result)
{
return result;
}
//
// Define Requirements ...
//
int zIDX = 0;
int cIDX = zIDX + 1;
int pIDX = cIDX + 1;
int p2IDX = pIDX + 1;
//
datetime cTime = zBar.time;
string symbol = zBar.symbol;
ENUM_TIMEFRAMES period = zBar.period;
double points = GetPoints(symbol);
//
// Reading Conditional Values ...
//
// TREND ...
double zTrend = conditions.trendBuffer[zIDX];
double cTrend = conditions.trendBuffer[cIDX];
double pTrend = conditions.trendBuffer[pIDX];
double p2Trend = conditions.trendBuffer[p2IDX];
//
// TREND State ...
double zTrendState = conditions.trendStateBuffer[zIDX];
double cTrendState = conditions.trendStateBuffer[cIDX];
double pTrendState = conditions.trendStateBuffer[pIDX];
double p2TrendState = conditions.trendStateBuffer[p2IDX];
//
// Prepare Conditinal Conditions ...
//
// Bullish ...
//
bool isTrendBullish =
cTrendState > 0;
bool isTrendBullishPrev =
pTrendState > 0;
//
bool isTrendSwitchedToBullish = isTrendBullish &&
!isTrendBullishPrev;
bool isTrendFinishedFromBullish = !isTrendBullish &&
isTrendBullishPrev;
//
// Bearish ...
//
bool isTrendBearish =
cTrendState < 0;
bool isTrendBearishPrev =
pTrendState < 0;
//
bool isTrendSwitchedToBearish = isTrendBearish &&
!isTrendBearishPrev;
bool isTrendFinishedFromBearish = !isTrendBearish &&
isTrendBearishPrev;
//
// Summarizing Conditions ...
//
result = false;
//
bool hasStartCondition =
forBullish
? isTrendFinishedFromBullish
: isTrendFinishedFromBearish;
bool hasContinuationCondition =
forBullish
? isTrendBullish
: isTrendBearish;
bool hasEndCondition =
forBullish
? isTrendSwitchedToBullish
: isTrendSwitchedToBearish;
//
// ReInstance Pivot ...
if (hasStartCondition)
{
//
// Bullish ...
if (forBullish)
{
//
trendBullishPivot.Clean();
//
trendBullishPivot.symbol = symbol;
trendBullishPivot.period = period;
trendBullishPivot.type = XCA_TREND_BULL;
//
trendBullishPivot.to = pBar.time;
trendBullishPivot.from = pBar.time;
trendBullishPivot.value = pTrend;
trendBullishPivot.reserve = pTrend;
}
//
// Bearish ...
if (forBearish)
{
//
trendBearishPivot.Clean();
//
trendBearishPivot.symbol = symbol;
trendBearishPivot.period = period;
trendBearishPivot.type = XCA_TREND_BEAR;
//
trendBearishPivot.to = pBar.time;
trendBearishPivot.from = pBar.time;
trendBearishPivot.value = pTrend;
trendBearishPivot.reserve = pTrend;
}
}
//
// Calculate and Fill Pivot Requirements ...
if (hasContinuationCondition)
{
//
// Bullish ...
if (forBullish)
{
//
trendBullishPivot.from = pBar.time;
//
Add(
pTrend,
trendBullishPivot.values //
);
Add(
pTrend,
trendBullishPivot.values //
);
}
//
// Bearish ...
if (forBearish)
{
//
trendBearishPivot.from = pBar.time;
//
Add(
pTrend,
trendBearishPivot.values //
);
Add(
pTrend,
trendBearishPivot.values //
);
}
}
//
// End up Pivot and Store it ...
if (hasEndCondition)
{
//
// Bullish ...
if (forBullish)
{
//
// Update Values ...
trendBullishPivot.value = GetMin(trendBullishPivot.values);
trendBullishPivot.reserve = GetMax(trendBullishPivot.values);
//
result =
trendBullishPivot.IsValid() &&
trendBullishPivot.GetAge() >= pivotVerifications;
if (result)
{
//
XBoxZone iBox;
result = trendBullishPivot.AsBox(iBox);
if (result)
{
//
newTrendBullishPivotDetected = AddBox(
iBox,
trendBullishPivots //
);
}
//
iBox.Clean();
}
//
trendBullishPivot.Clean();
}
//
// Bearish ...
if (forBearish)
{
//
// Update Values ...
trendBearishPivot.value = GetMax(trendBearishPivot.values);
trendBearishPivot.reserve = GetMin(trendBearishPivot.values);
//
result =
trendBearishPivot.IsValid() &&
trendBearishPivot.GetAge() >= pivotVerifications;
if (result)
{
//
XBoxZone iBox;
result = trendBearishPivot.AsBox(iBox);
if (result)
{
//
newTrendBearishPivotDetected = AddBox(
iBox,
trendBearishPivots //
);
}
//
iBox.Clean();
}
//
trendBearishPivot.Clean();
}
}
//
return result;
}
//
void ValidateTrendPivots(
XBoxZone &unavailables[],
int barIndex = 0 //
)
{
//
bool has = false;
//
bool applyLifetimeValidating = maxAllowedTrendLifetime > 0;
//
// Bullish ...
has = HasTrendBullishPivots();
if (has)
{
//
ApplyValidationOnBoxes(
trendBullishPivots,
unavailables,
barIndex //
);
//
if (applyLifetimeValidating)
{
//
ApplyLifeTimeValidationOnBoxes(
trendBullishPivots,
maxAllowedTrendLifetime,
barIndex //
);
}
}
//
// Bearish ...
has = HasTrendBearishPivots();
if (has)
{
//
ApplyValidationOnBoxes(
trendBearishPivots,
unavailables,
barIndex //
);
//
if (applyLifetimeValidating)
{
//
ApplyLifeTimeValidationOnBoxes(
trendBearishPivots,
maxAllowedTrendLifetime,
barIndex //
);
}
}
}
//
// Bullish ...
//
XCAPivot trendBullishPivot;
XBoxZone trendBullishPivots[];
bool detectTrendBullishPivots;
bool newTrendBullishPivotDetected;
//
bool HasTrendBullishPivots()
{
return HasChild(trendBullishPivots);
}
//
int CountTrendBullishPivots()
{
return ArraySize(trendBullishPivots);
}
//
// Bearish ...
//
XCAPivot trendBearishPivot;
XBoxZone trendBearishPivots[];
bool detectTrendBearishPivots;
bool newTrendBearishPivotDetected;
//
bool HasTrendBearishPivots()
{
return HasChild(trendBearishPivots);
}
//
int CountTrendBearishPivots()
{
return ArraySize(trendBearishPivots);
}
//
// Protected ...
protected:
//
// Props ...
//
// Prrivate ...
private:
//
// Props ...
//
XCPOIDrawer *drawer;
XCXCAEAHelper *helper;
XCBarAnalyser *barAnalyser;
//
bool AddBox(
XBoxZone &box,
XBoxZone &boxes[] //
)
{
//
bool result = false;
//
result = box.IsValid();
if (!result)
{
return result;
}
//
int idx = -1;
bool isExists = FindBoxIndex(
idx,
box,
boxes //
);
result = !isExists;
if (!result)
{
return result;
}
//
int before = ArraySize(boxes);
//
AddRef(
box,
boxes //
);
//
int after = ArraySize(boxes);
//
result = after > before;
//
return result;
}
//
bool ValidateBox(
XBoxZone &box,
XBoxZone &unavailables[],
int barIndex = 0 //
)
{
//
bool result = false;
//
// Normalize Bar Index ...
barIndex = NormalizeInt(barIndex, 0);
//
// Ceck Input Box is Valid ...
result = box.IsValid();
if (!result)
{
return result;
}
//
// Check Input Box is Available ...
bool canCheckUnAvailableBoxes = HasChild(unavailables);
if (canCheckUnAvailableBoxes)
{
//
int idx = -1;
bool isUnAvailable = FindBoxIndex(
idx,
box,
unavailables //
);
result = !isUnAvailable;
if (!result)
{
return result;
}
}
//
// Check Input Box is Breaked or not ...
//
// Check Bar Index must after Box To Index ...
int toIDX = box.ToIndex();
int fromIDX = box.FromIndex();
result = toIDX > barIndex &&
fromIDX > barIndex &&
fromIDX > toIDX;
if (!result)
{
return result;
}
//
// Detect Box Applied Boundary Price ...
// For Checking Break of Box ...
bool isBullish = box.IsBullish();
double boundary =
isBullish
? box.lower
: box.upper;
//
// for validating Box Break we have to wait At Least 3 Bars Close
// out of Box Boundary ...
int barsLength = 3;
//
// Calculate Start Checking Bar Index ...
int startCheckBreaktionBarIndex = toIDX - barsLength;
bool isBarIndexValid = startCheckBreaktionBarIndex > 0 &&
barIndex < startCheckBreaktionBarIndex;
result = isBarIndexValid;
if (!result)
{
//
// Assume Box is Valid if Bar Index not Valid for Checking ...
result = true;
return result;
}
//
// Try to Check Box Validation if Everything is OK ...
XOHCL cBar;
XOHCL pBar;
XOHCL p2Bar;
bool isValid = false;
bool isBreaked = false;
for (int i = barIndex; i < startCheckBreaktionBarIndex; i++)
{
//
// Initialize Bars ...
isValid = cBar.Init(
box.symbol,
box.period,
i + 1 //
);
isValid =
result &&
cBar.GetPreviousBar(pBar);
isValid =
result &&
pBar.GetPreviousBar(p2Bar);
if (!isValid)
{
//
cBar.Clean();
pBar.Clean();
p2Bar.Clean();
//
result = false;
//
break;
}
//
// Preparing Conditions ...
//
bool isBullishBreaked =
isBullish &&
cBar.close < boundary &&
pBar.close < boundary &&
p2Bar.close < boundary;
//
bool isBearishBreaked =
!isBullish &&
cBar.close > boundary &&
pBar.close > boundary &&
p2Bar.close > boundary;
//
// Calculate Result ...
isBreaked = isBullishBreaked ||
isBearishBreaked;
if (isBreaked)
{
//
cBar.Clean();
pBar.Clean();
p2Bar.Clean();
//
result = false;
//
break;
}
//
cBar.Clean();
pBar.Clean();
p2Bar.Clean();
}
//
result = isValid &&
!isBreaked;
if (!result)
{
//
int idx = -1;
bool isExists = FindBoxIndex(
idx,
box,
invalidPivots //
);
if (!isExists)
{
//
AddRef(
box,
invalidPivots //
);
}
}
//
// Cleanup Resource ...
//
cBar.Clean();
pBar.Clean();
p2Bar.Clean();
//
return result;
}
//
void CleanPivots()
{
//
Clean(invalidPivots);
//
peakPivot.Clean();
valePivot.Clean();
trendBullishPivot.Clean();
trendBearishPivot.Clean();
//
Clean(peakPivots);
Clean(valePivots);
//
Clean(fvgBullishPivots);
Clean(fvgBearishPivots);
//
Clean(trendBullishPivots);
Clean(trendBearishPivots);
}
//
void SortPivots()
{
//
bool has = false;
//
// Invalid Pivots ...
has = HasInvalidPivots();
if (has)
{
ApplySortOnBoxes(invalidPivots);
}
//
// PV ...
//
// PEAK ...
has = HasPeakPivots();
if (has)
{
ApplySortOnBoxes(peakPivots);
}
//
// VALE ...
has = HasValePivots();
if (has)
{
ApplySortOnBoxes(valePivots);
}
//
// FVG ...
//
// Bullish ...
has = HasFVGBullishPivots();
if (has)
{
ApplySortOnBoxes(fvgBullishPivots);
}
//
// Bearish ...
has = HasFVGBearishPivots();
if (has)
{
ApplySortOnBoxes(fvgBearishPivots);
}
//
// TREND ...
//
// Bullish ...
has = HasTrendBullishPivots();
if (has)
{
ApplySortOnBoxes(trendBullishPivots);
}
//
// Bearish ...
has = HasTrendBearishPivots();
if (has)
{
ApplySortOnBoxes(trendBearishPivots);
}
}
//
void ApplySortOnBoxes(
XBoxZone &items[] //
)
{
//
int idx = -1;
bool has = false;
//
has = HasChild(items);
if (!has)
{
return;
}
//
XBoxZone tmp[];
Copy(
items,
tmp //
);
Clean(items);
//
while (HasChild(tmp))
{
//
idx = GetOldest(tmp);
has = IsValidIndex(idx);
if (!has)
{
break;
}
//
XBoxZone iBox = tmp[idx];
ArrayRemove(
tmp,
idx,
1 //
);
//
AddRef(
iBox,
items //
);
}
//
CleanupArray(
items,
maxAllowedPivots //
);
//
Clean(tmp);
}
//
void ApplyValidationOnBoxes(
XBoxZone &items[],
XBoxZone &unavailables[],
int barIndex = 0 //
)
{
//
bool has = false;
//
has = HasChild(items);
if (!has)
{
return;
}
//
XBoxZone tmp[];
Copy(
items,
tmp //
);
Clean(items);
while (HasChild(tmp))
{
//
XBoxZone iBox = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
has = ValidateBox(
iBox,
unavailables,
barIndex //
);
if (has)
{
//
AddRef(
iBox,
items //
);
}
//
iBox.Clean();
//
}
//
Clean(tmp);
}
//
void ApplyLifeTimeValidationOnBoxes(
XBoxZone &items[],
int maxAllowedAge = 0,
int barIndex = 0 //
)
{
//
bool has = false;
//
barIndex = NormalizeInt(barIndex, 0);
//
has =
maxAllowedAge > 0 &&
HasChild(items);
if (!has)
{
return;
}
//
datetime cTime = GetBarTime(
helper.GetSymbol(),
helper.GetPeriod(),
barIndex //
);
//
XBoxZone tmp[];
Copy(
items,
tmp //
);
Clean(items);
//
while (HasChild(tmp))
{
//
XBoxZone iBox = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
datetime defTo = iBox.to;
iBox.to = cTime;
//
int iAge = iBox.GetAge();
has = iAge <= maxAllowedAge;
iBox.to = defTo;
if (has)
{
//
AddRef(
iBox,
items //
);
}
else
{
//
int idx = -1;
bool isExists = FindBoxIndex(
idx,
iBox,
invalidPivots //
);
if (!isExists)
{
//
AddRef(
iBox,
invalidPivots //
);
}
}
//
iBox.Clean();
}
//
Clean(tmp);
}
//
};
//