Files
MQL5Data/XCATBEA/Classes/xcatbea.x-poi.detector.class.mq5
T
2025-06-20 17:17:11 +03:30

2678 lines
54 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class
// -------------------------------------------------
// Name: XCXCAYBEAPOIDetector ...
// Description: Class for XCATBEA 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 XCATBEA POI Detector"
#property strict
//
// Imports ...
#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5"
#include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5"
#include "../../Libraries/x-saherelm.x-poi.extensions.lib.mq5"
//
// Definitions ...
//
enum ENUM_XCATB_PIVOTS
{
XCATB_NONE, // None
XCATB_PEAK, // Peak
XCATB_VALE, // Vale
XCATB_BULLISH_MT, // MTBull
XCATB_BEARISH_MT, // MTBear
XCATB_BULLISH_OB, // OBBull
XCATB_BEARISH_OB, // OBBear
};
//
bool IsValid(ENUM_XCATB_PIVOTS value)
{
//
bool result = false;
//
result = value != XCATB_NONE;
//
return result;
}
//
string ToString(ENUM_XCATB_PIVOTS value)
{
//
string result = NULL;
//
result = EnumToString(value);
//
return result;
}
//
ENUM_X_DIRECTION GetDirection(ENUM_XCATB_PIVOTS value)
{
//
ENUM_X_DIRECTION result = X_DIRECTION_NONE;
//
switch (value)
{
//
case XCATB_VALE:
case XCATB_BULLISH_MT:
case XCATB_BULLISH_OB:
result = X_DIRECTION_BULLISH;
break;
//
case XCATB_PEAK:
case XCATB_BEARISH_MT:
case XCATB_BEARISH_OB:
result = X_DIRECTION_BEARISH;
break;
}
//
return result;
}
//
string GetBoxType(ENUM_XCATB_PIVOTS value)
{
//
string result = NULL;
//
switch (value)
{
//
case XCATB_VALE:
case XCATB_PEAK:
result = ToString(value);
break;
//
case XCATB_BULLISH_MT:
case XCATB_BEARISH_MT:
result = "XMT";
break;
//
case XCATB_BULLISH_OB:
case XCATB_BEARISH_OB:
result = "XOB";
break;
}
//
return result;
}
//
ENUM_XCATB_PIVOTS GetPivotType(XBoxZone &value)
{
//
ENUM_XCATB_PIVOTS result = XCATB_NONE;
//
bool has = value.IsValid();
if (!has)
{
return result;
}
//
bool isPeak = value.type == GetBoxType(XCATB_PEAK) &&
value.dir == GetDirection(XCATB_PEAK);
bool isVale = value.type == GetBoxType(XCATB_VALE) &&
value.dir == GetDirection(XCATB_VALE);
bool isBullishMT = value.type == GetBoxType(XCATB_BULLISH_MT) &&
value.dir == GetDirection(XCATB_BULLISH_MT);
bool isBearishMT = value.type == GetBoxType(XCATB_BEARISH_MT) &&
value.dir == GetDirection(XCATB_BEARISH_MT);
bool isBullishOB = value.type == GetBoxType(XCATB_BULLISH_OB) &&
value.dir == GetDirection(XCATB_BULLISH_OB);
bool isBearishOB = value.type == GetBoxType(XCATB_BEARISH_OB) &&
value.dir == GetDirection(XCATB_BEARISH_OB);
//
if (isPeak)
{
result = XCATB_PEAK;
}
else if (isVale)
{
result = XCATB_VALE;
}
else if (isBullishMT)
{
result = XCATB_BULLISH_MT;
}
else if (isBearishMT)
{
result = XCATB_BEARISH_MT;
}
else if (isBullishOB)
{
result = XCATB_BULLISH_OB;
}
else if (isBearishOB)
{
result = XCATB_BEARISH_OB;
}
//
return result;
}
//
struct XCATBPivot
{
//
// Props ...
datetime to;
double value;
string symbol;
datetime from;
double reserve;
ENUM_XCATB_PIVOTS type;
ENUM_TIMEFRAMES period;
//
double values[];
//
// Constructor ...
XCATBPivot()
{
Clean();
}
//
// Tools ...
/**
* Cleanup ...
*/
void Clean()
{
//
value = 0;
to = NULL;
reserve = 0;
from = NULL;
symbol = NULL;
period = NULL;
type = XCATB_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: XCATBPivot ...
*
* @return ( bool )
*/
bool IsSameAs(XCATBPivot &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 XCXCATBEAPOIDetector : public XCBase
{
//
// Public ...
public:
//
// Props ...
int maxAllowedPivots; // Max Allowed Holding Pibots ...
int pivotVerifications; // Pivots Verifications ...
int pivotDetectionLoopbac; // Pivots Detection Loopback ...
//
// Breaked Pivots ...
XBoxZone invalidPivots[];
//
// Constructors ...
XCXCATBEAPOIDetector(
XCX121XCatbHelper *_helper //
)
{
//
helper = _helper;
barAnalyser = new XCBarAnalyser();
//
Default();
}
//
// De Constructors ...
~XCXCATBEAPOIDetector()
{
//
CleanPivots();
//
ZeroMemory(helper);
//
delete barAnalyser;
ZeroMemory(barAnalyser);
}
//
// Properties ...
//
// Tools ...
//
virtual void Default()
{
//
// COMMON ...
//
maxAllowedPivots = 50;
pivotVerifications = 5;
pivotDetectionLoopbac = 100;
//
// PV ...
//
maxAllowedPVLifetime = 0;
selectRejectedPVPivots = false;
selectEngulfedPVPivots = false;
//
detectPeakPivots = false;
detectValePivots = false;
//
detectMTBullishPivots = false;
detectMTBearishPivots = false;
//
detectOBBullishPivots = false;
detectOBBearishPivots = false;
}
//
void Detect(
int barIndex = 0 //
)
{
//
barIndex = NormalizeInt(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;
newMTBullishPivotDetected = false;
newMTBearishPivotDetected = false;
newOBBullishPivotDetected = false;
newOBBearishPivotDetected = false;
//
int index = barIndex;
int start = index;
int end = index + loopback;
while (start < end)
{
//
// Retrieve Conditions ...
X121XCatbConditions 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 //
);
}
//
// MT ...
//
// Bullish ...
if (detectMTBullishPivots)
{
//
newMTBullishPivotDetected = DetectMTPivot(
barIndex,
X_DIRECTION_BULLISH,
zBar,
cBar,
pBar,
p2Bar,
conditions //
);
}
//
// Bearish ...
if (detectMTBearishPivots)
{
//
newMTBearishPivotDetected = DetectMTPivot(
barIndex,
X_DIRECTION_BEARISH,
zBar,
cBar,
pBar,
p2Bar,
conditions //
);
}
//
// OB ...
//
// Bullish ...
if (detectOBBullishPivots)
{
//
newOBBullishPivotDetected = DetectOBPivot(
barIndex,
X_DIRECTION_BULLISH,
zBar,
cBar,
pBar,
p2Bar,
conditions //
);
}
//
// Bearish ...
if (detectOBBearishPivots)
{
//
newOBBearishPivotDetected = DetectOBPivot(
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 //
);
//
// MT ...
ValidateMTPivots(
unavailables,
barIndex //
);
//
// OB ...
ValidateOBPivots(
unavailables,
barIndex //
);
//
SortPivots();
}
//
void CleanPivots()
{
//
Clean(invalidPivots);
//
peakPivot.Clean();
valePivot.Clean();
//
Clean(peakPivots);
Clean(valePivots);
//
Clean(mtBullishPivots);
Clean(mtBearishPivots);
//
Clean(obBullishPivots);
Clean(obBearishPivots);
}
//
// Pivots ...
//
// INVALID Pivots ...
//
bool HasInvalidPivots()
{
return HasChild(invalidPivots);
}
//
int CountInvalidPivots()
{
return ArraySize(invalidPivots);
}
//
// PV ...
//
int maxAllowedPVLifetime; // Max Allowed PV Life ...
bool selectRejectedPVPivots; // Select Rejected PV Pivots ...
bool selectEngulfedPVPivots; // Select Engulfed PV Pivots ...
//
bool DetectPeakAndValePivot(
int barIndex,
ENUM_X_DIRECTION forDir,
XOHCL &zBar,
XOHCL &cBar,
XOHCL &pBar,
XOHCL &p2Bar,
X121XCatbConditions &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];
//
// Detecting Bar Conditions ...
//
ENUM_X_DIRECTION cBarDir;
//
// Rejected ...
bool isCBarRejected = 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 = 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 = barAnalyser
.IsEngulfed(
cBar,
cBarDir //
);
bool isCBarBullishEngulfed =
forBullish &&
isCBarEngulfed &&
IsBullish(cBarDir);
bool isCBarBearishEngulfed =
forBearish &&
isCBarEngulfed &&
IsBearish(cBarDir);
//
bool isPBarEngulfed = 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;
//
bool isPeakSwitchedToSameLast = isPeakSameLast &&
!isPeakSameLastPrev;
bool isPeakFinishedFromSameLast = !isPeakSameLast &&
isPeakSameLastPrev;
//
// VALE ...
//
bool isValeSameLast = cVale == pVale;
bool isValeSameLastPrev = pVale == p2Vale;
//
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 = XCATB_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 = XCATB_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)
{
//
newValePivotDetected = 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 ...
//
XCATBPivot peakPivot;
bool detectPeakPivots;
XBoxZone peakPivots[];
bool newPeakPivotDetected;
//
bool HasPeakPivots()
{
return HasChild(peakPivots);
}
//
int CountPeakPivots()
{
return ArraySize(peakPivots);
}
//
int FillPeakPivots(XBoxZone &pivots[])
{
//
int result = 0;
//
Clean(pivots);
//
if (!HasPeakPivots())
{
return result;
}
//
int count = CountPeakPivots();
for (int i = 0; i < count; i++)
{
//
XBoxZone iPivot = peakPivots[i];
//
AddRef(
iPivot,
pivots //
);
//
iPivot.Clean();
}
//
result = ArraySize(pivots);
//
return result;
}
//
// VALE ...
//
XCATBPivot valePivot;
bool detectValePivots;
XBoxZone valePivots[];
bool newValePivotDetected;
//
bool HasValePivots()
{
return HasChild(valePivots);
}
//
int CountValePivots()
{
return ArraySize(valePivots);
}
//
int FillValePivots(XBoxZone &pivots[])
{
//
int result = 0;
//
Clean(pivots);
//
if (!HasValePivots())
{
return result;
}
//
int count = CountValePivots();
for (int i = 0; i < count; i++)
{
//
XBoxZone iPivot = valePivots[i];
//
AddRef(
iPivot,
pivots //
);
//
iPivot.Clean();
}
//
result = ArraySize(pivots);
//
return result;
}
//
// MITIGATIONBLOCK ...
//
int maxAllowedMTLifetime; // Max Allowed MT Life ...
//
bool DetectMTPivot(
int barIndex,
ENUM_X_DIRECTION forDir,
XOHCL &zBar,
XOHCL &cBar,
XOHCL &pBar,
XOHCL &p2Bar,
X121XCatbConditions &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
? detectMTBullishPivots
: detectMTBearishPivots;
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);
//
// Detecting Bar Conditions ...
//
ENUM_X_DIRECTION cBarDir;
//
// Rejected ...
bool isCBarRejected = barAnalyser
.IsRejected(
cBar,
cBarDir,
false, // Force Type ...
true // Force Fibo Pressure ...
);
//
bool isCBarBullishRejected =
forBullish &&
isCBarRejected &&
IsBullish(cBarDir);
bool isCBarBearishRejected =
forBearish &&
isCBarRejected &&
IsBearish(cBarDir);
//
// Prepare Conditinal Conditions ...
//
// Summarizing Conditions ...
//
result = false;
//
bool hasEndCondition =
//
forBullish
? isCBarBullishRejected
: isCBarBearishRejected
//
;
//
// End up Pivot and Store it ...
if (hasEndCondition)
{
//
XBoxZone iPivot;
iPivot.to = zBar.time;
iPivot.from = cBar.time;
iPivot.symbol = cBar.symbol;
iPivot.period = cBar.period;
//
// Bullish ...
if (forBullish)
{
//
iPivot.lower = cBar.low;
iPivot.upper = cBar.GetDown();
iPivot.dir = X_DIRECTION_BULLISH;
iPivot.type = GetBoxType(XCATB_BULLISH_MT);
//
result = iPivot.IsValid();
if (result)
{
//
newMTBullishPivotDetected = AddBox(
iPivot,
mtBullishPivots //
);
}
}
//
// Bearish ...
if (forBearish)
{
//
iPivot.upper = cBar.high;
iPivot.lower = cBar.GetUp();
iPivot.dir = X_DIRECTION_BEARISH;
iPivot.type = GetBoxType(XCATB_BEARISH_MT);
//
result = iPivot.IsValid();
if (result)
{
//
newMTBearishPivotDetected = AddBox(
iPivot,
mtBearishPivots //
);
}
}
}
//
return result;
}
//
void ValidateMTPivots(
XBoxZone &unavailables[],
int barIndex = 0 //
)
{
//
bool has = false;
//
bool applyLifetimeValidating = maxAllowedMTLifetime > 0;
//
// Bullish ...
has = HasMTBullishPivots();
if (has)
{
//
ApplyValidationOnBoxes(
mtBullishPivots,
unavailables,
barIndex //
);
//
if (applyLifetimeValidating)
{
//
ApplyLifeTimeValidationOnBoxes(
mtBullishPivots,
maxAllowedMTLifetime,
barIndex //
);
}
}
//
// Bearish ...
has = HasMTBearishPivots();
if (has)
{
//
ApplyValidationOnBoxes(
mtBearishPivots,
unavailables,
barIndex //
);
//
if (applyLifetimeValidating)
{
//
ApplyLifeTimeValidationOnBoxes(
mtBearishPivots,
maxAllowedMTLifetime,
barIndex //
);
}
}
}
//
// Bullish ...
XBoxZone mtBullishPivots[];
bool detectMTBullishPivots;
bool newMTBullishPivotDetected;
//
bool HasMTBullishPivots()
{
return HasChild(mtBullishPivots);
}
//
int CountMTBullishPivots()
{
return ArraySize(mtBullishPivots);
}
//
int FillMTBullishPivots(XBoxZone &pivots[])
{
//
int result = 0;
//
Clean(pivots);
//
if (!HasMTBullishPivots())
{
return result;
}
//
int count = CountMTBullishPivots();
for (int i = 0; i < count; i++)
{
//
XBoxZone iPivot = mtBullishPivots[i];
//
AddRef(
iPivot,
pivots //
);
//
iPivot.Clean();
}
//
result = ArraySize(pivots);
//
return result;
}
//
// Bearish ...
XBoxZone mtBearishPivots[];
bool detectMTBearishPivots;
bool newMTBearishPivotDetected;
//
bool HasMTBearishPivots()
{
return HasChild(mtBearishPivots);
}
//
int CountMTBearishPivots()
{
return ArraySize(mtBearishPivots);
}
//
int FillMTBearishPivots(XBoxZone &pivots[])
{
//
int result = 0;
//
Clean(pivots);
//
if (!HasMTBearishPivots())
{
return result;
}
//
int count = CountMTBearishPivots();
for (int i = 0; i < count; i++)
{
//
XBoxZone iPivot = mtBearishPivots[i];
//
AddRef(
iPivot,
pivots //
);
//
iPivot.Clean();
}
//
result = ArraySize(pivots);
//
return result;
}
//
// ORDERBLOCK ...
//
int maxAllowedOBLifetime; // Max Allowed MT Life ...
//
bool DetectOBPivot(
int barIndex,
ENUM_X_DIRECTION forDir,
XOHCL &zBar,
XOHCL &cBar,
XOHCL &pBar,
XOHCL &p2Bar,
X121XCatbConditions &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
? detectOBBullishPivots
: detectOBBearishPivots;
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);
//
XBoxZone iPivot;
//
// Detecting Bar Conditions ...
//
//
// OB ...
bool isOB = barAnalyser
.IsOB(
cBar,
iPivot,
false,
false //
);
//
bool isBullishOB =
isOB &&
iPivot.IsBullish();
bool isBearishOB =
isOB &&
iPivot.IsBearish();
//
// Prepare Conditinal Conditions ...
//
// Summarizing Conditions ...
//
result = false;
//
bool hasEndCondition =
//
forBullish
? isBullishOB
: isBearishOB
//
;
//
// End up Pivot and Store it ...
if (hasEndCondition)
{
//
// Bullish ...
if (forBullish)
{
//
iPivot.type = GetBoxType(XCATB_BULLISH_OB);
//
result = iPivot.IsValid();
if (result)
{
//
newOBBullishPivotDetected = AddBox(
iPivot,
obBullishPivots //
);
}
}
//
// Bearish ...
if (forBearish)
{
//
iPivot.type = GetBoxType(XCATB_BEARISH_OB);
//
result = iPivot.IsValid();
if (result)
{
//
newOBBearishPivotDetected = AddBox(
iPivot,
obBearishPivots //
);
}
}
}
//
return result;
}
//
void ValidateOBPivots(
XBoxZone &unavailables[],
int barIndex = 0 //
)
{
//
bool has = false;
//
bool applyLifetimeValidating = maxAllowedOBLifetime > 0;
//
// Bullish ...
has = HasOBBullishPivots();
if (has)
{
//
ApplyValidationOnBoxes(
obBullishPivots,
unavailables,
barIndex //
);
//
if (applyLifetimeValidating)
{
//
ApplyLifeTimeValidationOnBoxes(
obBullishPivots,
maxAllowedOBLifetime,
barIndex //
);
}
}
//
// Bearish ...
has = HasOBBearishPivots();
if (has)
{
//
ApplyValidationOnBoxes(
obBearishPivots,
unavailables,
barIndex //
);
//
if (applyLifetimeValidating)
{
//
ApplyLifeTimeValidationOnBoxes(
obBearishPivots,
maxAllowedOBLifetime,
barIndex //
);
}
}
}
//
// Bullish ...
XBoxZone obBullishPivots[];
bool detectOBBullishPivots;
bool newOBBullishPivotDetected;
//
bool HasOBBullishPivots()
{
return HasChild(obBullishPivots);
}
//
int CountOBBullishPivots()
{
return ArraySize(obBullishPivots);
}
//
int FillOBBullishPivots(XBoxZone &pivots[])
{
//
int result = 0;
//
Clean(pivots);
//
if (!HasOBBullishPivots())
{
return result;
}
//
int count = CountOBBullishPivots();
for (int i = 0; i < count; i++)
{
//
XBoxZone iPivot = obBullishPivots[i];
//
AddRef(
iPivot,
pivots //
);
//
iPivot.Clean();
}
//
result = ArraySize(pivots);
//
return result;
}
//
// Bearish ...
XBoxZone obBearishPivots[];
bool detectOBBearishPivots;
bool newOBBearishPivotDetected;
//
bool HasOBBearishPivots()
{
return HasChild(obBearishPivots);
}
//
int CountOBBearishPivots()
{
return ArraySize(obBearishPivots);
}
//
int FillOBBearishPivots(XBoxZone &pivots[])
{
//
int result = 0;
//
Clean(pivots);
//
if (!HasOBBearishPivots())
{
return result;
}
//
int count = CountOBBearishPivots();
for (int i = 0; i < count; i++)
{
//
XBoxZone iPivot = obBearishPivots[i];
//
AddRef(
iPivot,
pivots //
);
//
iPivot.Clean();
}
//
result = ArraySize(pivots);
//
return result;
}
//
// Protected ...
protected:
//
// Props ...
//
bool AddBox(
XBoxZone &box,
XBoxZone &boxes[] //
)
{
//
bool result = false;
//
result = box.IsValid();
if (!result)
{
return result;
}
//
int idx = -1;
bool isExists = FindIndex(
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 = FindIndex(
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 = FindIndex(
idx,
box,
invalidPivots //
);
if (!isExists)
{
//
AddRef(
box,
invalidPivots //
);
}
}
//
// Cleanup Resource ...
//
cBar.Clean();
pBar.Clean();
p2Bar.Clean();
//
return result;
}
//
void SortPivots()
{
//
bool has = false;
//
// Invalid Pivots ...
has = HasInvalidPivots();
if (has)
{
SortBoxes(invalidPivots);
}
//
// PV ...
//
// PEAK ...
has = HasPeakPivots();
if (has)
{
SortBoxes(peakPivots);
}
//
// VALE ...
has = HasValePivots();
if (has)
{
SortBoxes(valePivots);
}
//
// MT Bullish ...
has = HasMTBullishPivots();
if (has)
{
SortBoxes(mtBullishPivots);
}
//
// MT Bearish ...
has = HasMTBearishPivots();
if (has)
{
SortBoxes(mtBearishPivots);
}
//
// OB Bullish ...
has = HasOBBullishPivots();
if (has)
{
SortBoxes(obBullishPivots);
}
//
// OB Bearish ...
has = HasOBBearishPivots();
if (has)
{
SortBoxes(obBearishPivots);
}
}
//
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 = FindIndex(
idx,
iBox,
invalidPivots //
);
if (!isExists)
{
//
AddRef(
iBox,
invalidPivots //
);
}
}
//
iBox.Clean();
}
//
Clean(tmp);
}
//
// Prrivate ...
private:
//
// Props ...
//
XCX121XCatbHelper *helper;
XCBarAnalyser *barAnalyser;
//
};
//