Files
MQL5Data/Documents/BKP/xcaea.x-poi.detector.class.mq5
T

5287 lines
119 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_SWL, // Swing Low
XCA_SWH, // Swing High
XCA_PEAK, // Peak
XCA_VALE, // Vale
XCA_OB_BULL, // OBBull
XCA_OB_BEAR, // OBBear
XCA_FVG_BULL, // FVGBull
XCA_FVG_BEAR, // FVGBear
XCA_RSI_COOS, // RSICOOS
XCA_RSI_CUOB, // RSICUOB
XCA_TREND_BULL, // TrendBull
XCA_TREND_BEAR, // TrendBear
XCA_TRIGGER_BULL, // TriggerBull
XCA_TRIGGER_BEAR, // TriggerBear
};
//
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_SWL:
case XCA_VALE:
case XCA_OB_BULL:
case XCA_FVG_BULL:
case XCA_RSI_COOS:
case XCA_TREND_BULL:
case XCA_TRIGGER_BULL:
result = X_DIRECTION_BULLISH;
break;
//
case XCA_SWH:
case XCA_PEAK:
case XCA_OB_BEAR:
case XCA_FVG_BEAR:
case XCA_RSI_CUOB:
case XCA_TREND_BEAR:
case XCA_TRIGGER_BEAR:
result = X_DIRECTION_BEARISH;
break;
}
//
return result;
}
//
string GetBoxType(ENUM_XCA_PIVOTS value)
{
//
string result = NULL;
//
switch (value)
{
//
case XCA_SWL:
case XCA_SWH:
case XCA_VALE:
case XCA_PEAK:
case XCA_RSI_COOS:
case XCA_RSI_CUOB:
result = ToString(value);
break;
//
case XCA_OB_BULL:
case XCA_OB_BEAR:
result = "XCA_OB";
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;
//
case XCA_TRIGGER_BULL:
case XCA_TRIGGER_BEAR:
result = "XCA_TRIGGER";
break;
}
//
return result;
}
//
ENUM_XCA_PIVOTS GetPivotType(XBoxZone &value)
{
//
ENUM_XCA_PIVOTS result = XCA_NONE;
//
bool has = value.IsValid();
if (!has)
{
return result;
}
//
bool isSWL = value.type == GetBoxType(XCA_SWL) &&
value.dir == GetDirection(XCA_SWL);
bool isSWH = value.type == GetBoxType(XCA_SWH) &&
value.dir == GetDirection(XCA_SWH);
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 isOBBull = value.type == GetBoxType(XCA_OB_BULL) &&
value.dir == GetDirection(XCA_OB_BULL);
bool isOBBear = value.type == GetBoxType(XCA_OB_BEAR) &&
value.dir == GetDirection(XCA_OB_BEAR);
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);
bool isTriggerBullish = value.type == GetBoxType(XCA_TRIGGER_BULL) &&
value.dir == GetDirection(XCA_TRIGGER_BULL);
bool isTriggerBearish = value.type == GetBoxType(XCA_TRIGGER_BEAR) &&
value.dir == GetDirection(XCA_TRIGGER_BEAR);
//
if (isSWL)
{
result = XCA_SWL;
}
else if (isSWH)
{
result = XCA_SWH;
}
else if (isPeak)
{
result = XCA_PEAK;
}
else if (isVale)
{
result = XCA_VALE;
}
else if (isOBBull)
{
result = XCA_OB_BULL;
}
else if (isOBBear)
{
result = XCA_OB_BEAR;
}
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;
}
else if (isTriggerBullish)
{
result = XCA_TRIGGER_BULL;
}
else if (isTriggerBearish)
{
result = XCA_TRIGGER_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;
//
// SWING ...
//
maxAllowedSwingLifetime = 0;
//
detectSWHPivots = false;
detectSWLPivots = false;
//
// 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;
//
// OB ...
maxAllowedOBLifetime = 0;
//
detectOBBullishPivots = false;
detectOBBearishPivots = false;
//
// TREND ...
maxAllowedTrendLifetime = 0;
//
detectTrendBullishPivots = false;
detectTrendBearishPivots = false;
//
// Trigger Block ...
triggerBlockSwingLength = 7;
triggerBlockMaxAllowedRange = 0;
filterTriggerBlocksBySar = true;
triggerBlockBarHasProperSwing = true;
detectTriggerBlockBullishPivots = false;
detectTriggerBlockBearishPivots = false;
triggerBlockBarPressureValidation = true;
//
}
//
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;
//
newSWHPivotDetected = false;
newSWLPivotDetected = false;
newPeakPivotDetected = false;
newValePivotDetected = false;
newOBBullishPivotDetected = false;
newOBBearishPivotDetected = false;
newFVGBullishPivotDetected = false;
newFVGBearishPivotDetected = false;
newTrendBullishPivotDetected = false;
newTrendBearishPivotDetected = false;
newTriggerBlockBullishPivotDetected = false;
newTriggerBlockBearishPivotDetected = 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;
}
//
// Handle On Time Detection Pivots ...
bool isFirstBar = start == index;
if (isFirstBar)
{
//
// TRIGGER Block ...
// Since Trigger Block Pivots Only Used on Detection Time ...
// we have to Detect only when zBar Index is Zero, means at Last Bar ...
// in this Senario we Have to Ignore LoopBacks ...
//
// Bullish ...
if (detectTriggerBlockBullishPivots)
{
//
newTriggerBlockBullishPivotDetected = DetectTriggerBlockPivot(
barIndex,
X_DIRECTION_BULLISH,
zBar,
cBar,
pBar,
p2Bar,
conditions //
);
}
//
// Bearish ...
if (detectTriggerBlockBearishPivots)
{
//
newTriggerBlockBearishPivotDetected = DetectTriggerBlockPivot(
barIndex,
X_DIRECTION_BEARISH,
zBar,
cBar,
pBar,
p2Bar,
conditions //
);
}
}
//
// Checking Pivots ...
//
// SWING ...
//
// SWH ...
if (detectSWHPivots)
{
//
newSWHPivotDetected = DetectSwingPivot(
barIndex,
X_DIRECTION_BEARISH,
zBar,
cBar,
pBar,
p2Bar,
conditions //
);
}
//
// SWL ...
if (detectSWLPivots)
{
//
newSWLPivotDetected = DetectSwingPivot(
barIndex,
X_DIRECTION_BULLISH,
zBar,
cBar,
pBar,
p2Bar,
conditions //
);
}
//
// 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 //
);
}
//
// 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 //
);
}
//
// 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 ...
//
// SWING ...
ValidateSwingPivots(
unavailables,
barIndex //
);
//
// PV ...
ValidatePeakValePivots(
unavailables,
barIndex //
);
//
// OB ...
ValidateOBPivots(
unavailables,
barIndex //
);
//
// FVG ...
ValidateFVGPivots(
unavailables,
barIndex //
);
//
// TREND ...
ValidateTrendPivots(
unavailables,
barIndex //
);
//
// TRIGGER Block ...
ValidateTriggerBlockPivots(
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(
swlPivots,
pivots,
false //
);
//
Copy(
valePivots,
pivots,
false //
);
//
Copy(
obBullishPivots,
pivots,
false //
);
//
Copy(
fvgBullishPivots,
pivots,
false //
);
//
Copy(
trendBullishPivots,
pivots,
false //
);
}
//
// Bearish ...
if (canFillBearish)
{
//
Copy(
swhPivots,
pivots,
false //
);
//
Copy(
peakPivots,
pivots,
false //
);
//
Copy(
obBearishPivots,
pivots,
false //
);
//
Copy(
fvgBearishPivots,
pivots,
false //
);
//
Copy(
trendBearishPivots,
pivots,
false //
);
}
//
result = ArraySize(pivots);
//
return result;
}
//
int FillPivots(
XBoxZone &pivots[],
XBoxZone &unavailables[],
ENUM_XCA_PIVOTS &allowedTypes[],
datetime to = NULL //
)
{
//
int result = 0;
//
Clean(pivots);
//
bool canUpdateTo = IsValid(to);
//
XBoxZone tmp[];
bool has = false;
int tmpCount = FillPivots(
tmp,
X_DIRECTION_ALL //
);
has = IsValidSize(tmpCount);
if (!has)
{
return result;
}
//
XBoxZone iBox;
while (HasChild(tmp))
{
//
iBox = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
if (canUpdateTo)
{
iBox.to = to;
}
//
ENUM_XCA_PIVOTS iType = GetPivotType(iBox);
bool isAllowed =
!HasChild(allowedTypes)
? true
: Contains(
iType,
allowedTypes //
);
//
int idx = -1;
bool isUnAvailable = FindBoxIndex(
idx,
iBox,
unavailables //
);
//
if (isAllowed &&
!isUnAvailable)
{
//
AddRef(
iBox,
pivots //
);
}
//
iBox.Clean();
}
iBox.Clean();
//
result = ArraySize(pivots);
//
return result;
}
//
int FillPivots(
XBoxZone &decision,
XBoxZone &pivots[],
XBoxZone &unavailables[],
ENUM_XCA_PIVOTS &allowedTypes[],
datetime to = NULL //
)
{
//
int result = false;
//
bool has = false;
has = decision.IsValid();
if (!has)
{
return result;
}
//
XBoxZone tmp[];
int count = FillPivots(
tmp,
unavailables,
allowedTypes,
to //
);
//
for (int i = 0; i < count; i++)
{
//
XBoxZone iBox = tmp[i];
//
// Validate Box ...
has =
//
// Validate Time ..
iBox.from > decision.from
//
&&
//
// Validate Price ...
(
//
(iBox.upper < decision.upper &&
iBox.upper > decision.lower)
//
||
//
(iBox.lower > decision.lower &&
iBox.lower < decision.upper)
//
);
if (has)
{
//
AddRef(
iBox,
pivots //
);
}
//
iBox.Clean();
}
//
Clean(tmp);
//
result = ArraySize(pivots);
//
return result;
}
//
// Pivots ...
//
// INVALID Pivots ...
//
bool HasInvalidPivots()
{
return HasChild(invalidPivots);
}
//
int CountInvalidPivots()
{
return ArraySize(invalidPivots);
}
//
// SWING ...
//
int maxAllowedSwingLifetime; // Max Allowed Swing Life ...
//
bool DetectSwingPivot(
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
? detectSWLPivots
: detectSWHPivots;
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];
//
// 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];
//
// Prepare Conditinal Conditions ...
//
// SWH ...
//
bool isSWHSameLast = cSwingHigh == pSwingHigh;
bool isSWHSameLastPrev = pSwingHigh == p2SwingHigh;
//
bool isSWHSwitchedToSameLast = isSWHSameLast &&
!isSWHSameLastPrev;
bool isSWHFinishedFromSameLast = !isSWHSameLast &&
isSWHSameLastPrev;
//
// SWL ...
//
bool isSWLSameLast = cSwingLow == pSwingLow;
bool isSWLSameLastPrev = pSwingLow == p2SwingLow;
//
bool isSWLSwitchedToSameLast = isSWLSameLast &&
!isSWLSameLastPrev;
bool isSWLFinishedFromSameLast = !isSWLSameLast &&
isSWLSameLastPrev;
//
// Summarizing Conditions ...
//
result = false;
//
bool hasStartCondition =
//
forBullish
? isSWLFinishedFromSameLast
: isSWHFinishedFromSameLast
//
;
//
bool hasContinuationCondition =
//
forBullish
? isSWLSameLast
: isSWHSameLast
//
;
//
bool hasEndCondition =
//
forBullish
? isSWLSwitchedToSameLast
: isSWHSwitchedToSameLast
//
;
//
//
//
//
// ReInstance Pivot ...
if (hasStartCondition)
{
//
// SWL ...
if (forBullish)
{
//
swlPivot.Clean();
//
swlPivot.type = XCA_SWL;
swlPivot.symbol = symbol;
swlPivot.period = period;
//
swlPivot.to = pBar.time;
swlPivot.from = pBar.time;
swlPivot.value = pSwingLow;
swlPivot.reserve = pVale;
}
//
// SWH ...
if (forBearish)
{
//
swhPivot.Clean();
//
swhPivot.type = XCA_SWH;
swhPivot.symbol = symbol;
swhPivot.period = period;
//
swhPivot.to = pBar.time;
swhPivot.from = pBar.time;
swhPivot.value = pSwingHigh;
swhPivot.reserve = pPeak;
}
}
//
// Calculate and Fill Pivot Requirements ...
if (hasContinuationCondition)
{
//
// SWL ...
if (forBullish)
{
//
swlPivot.from = pBar.time;
//
swlPivot.reserve =
swlPivot.reserve == 0
? pVale
: MathMin(swlPivot.reserve, pVale);
}
//
// SWH ...
if (forBearish)
{
//
swhPivot.from = pBar.time;
//
swhPivot.reserve =
swhPivot.reserve == 0
? pPeak
: MathMin(swhPivot.reserve, pPeak);
}
}
//
// End up Pivot and Store it ...
if (hasEndCondition)
{
//
// SWL ...
if (forBullish)
{
//
result =
swlPivot.IsValid() &&
swlPivot.GetAge() >= pivotVerifications;
if (result)
{
//
XBoxZone iBox;
result = swlPivot.AsBox(iBox);
if (result)
{
//
newSWLPivotDetected = AddBox(
iBox,
swlPivots //
);
}
//
iBox.Clean();
}
//
swlPivot.Clean();
}
//
// SWH ...
if (forBearish)
{
//
result =
swhPivot.IsValid() &&
swhPivot.GetAge() >= pivotVerifications;
if (result)
{
//
XBoxZone iBox;
result = swhPivot.AsBox(iBox);
if (result)
{
//
newSWHPivotDetected = AddBox(
iBox,
swhPivots //
);
}
//
iBox.Clean();
}
//
swhPivot.Clean();
}
}
//
return result;
}
//
void ValidateSwingPivots(
XBoxZone &unavailables[],
int barIndex = 0 //
)
{
//
bool has = false;
//
bool applyLifetimeValidating = maxAllowedSwingLifetime > 0;
//
// SWH ...
has = HasSWHPivots();
if (has)
{
//
ApplyValidationOnBoxes(
swhPivots,
unavailables,
barIndex //
);
//
if (applyLifetimeValidating)
{
//
ApplyLifeTimeValidationOnBoxes(
swhPivots,
maxAllowedSwingLifetime,
barIndex //
);
}
}
//
// SWL ...
has = HasSWLPivots();
if (has)
{
//
ApplyValidationOnBoxes(
swlPivots,
unavailables,
barIndex //
);
//
if (applyLifetimeValidating)
{
//
ApplyLifeTimeValidationOnBoxes(
swlPivots,
maxAllowedSwingLifetime,
barIndex //
);
}
}
}
//
// SWL ...
//
XCAPivot swlPivot;
bool detectSWLPivots;
XBoxZone swlPivots[];
bool newSWLPivotDetected;
//
bool HasSWLPivots()
{
return HasChild(swlPivots);
}
//
int CountSWLPivots()
{
return ArraySize(swlPivots);
}
//
// SWH ...
//
XCAPivot swhPivot;
bool detectSWHPivots;
XBoxZone swhPivots[];
bool newSWHPivotDetected;
//
bool HasSWHPivots()
{
return HasChild(swhPivots);
}
//
int CountSWHPivots()
{
return ArraySize(swhPivots);
}
//
// 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)
{
//
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 ...
//
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);
}
//
// OB ...
int maxAllowedOBLifetime; // Max Allowed OB Life ...
//
bool DetectOBPivot(
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
? detectOBBullishPivots
: detectOBBearishPivots;
if (!result)
{
return result;
}
//
// Validate Args ...
result =
//
barIndex >= 0 &&
zBar.IsValid() &&
cBar.IsValid() &&
pBar.IsValid() &&
p2Bar.IsValid()
//
;
if (!result)
{
return result;
}
//
// Prepare Conditinal Conditions ...
//
// Default OB Detection ...
XBoxZone obBox;
bool isOB = barAnalyser.IsOB(
cBar,
obBox,
true, // OB FVG Bar Type ...
true // TWO Bar Verification ...
);
bool isBullishOB =
isOB &&
forBullish &&
obBox.IsBullish();
bool isBearishOB =
isOB &&
forBearish &&
obBox.IsBearish();
//
// Summarizing Conditions ...
//
result = false;
//
bool hasStartCondition = false;
bool hasContinuationCondition = false;
bool hasEndCondition = isBullishOB ||
isBearishOB;
//
// 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 = obBox.to;
iPivot.from = obBox.from;
iPivot.symbol = obBox.symbol;
iPivot.period = obBox.period;
iPivot.type = forBullish
? XCA_OB_BULL
: XCA_OB_BEAR;
iPivot.value = forBullish
? obBox.lower
: obBox.upper;
iPivot.reserve = forBullish
? obBox.upper
: obBox.lower;
//
result = iPivot.IsValid();
if (result)
{
//
result = iPivot.AsBox(iBox);
if (result)
{
//
if (forBullish)
{
//
result = AddBox(
iBox,
obBullishPivots //
);
}
else
{
//
result = AddBox(
iBox,
obBearishPivots //
);
}
}
}
//
iBox.Clean();
iPivot.Clean();
}
//
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 //
);
}
}
}
//
// OB Bullish Pivots ...
//
bool detectOBBullishPivots;
XBoxZone obBullishPivots[];
bool newOBBullishPivotDetected;
//
bool HasOBBullishPivots()
{
return HasChild(obBullishPivots);
}
//
int CountOBBullishPivots()
{
return ArraySize(obBullishPivots);
}
//
// OB Bearish Pivots ...
//
bool detectOBBearishPivots;
XBoxZone obBearishPivots[];
bool newOBBearishPivotDetected;
//
bool HasOBBearishPivots()
{
return HasChild(obBearishPivots);
}
//
int CountOBBearishPivots()
{
return ArraySize(obBearishPivots);
}
//
// 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);
}
//
// TRIGGER Blocks ...
//
int triggerBlockSwingLength;
int filterTriggerBlocksBySar;
double triggerBlockMaxAllowedRange;
bool triggerBlockBarHasProperSwing;
bool triggerBlockBarPressureValidation;
//
bool DetectTriggerBlockPivot(
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
? detectTriggerBlockBullishPivots
: detectTriggerBlockBearishPivots;
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;
int p3IDX = p2IDX + 1;
//
datetime cTime = zBar.time;
string symbol = zBar.symbol;
ENUM_TIMEFRAMES period = zBar.period;
double points = GetPoints(symbol);
//
// Reading Conditional Values ...
//
// Prepare Conditinal Conditions ...
//
// Checking Base Block Exists ...
XBoxZone iBlock;
result = helper.barAnalyser.IsOB(
cBar,
iBlock,
true, // Force FVG Bar Type ...
true // Force Two Bar ...
);
if (!result)
{
//
iBlock.Clean();
//
return result;
}
//
// Bullish ...
bool isBullish =
result &&
forBullish &&
iBlock.IsBullish();
//
// Bearish ...
bool isBearish =
result &&
forBearish &&
iBlock.IsBearish();
//
// Summarizing Conditions ...
//
result = isBullish ||
isBearish;
if (!result)
{
//
iBlock.Clean();
//
return result;
}
//
// Adding Pivot to Box Type ...
string iType = isBullish
? GetBoxType(XCA_TRIGGER_BULL)
: GetBoxType(XCA_TRIGGER_BEAR);
iBlock.type = iType;
//
// Validate TriggerBlock ...
XOHCL p3Bar;
XOHCL p4Bar;
result =
p2Bar.GetPreviousBar(p3Bar);
result =
result &&
p3Bar.GetPreviousBar(p4Bar);
if (!result)
{
//
p3Bar.Clean();
p4Bar.Clean();
iBlock.Clean();
//
return result;
}
ENUM_X_DIRECTION iDir;
//
// Validating Range ...
if (triggerBlockMaxAllowedRange > 0)
{
//
double blockRange = iBlock.GetRange();
result = blockRange <= triggerBlockMaxAllowedRange * points;
if (!result)
{
//
p3Bar.Clean();
p4Bar.Clean();
iBlock.Clean();
//
return result;
}
}
//
// Validate Using Swing Bars ...
if (triggerBlockBarHasProperSwing)
{
//
// Check Has Proper Swing ...
//
// CBar ...
bool isCBarSimpleSwing =
barAnalyser.IsSimpleSwing(
cBar,
iDir //
);
bool isCBarBullishSimpleSwing =
isCBarSimpleSwing &&
IsBullish(iDir);
bool isCBarBearishSimpleSwing =
isCBarSimpleSwing &&
IsBearish(iDir);
//
// PBar ...
bool isPBarSimpleSwing =
barAnalyser.IsSimpleSwing(
pBar,
iDir //
);
bool isPBarBullishSimpleSwing =
isPBarSimpleSwing &&
IsBullish(iDir);
bool isPBarBearishSimpleSwing =
isPBarSimpleSwing &&
IsBearish(iDir);
//
// P2Bar ...
bool isP2BarSimpleSwing =
barAnalyser.IsSimpleSwing(
p2Bar,
iDir //
);
bool isP2BarBullishSimpleSwing =
isP2BarSimpleSwing &&
IsBullish(iDir);
bool isP2BarBearishSimpleSwing =
isP2BarSimpleSwing &&
IsBearish(iDir);
//
// P3Bar ...
bool isP3BarSimpleSwing =
barAnalyser.IsSimpleSwing(
p3Bar,
iDir //
);
bool isP3BarBullishSimpleSwing =
isP3BarSimpleSwing &&
IsBullish(iDir);
bool isP3BarBearishSimpleSwing =
isP3BarSimpleSwing &&
IsBearish(iDir);
//
// P4Bar ...
bool isP4BarSimpleSwing =
barAnalyser.IsSimpleSwing(
p4Bar,
iDir //
);
bool isP4BarBullishSimpleSwing =
isP4BarSimpleSwing &&
IsBullish(iDir);
bool isP4BarBearishSimpleSwing =
isP4BarSimpleSwing &&
IsBearish(iDir);
//
// Summarise Validation ...
//
bool isBullishSwimpleSwing =
isBullish &&
(isCBarBullishSimpleSwing ||
isPBarBullishSimpleSwing ||
isP2BarBullishSimpleSwing ||
isP3BarBullishSimpleSwing ||
isP4BarBullishSimpleSwing);
//
bool isBearishSwimpleSwing =
isBearish &&
(isCBarBearishSimpleSwing ||
isPBarBearishSimpleSwing ||
isP2BarBearishSimpleSwing ||
isP3BarBearishSimpleSwing ||
isP4BarBearishSimpleSwing);
//
result = isBullishSwimpleSwing ||
isBearishSwimpleSwing;
if (!result)
{
//
p3Bar.Clean();
p4Bar.Clean();
iBlock.Clean();
//
return result;
}
}
//
// Validating Using Bar Pressure ...
if (triggerBlockBarPressureValidation)
{
//
// Check pBar is Momentum Bar ...
// and Breakd Block Side ...
//
bool isCBarMomentum = barAnalyser.IsMomentum(
pBar,
iDir //
);
bool isCBarBullishMomentum =
isCBarMomentum &&
IsBullish(iDir);
bool isCBarBearishMomentum =
isCBarMomentum &&
IsBearish(iDir);
//
bool isPBarMomentum = barAnalyser.IsMomentum(
pBar,
iDir //
);
bool isPBarBullishMomentum =
isPBarMomentum &&
IsBullish(iDir);
bool isPBarBearishMomentum =
isPBarMomentum &&
IsBearish(iDir);
//
bool isBullishBreakedOut =
isBullish &&
forBullish &&
pBar.IsBullish() &&
(isCBarBullishMomentum ||
isPBarBullishMomentum) &&
pBar.GetUp() > iBlock.upper &&
pBar.GetDown() < iBlock.upper;
//
bool isBearishBreakedOut =
isBearish &&
forBearish &&
pBar.IsBearish() &&
(isCBarBearishMomentum ||
isPBarBearishMomentum) &&
pBar.GetUp() > iBlock.lower &&
pBar.GetDown() < iBlock.lower;
//
result =
isBullishBreakedOut ||
isBearishBreakedOut;
if (!result)
{
//
p3Bar.Clean();
p4Bar.Clean();
iBlock.Clean();
//
return result;
}
}
//
// Extract to and from Info ...
//
int toIDX = iBlock.ToIndex();
int fromIDX = iBlock.FromIndex();
//
XOHCL toBar;
XOHCL fromBar;
//
result = iBlock.ToBar(toBar);
result = result &&
iBlock.FromBar(fromBar);
if (!result)
{
//
toBar.Clean();
p3Bar.Clean();
p4Bar.Clean();
iBlock.Clean();
fromBar.Clean();
//
return result;
}
//
// Validating Using HH and LL ...
if (triggerBlockSwingLength > 0)
{
//
double toLL = toBar.FindLowest(triggerBlockSwingLength, MODE_LOW);
double toHH = toBar.FindHighest(triggerBlockSwingLength, MODE_HIGH);
//
double fromLL = fromBar.FindLowest(triggerBlockSwingLength, MODE_LOW);
double fromHH = fromBar.FindHighest(triggerBlockSwingLength, MODE_HIGH);
//
double selectedLL = fromLL; // MathMin(toLL, fromLL);
double selectedHH = fromHH; // MathMax(toHH, fromHH);
//
bool isBullishSwingPassed =
isBullish &&
forBullish &&
selectedLL >= iBlock.lower;
//
bool isBearishSwingPassed =
isBearish &&
forBearish &&
selectedHH <= iBlock.upper;
//
result = isBullishSwingPassed ||
isBearishSwingPassed;
if (!result)
{
//
toBar.Clean();
p3Bar.Clean();
p4Bar.Clean();
iBlock.Clean();
fromBar.Clean();
//
return result;
}
}
//
// Apply Filters ...
bool hasFilter =
filterTriggerBlocksBySar;
if (hasFilter)
{
//
// Sar Filtering ...
if (filterTriggerBlocksBySar)
{
//
// Reading Conditions ...
//
double zSar = conditions.sarBuffer[zIDX];
double cSar = conditions.sarBuffer[cIDX];
double pSar = conditions.sarBuffer[pIDX];
double p2Sar = conditions.sarBuffer[p2IDX];
double p3Sar = conditions.sarBuffer[p3IDX];
//
// Preparing Constom Conditions ...
//
bool isZSarBullish = zSar < zBar.low;
bool isCSarBullish = cSar < cBar.low;
bool isPSarBullish = pSar < pBar.low;
bool isP2SarBullish = p2Sar < p2Bar.low;
bool isP3SarBullish = p3Sar < p3Bar.low;
//
bool isZSarBearish = zSar > zBar.high;
bool isCSarBearish = cSar > cBar.high;
bool isPSarBearish = pSar > pBar.high;
bool isP2SarBearish = p2Sar > p2Bar.high;
bool isP3SarBearish = p3Sar > p3Bar.high;
//
bool isCSarSwitchedToBullish =
isCSarBullish &&
!isPSarBullish;
bool isPSarSwitchedToBullish =
isPSarBullish &&
!isP2SarBullish;
bool isP2SarSwitchedToBullish =
isP2SarBullish &&
!isP3SarBullish;
//
bool isCSarSwitchedToBearish =
isCSarBearish &&
!isPSarBearish;
bool isPSarSwitchedToBearish =
isPSarBearish &&
!isP2SarBearish;
bool isP2SarSwitchedToBearish =
isP2SarBearish &&
!isP3SarBearish;
//
// Summarize Custom Conditions ...
//
// Bullish ...
//
bool isCSarBullishPassed =
isZSarBullish &&
isCSarSwitchedToBullish;
//
bool isPSarBullishPassed =
isZSarBullish &&
isCSarBullish &&
isPSarSwitchedToBullish;
//
bool isP2SarBullishPassed =
isZSarBullish &&
isCSarBullish &&
isPSarBullish &&
isP2SarSwitchedToBullish;
//
// Bearish ...
//
bool isCSarBearishPassed =
isZSarBearish &&
isCSarSwitchedToBearish;
//
bool isPSarBearishPassed =
isZSarBearish &&
isCSarBearish &&
isPSarSwitchedToBearish;
//
bool isP2SarBearishPassed =
isZSarBearish &&
isCSarBearish &&
isPSarBearish &&
isP2SarSwitchedToBearish;
//
// Summarize Conditions ...
//
bool isBullishFiltered =
isBullish &&
forBullish &&
(isCSarBullishPassed ||
isPSarBullishPassed ||
isP2SarBullishPassed);
//
bool isBearishFiltered =
isBearish &&
forBearish &&
(isCSarBearishPassed ||
isPSarBearishPassed ||
isP2SarBearishPassed);
//
result = isBullishFiltered ||
isBearishFiltered;
if (!result)
{
//
toBar.Clean();
p3Bar.Clean();
p4Bar.Clean();
iBlock.Clean();
fromBar.Clean();
//
return result;
}
}
}
//
// Summarize ...
//
isBullish =
isBullish &&
forBullish &&
iBlock.IsValid();
//
isBearish =
isBearish &&
forBearish &&
iBlock.IsValid();
//
result = isBullish ||
isBearish;
if (!result)
{
iBlock.Clean();
}
//
// Storing Pivot ...
//
if (isBullish)
{
//
result = AddBox(
iBlock,
triggerBlockBullishPivots //
);
}
//
if (isBearish)
{
//
result = AddBox(
iBlock,
triggerBlockBearishPivots //
);
}
//
// Cleanup Resource ...
//
toBar.Clean();
p3Bar.Clean();
p4Bar.Clean();
iBlock.Clean();
fromBar.Clean();
//
return result;
}
//
void ValidateTriggerBlockPivots(
XBoxZone &unavailables[],
int barIndex = 0 //
)
{
//
// Since Trigger Blocks Doesnt Use Multiple Times,
// there is not any Validation Required for them ...
bool has = false;
//
// bool applyLifetimeValidating = maxAllowedTriggerBlockLifetime > 0;
//
// Bullish ...
has = HasTriggerBlockBullishPivots();
if (has)
{
}
//
// Bearish ...
has = HasTriggerBlockBearishPivots();
if (has)
{
}
}
//
// Bullish ...
//
XBoxZone triggerBlockBullishPivots[];
bool detectTriggerBlockBullishPivots;
bool newTriggerBlockBullishPivotDetected;
//
bool HasTriggerBlockBullishPivots()
{
return HasChild(triggerBlockBullishPivots);
}
//
int CountTriggerBlockBullishPivots()
{
return ArraySize(triggerBlockBullishPivots);
}
//
// Bearish ...
//
bool detectTriggerBlockBearishPivots;
XBoxZone triggerBlockBearishPivots[];
bool newTriggerBlockBearishPivotDetected;
//
bool HasTriggerBlockBearishPivots()
{
return HasChild(triggerBlockBearishPivots);
}
//
int CountTriggerBlockBearishPivots()
{
return ArraySize(triggerBlockBearishPivots);
}
//
// 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);
//
swlPivot.Clean();
swhPivot.Clean();
peakPivot.Clean();
valePivot.Clean();
trendBullishPivot.Clean();
trendBearishPivot.Clean();
//
Clean(swlPivots);
Clean(swhPivots);
//
Clean(peakPivots);
Clean(valePivots);
//
Clean(obBullishPivots);
Clean(obBearishPivots);
//
Clean(fvgBullishPivots);
Clean(fvgBearishPivots);
//
Clean(trendBullishPivots);
Clean(trendBearishPivots);
//
Clean(triggerBlockBullishPivots);
Clean(triggerBlockBearishPivots);
}
//
void SortPivots()
{
//
bool has = false;
//
// Invalid Pivots ...
has = HasInvalidPivots();
if (has)
{
ApplySortOnBoxes(invalidPivots);
}
//
// SWING ...
//
// SWH ...
has = HasSWHPivots();
if (has)
{
ApplySortOnBoxes(swhPivots);
}
//
// SWL ...
has = HasSWLPivots();
if (has)
{
ApplySortOnBoxes(swlPivots);
}
//
// PV ...
//
// PEAK ...
has = HasPeakPivots();
if (has)
{
ApplySortOnBoxes(peakPivots);
}
//
// VALE ...
has = HasValePivots();
if (has)
{
ApplySortOnBoxes(valePivots);
}
//
// OB ...
//
// Bullish ...
has = HasOBBullishPivots();
if (has)
{
ApplySortOnBoxes(obBullishPivots);
}
//
// Bearish ...
has = HasOBBearishPivots();
if (has)
{
ApplySortOnBoxes(obBearishPivots);
}
//
// 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);
}
//
// TRIGGER Block ...
//
// Bullish ...
has = HasTriggerBlockBullishPivots();
if (has)
{
ApplySortOnBoxes(triggerBlockBullishPivots);
}
//
// Bearish ...
has = HasTriggerBlockBearishPivots();
if (has)
{
ApplySortOnBoxes(triggerBlockBearishPivots);
}
}
//
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);
}
//
};
//