Files
MQL5Data/XCAEA/Classes/xcaea.x-poi.detector.class.mq5
T
2025-04-24 06:25:28 +03:30

2930 lines
66 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_LL, // LowestLow
XCA_HH, // HighestHigh
XCA_KI, // KI
XCA_SWL, // SWL
XCA_SWH, // SWH
XCA_VALE, // VALE
XCA_PEAK, // PEAK
XCA_FVG_BULL, // FVGBull
XCA_FVG_BEAR, // FVGBear
XCA_RSI_COOS, // RSICOOS
XCA_RSI_CUOB, // RSICUOB
XCA_RSI_PEAK, // RSIPeak
XCA_RSI_VALE, // RSIVale
XCA_CCI_COOS, // CCICOOS
XCA_CCI_CUOB, // CCICUOB
XCA_CCI_PEAK, // CCIPeak
XCA_CCI_VALE, // CCIVale
XCA_KI_BULL, // KIBull
XCA_KI_BEAR, // KIBear
XCA_TKI_BULL, // TKIBull
XCA_TKI_BEAR, // TKIBear
XCA_PEAKSWHRES, // PeakSWHRes
XCA_VALESWLSUP, // ValeSWLSup
XCA_TREND_BULL, // TrendBull
XCA_TREND_BEAR, // TrendBear
XCA_TKITRND_BULL, // TKITRNDBull
XCA_TKITRND_BEAR, // TKITRNDBear
};
//
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;
}
//
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 = X_DIRECTION_NONE;
switch (type)
{
//
case XCA_LL:
case XCA_SWL:
case XCA_VALE:
case XCA_KI_BULL:
case XCA_FVG_BULL:
case XCA_RSI_COOS:
case XCA_RSI_VALE:
case XCA_CCI_COOS:
case XCA_CCI_VALE:
case XCA_TKI_BULL:
case XCA_TREND_BULL:
case XCA_VALESWLSUP:
case XCA_TKITRND_BULL:
iDir = X_DIRECTION_BULLISH;
break;
//
case XCA_HH:
case XCA_SWH:
case XCA_PEAK:
case XCA_KI_BEAR:
case XCA_FVG_BEAR:
case XCA_RSI_CUOB:
case XCA_RSI_PEAK:
case XCA_CCI_CUOB:
case XCA_CCI_PEAK:
case XCA_TKI_BEAR:
case XCA_TREND_BEAR:
case XCA_PEAKSWHRES:
case XCA_TKITRND_BEAR:
iDir = X_DIRECTION_BEARISH;
break;
}
//
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 = ToString(type);
if (type == XCA_KI_BULL ||
type == XCA_KI_BEAR)
{
//
typeStr = "XCA_KI";
}
else if (type == XCA_FVG_BULL ||
type == XCA_FVG_BEAR)
{
//
typeStr = "XCA_FVG";
}
else if (type == XCA_RSI_COOS ||
type == XCA_RSI_CUOB)
{
//
typeStr = "XCA_RSI";
}
else if (type == XCA_CCI_COOS ||
type == XCA_CCI_CUOB)
{
//
typeStr = "XCA_CCI";
}
else if (type == XCA_TKI_BULL ||
type == XCA_TKI_BEAR)
{
//
typeStr = "XCA_TKI";
}
else if (type == XCA_TREND_BULL ||
type == XCA_TREND_BEAR)
{
//
typeStr = "XCA_TREND";
}
else if (type == XCA_TKITRND_BULL ||
type == XCA_TKITRND_BEAR)
{
//
typeStr = "XCA_TKITRND";
}
box.type = typeStr;
//
box.upper =
isBullish
? reserve
: value;
box.lower =
isBullish
? value
: reserve;
//
result = box.IsValid();
if (!result)
{
box.Clean();
}
//
return result;
}
//
};
//
struct XCAPVFVG
{
//
double value;
XBoxZone fvgs[];
ENUM_X_DIRECTION dir;
//
XCAPVFVG()
{
Clean();
}
//
// Tools ...
//
void Clean()
{
//
value = 0;
Clean(fvgs);
dir = X_DIRECTION_NONE;
}
//
bool IsValid()
{
//
bool result = false;
//
result = value > 0 &&
HasChild(fvgs) &&
HasDirection(dir);
//
return result;
}
//
void AddFVG(XBoxZone &fvg)
{
//
bool has = fvg.IsValid() &&
fvg.dir == dir;
if (!has)
{
return;
}
//
int idx = -1;
has = FindBoxIndex(
idx,
fvg,
fvgs //
);
if (has)
{
return;
}
//
AddRef(
fvg,
fvgs //
);
}
//
bool IsBullish()
{
return IsValid() &&
IsBullish(dir);
}
//
bool IsBearish()
{
return IsValid() &&
IsBearish(dir);
}
//
bool GetSelectedFVG(XBoxZone &fvg)
{
//
bool result = false;
//
fvg.Clean();
//
result = IsValid();
if (!result)
{
return result;
}
//
int idx = -1;
if (IsBullish())
{
idx = GetLowest(fvgs);
}
else if (IsBearish())
{
idx = GetHighest(fvgs);
}
result = IsValidIndex(idx);
if (!result)
{
return result;
}
//
fvg = fvgs[idx];
//
result = fvg.IsValid();
//
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 ...
//
// RSI Peak Pivot ...
//
XCAPivot rsiPeakPivot;
bool detectRSIPeakPivots;
XBoxZone rsiPeakPivots[];
bool newRSIPeakPivotDetected;
//
// RSI Vale Pivot ...
//
XCAPivot rsiValePivot;
bool detectRSIValePivots;
XBoxZone rsiValePivots[];
bool newRSIValePivotDetected;
//
// CCI Peak Pivot ...
//
XCAPivot cciPeakPivot;
bool detectCCIPeakPivots;
XBoxZone cciPeakPivots[];
bool newCCIPeakPivotDetected;
//
// CCI Vale Pivot ...
//
XCAPivot cciValePivot;
bool detectCCIValePivots;
XBoxZone cciValePivots[];
bool newCCIValePivotDetected;
//
// FVG Bullish Pivots ...
//
bool detectFVGBullishPivots;
XBoxZone fvgBullishPivots[];
bool newFVGBullishPivotDetected;
//
// FVG Bearish Pivots ...
//
bool detectFVGBearishPivots;
XBoxZone fvgBearishPivots[];
bool newFVGBearishPivotDetected;
//
// VALE Pivot Support Swing Low ...
//
XCAPivot valeSupSWLPivot;
bool detectValeSupSWLPivots;
XBoxZone valeSupSWLPivots[];
bool newValeSupSWLPivotDetected;
//
// PEAK Pivot Resistance Swing High ...
//
XCAPivot peakResSWHPivot;
bool detectPeakResSWHPivots;
XBoxZone peakResSWHPivots[];
bool newPeakResSWHPivotDetected;
//
// XPVFVG Bullish ...
//
bool detectPVFVGBullishPivots;
XCAPVFVG pvFVGBullishPivots[];
bool newPVFVGBullishPivotDetected;
//
// XPVFVG Bearish ...
//
bool detectPVFVGBearishPivots;
XCAPVFVG pvFVGBearishPivots[];
bool newPVFVGBearishPivotDetected;
//
// Constructors ...
XCXCAEAPOIDetector(
XCXCAEAHelper *_helper //
)
{
//
helper = _helper;
drawer = new XCPOIDrawer();
barAnalyser = new XCBarAnalyser();
//
Default();
}
//
// De Constructors ...
~XCXCAEAPOIDetector()
{
//
rsiPeakPivot.Clean();
rsiValePivot.Clean();
cciPeakPivot.Clean();
cciValePivot.Clean();
valeSupSWLPivot.Clean();
peakResSWHPivot.Clean();
//
CleanPivots();
//
ZeroMemory(helper);
ZeroMemory(drawer);
ZeroMemory(barAnalyser);
}
//
// Properties ...
//
// Tools ...
//
virtual void Default()
{
//
maxAllowedPivots = 50;
pivotVerifications = 5;
pivotDetectionLoopbac = 100;
//
detectRSIPeakPivots = true;
detectRSIValePivots = true;
detectCCIPeakPivots = true;
detectCCIValePivots = true;
detectFVGBullishPivots = true;
detectFVGBearishPivots = true;
detectValeSupSWLPivots = true;
detectPeakResSWHPivots = true;
detectPVFVGBullishPivots = true;
detectPVFVGBearishPivots = true;
//
}
//
void Update(
int barIndex = 0 //
)
{
//
if (barIndex < 0)
{
barIndex = 0;
}
//
int loopback = pivotDetectionLoopbac;
loopback = NormalizeInt(loopback, 50);
//
int idx = -1;
int count = 0;
bool has = false;
//
newRSIPeakPivotDetected = false;
newRSIValePivotDetected = false;
newCCIPeakPivotDetected = false;
newCCIValePivotDetected = false;
newFVGBullishPivotDetected = false;
newFVGBearishPivotDetected = false;
newValeSupSWLPivotDetected = false;
newPeakResSWHPivotDetected = false;
newPVFVGBullishPivotDetected = false;
newPVFVGBearishPivotDetected = false;
//
int zIDX = 0;
int cIDX = zIDX + 1;
int pIDX = cIDX + 1;
int p2IDX = pIDX + 1;
int p3IDX = p2IDX + 1;
//
int index = barIndex;
int start = index;
int end = index + loopback;
while (start < end)
{
//
// Retrieve Conditions ...
XCAEAConditions conditions;
has = helper.GetConditions(
conditions,
start,
5 //
);
//
// 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;
}
//
// Bars Conditions ...
//
// 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);
//
// FVG ...
//
XBoxZone fvgBox;
bool isFVG = barAnalyser.IsFVG(
cBar,
fvgBox //
);
bool isBullishFVG =
isFVG &&
fvgBox.IsBullish();
bool isBearishFVG =
isFVG &&
fvgBox.IsBearish();
//
bool isCBarHasBullishPower = isBullishFVG ||
isCBarBullishRejected ||
isCBarBullishEngulfed ||
isCBarBullishMomentum;
//
bool isCBarHasBearishPower = isBearishFVG ||
isCBarBearishRejected ||
isCBarBearishEngulfed ||
isCBarBearishMomentum;
//
// Reading Values from Conditions and
// Create Customized Conditions if required ...
//
// 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];
//
// RSI ...
//
double zRSI = conditions.rsiBuffer[zIDX];
double cRSI = conditions.rsiBuffer[cIDX];
double pRSI = conditions.rsiBuffer[pIDX];
double p2RSI = conditions.rsiBuffer[p2IDX];
//
bool isRSIPeak =
pRSI > cRSI &&
pRSI > p2RSI &&
pRSI > zRSI;
//
bool isRSIVale =
pRSI < cRSI &&
pRSI < p2RSI &&
pRSI < zRSI;
//
// CCI ...
//
double zCCI = conditions.cciBuffer[zIDX];
double cCCI = conditions.cciBuffer[cIDX];
double pCCI = conditions.cciBuffer[pIDX];
double p2CCI = conditions.cciBuffer[p2IDX];
//
bool isCCIPeak =
pCCI > cCCI &&
pCCI > p2CCI &&
pCCI > zCCI;
//
bool isCCIVale =
pCCI < cCCI &&
pCCI < p2CCI &&
pCCI < zCCI;
//
// Checking Pivots ...
//
// RSI Peak Pivot ...
if (detectRSIPeakPivots)
{
//
bool checkingCondition =
isRSIPeak &&
isCBarHasBearishPower // &&
// conditions.isRSICrossedUnderOB
;
//
if (checkingCondition)
{
//
XCAPivot iPivot;
//
iPivot.to = cBar.time;
iPivot.from = p2Bar.time;
iPivot.value = pBar.high;
iPivot.type = XCA_RSI_PEAK;
iPivot.symbol = cBar.symbol;
iPivot.period = cBar.period;
//
Add(
cBar.high,
iPivot.values //
);
Add(
pBar.high,
iPivot.values //
);
Add(
p2Bar.high,
iPivot.values //
);
Add(
cBar.close,
iPivot.values //
);
Add(
pBar.close,
iPivot.values //
);
Add(
p2Bar.close,
iPivot.values //
);
//
iPivot.reserve = GetMin(iPivot.values);
//
XBoxZone iBox;
has = iPivot.IsValid();
if (has)
{
//
has = iPivot.AsBox(iBox);
if (has)
{
//
newRSIPeakPivotDetected = AddBox(
iBox,
rsiPeakPivots //
);
}
}
//
iBox.Clean();
iPivot.Clean();
}
}
//
// RSI Vale Pivot ...
if (detectRSIValePivots)
{
//
bool checkingCondition =
isRSIVale &&
isCBarHasBullishPower // &&
// conditions.isRSICrossedOverOS
;
//
if (checkingCondition)
{
//
XCAPivot iPivot;
//
iPivot.to = cBar.time;
iPivot.from = p2Bar.time;
iPivot.value = pBar.low;
iPivot.type = XCA_RSI_VALE;
iPivot.symbol = cBar.symbol;
iPivot.period = cBar.period;
//
Add(
cBar.low,
iPivot.values //
);
Add(
pBar.low,
iPivot.values //
);
Add(
p2Bar.low,
iPivot.values //
);
Add(
cBar.close,
iPivot.values //
);
Add(
pBar.close,
iPivot.values //
);
Add(
p2Bar.close,
iPivot.values //
);
//
iPivot.reserve = GetMax(iPivot.values);
//
XBoxZone iBox;
has = iPivot.IsValid();
if (has)
{
//
has = iPivot.AsBox(iBox);
if (has)
{
//
newRSIValePivotDetected = AddBox(
iBox,
rsiValePivots //
);
}
}
//
iBox.Clean();
iPivot.Clean();
}
}
//
// CCI Peak Pivot ...
if (detectCCIPeakPivots)
{
//
bool checkingCondition =
isCCIPeak &&
isCBarHasBearishPower // &&
// conditions.isCCICrossedUnderOB
;
//
if (checkingCondition)
{
//
XCAPivot iPivot;
//
iPivot.to = cBar.time;
iPivot.from = p2Bar.time;
iPivot.value = pBar.high;
iPivot.type = XCA_CCI_PEAK;
iPivot.symbol = cBar.symbol;
iPivot.period = cBar.period;
//
Add(
cBar.high,
iPivot.values //
);
Add(
pBar.high,
iPivot.values //
);
Add(
p2Bar.high,
iPivot.values //
);
Add(
cBar.close,
iPivot.values //
);
Add(
pBar.close,
iPivot.values //
);
Add(
p2Bar.close,
iPivot.values //
);
//
iPivot.reserve = GetMin(iPivot.values);
//
XBoxZone iBox;
has = iPivot.IsValid();
if (has)
{
//
has = iPivot.AsBox(iBox);
if (has)
{
//
newCCIPeakPivotDetected = AddBox(
iBox,
cciPeakPivots //
);
}
}
//
iBox.Clean();
iPivot.Clean();
}
}
//
// CCI Vale Pivot ...
if (detectCCIValePivots)
{
//
bool checkingCondition =
isCCIVale &&
isCBarHasBullishPower // &&
// conditions.isCCICrossedOverOS
;
//
if (checkingCondition)
{
//
XCAPivot iPivot;
//
iPivot.to = cBar.time;
iPivot.from = p2Bar.time;
iPivot.value = pBar.low;
iPivot.type = XCA_CCI_VALE;
iPivot.symbol = cBar.symbol;
iPivot.period = cBar.period;
//
Add(
cBar.low,
iPivot.values //
);
Add(
pBar.low,
iPivot.values //
);
Add(
p2Bar.low,
iPivot.values //
);
Add(
cBar.close,
iPivot.values //
);
Add(
pBar.close,
iPivot.values //
);
Add(
p2Bar.close,
iPivot.values //
);
//
iPivot.reserve = GetMax(iPivot.values);
//
XBoxZone iBox;
has = iPivot.IsValid();
if (has)
{
//
has = iPivot.AsBox(iBox);
if (has)
{
//
newCCIValePivotDetected = AddBox(
iBox,
cciValePivots //
);
}
}
//
iBox.Clean();
iPivot.Clean();
}
}
//
// FVG Bullish ...
if (detectFVGBullishPivots)
{
//
if (isBullishFVG)
{
//
XBoxZone iBox;
XCAPivot iPivot;
//
iPivot.to = fvgBox.to;
iPivot.from = fvgBox.from;
iPivot.type = XCA_FVG_BULL;
iPivot.value = fvgBox.lower;
iPivot.reserve = fvgBox.upper;
iPivot.symbol = fvgBox.symbol;
iPivot.period = fvgBox.period;
//
has = iPivot.IsValid();
if (has)
{
//
has = iPivot.AsBox(iBox);
if (has)
{
//
newFVGBullishPivotDetected = AddBox(
iBox,
fvgBullishPivots //
);
}
}
//
iBox.Clean();
iPivot.Clean();
}
}
//
// FVG Bearish ...
if (detectFVGBearishPivots)
{
//
if (isBearishFVG)
{
//
XBoxZone iBox;
XCAPivot iPivot;
//
iPivot.to = fvgBox.to;
iPivot.from = fvgBox.from;
iPivot.type = XCA_FVG_BEAR;
iPivot.value = fvgBox.upper;
iPivot.reserve = fvgBox.lower;
iPivot.symbol = fvgBox.symbol;
iPivot.period = fvgBox.period;
//
has = iPivot.IsValid();
if (has)
{
//
has = iPivot.AsBox(iBox);
if (has)
{
//
newFVGBearishPivotDetected = AddBox(
iBox,
fvgBearishPivots //
);
}
}
//
iBox.Clean();
iPivot.Clean();
}
}
//
// VALE Pivot Support Swing Low ...
if (detectValeSupSWLPivots)
{
//
if (conditions.isValeFinishedFromPivot)
{
//
valeSupSWLPivot.Clean();
//
valeSupSWLPivot.type = XCA_VALESWLSUP;
valeSupSWLPivot.symbol = conditions.symbol;
valeSupSWLPivot.period = conditions.period;
//
valeSupSWLPivot.to = pBar.time;
valeSupSWLPivot.from = pBar.time;
valeSupSWLPivot.value = conditions.valeBuffer[pIDX];
valeSupSWLPivot.reserve = conditions.valeGoldenBuffer[pIDX];
}
//
if (conditions.isValeIsPivot)
{
//
valeSupSWLPivot.from = pBar.time;
//
valeSupSWLPivot.reserve =
valeSupSWLPivot.reserve == 0
? conditions.valeGoldenBuffer[cIDX]
: MathMin(valeSupSWLPivot.reserve, conditions.valeGoldenBuffer[cIDX]);
}
//
if (conditions.isValeSwitchedToPivot)
{
//
has =
valeSupSWLPivot.IsValid() &&
valeSupSWLPivot.GetAge() >= pivotVerifications;
if (has)
{
//
XBoxZone iBox;
has = valeSupSWLPivot.AsBox(iBox);
if (has)
{
//
newValeSupSWLPivotDetected = AddBox(
iBox,
valeSupSWLPivots //
);
}
//
iBox.Clean();
}
//
valeSupSWLPivot.Clean();
}
}
//
// PEAK Pivot Resistance Swing High ...
if (detectPeakResSWHPivots)
{
//
if (conditions.isPeakFinishedFromPivot)
{
//
peakResSWHPivot.Clean();
//
peakResSWHPivot.type = XCA_PEAKSWHRES;
peakResSWHPivot.symbol = conditions.symbol;
peakResSWHPivot.period = conditions.period;
//
peakResSWHPivot.to = pBar.time;
peakResSWHPivot.from = pBar.time;
peakResSWHPivot.value = conditions.peakBuffer[pIDX];
peakResSWHPivot.reserve = conditions.peakGoldenBuffer[pIDX];
}
//
if (conditions.isPeakIsPivot)
{
//
peakResSWHPivot.from = pBar.time;
//
peakResSWHPivot.reserve =
peakResSWHPivot.reserve == 0
? conditions.peakGoldenBuffer[cIDX]
: MathMax(peakResSWHPivot.reserve, conditions.peakGoldenBuffer[cIDX]);
}
//
if (conditions.isPeakSwitchedToPivot)
{
//
has =
peakResSWHPivot.IsValid() &&
peakResSWHPivot.GetAge() >= pivotVerifications;
if (has)
{
//
XBoxZone iBox;
has = peakResSWHPivot.AsBox(iBox);
if (has)
{
//
newPeakResSWHPivotDetected = AddBox(
iBox,
peakResSWHPivots //
);
}
//
iBox.Clean();
}
//
peakResSWHPivot.Clean();
}
}
//
// PVFVG Bullish ...
if (detectPVFVGBullishPivots)
{
//
if (conditions.isValeIsPivot && isBullishFVG)
{
//
idx = -1;
has = HasPVFVGBullishPivots();
if (has)
{
//
count = CountPVFVGBullishPivots();
for (int i = 0; i < count; i++)
{
//
XCAPVFVG iPVFVG = pvFVGBullishPivots[i];
//
if (iPVFVG.value == cVale && iPVFVG.IsBullish())
{
//
idx = i;
iPVFVG.Clean();
//
break;
}
//
iPVFVG.Clean();
}
}
//
has = IsValidIndex(idx);
if (has)
{
//
// Add FVG to Exists PVFVG ...
//
XBoxZone iFVG = fvgBox;
iFVG.type = "XCA_FVG";
//
pvFVGBullishPivots[idx].AddFVG(iFVG);
}
else
{
//
// Add New PVFVG ...
//
newPVFVGBullishPivotDetected = true;
//
XCAPVFVG iPVFVG;
XBoxZone iFVG = fvgBox;
iFVG.type = "XCA_FVG";
//
iPVFVG.value = cVale;
iPVFVG.dir = X_DIRECTION_BULLISH;
//
iPVFVG.AddFVG(iFVG);
//
has = iPVFVG.IsValid();
if (has)
{
//
AddRef(
iPVFVG,
pvFVGBullishPivots //
);
}
//
iFVG.Clean();
iPVFVG.Clean();
}
}
}
//
// PVFVG Bearish ...
if (detectPVFVGBearishPivots)
{
//
if (conditions.isPeakIsPivot && isBearishFVG)
{
//
idx = -1;
has = HasPVFVGBearishPivots();
if (has)
{
//
count = CountPVFVGBearishPivots();
for (int i = 0; i < count; i++)
{
//
XCAPVFVG iPVFVG = pvFVGBearishPivots[i];
//
if (iPVFVG.value == cPeak && iPVFVG.IsBearish())
{
//
idx = i;
iPVFVG.Clean();
//
break;
}
//
iPVFVG.Clean();
}
}
//
has = IsValidIndex(idx);
if (has)
{
//
// Add FVG to Exists PVFVG ...
//
XBoxZone iFVG = fvgBox;
iFVG.type = "XCA_FVG";
//
pvFVGBearishPivots[idx].AddFVG(iFVG);
}
else
{
//
// Add New PVFVG ...
//
newPVFVGBearishPivotDetected = true;
//
XCAPVFVG iPVFVG;
XBoxZone iFVG = fvgBox;
iFVG.type = "XCA_FVG";
//
iPVFVG.value = cPeak;
iPVFVG.dir = X_DIRECTION_BEARISH;
//
iPVFVG.AddFVG(iFVG);
//
has = iPVFVG.IsValid();
if (has)
{
//
AddRef(
iPVFVG,
pvFVGBearishPivots //
);
}
//
iFVG.Clean();
iPVFVG.Clean();
}
}
}
//
start++;
//
zBar.Clean();
cBar.Clean();
pBar.Clean();
p2Bar.Clean();
fvgBox.Clean();
conditions.Clean();
}
//
}
//
void Validate(
XBoxZone &unAvailableBoxes[],
int barIndex = 0 //
)
{
//
// Do All Pivots Validation ...
//
if (barIndex < 0)
{
barIndex = 0;
}
//
XBoxZone tmp[];
bool has = false;
//
int zIDX = 0;
int cIDX = zIDX + 1;
int pIDX = cIDX + 1;
int p2IDX = pIDX + 1;
//
// Implement Validation Senarios ...
//
// RSI Peak Pivot ...
//
has = HasRSIPeakPivots();
if (has)
{
//
// Copy Items and Cleanup Collection ...
Copy(
rsiPeakPivots,
tmp //
);
Clean(rsiPeakPivots);
//
// Do Validation ...
while (HasChild(tmp))
{
//
XBoxZone iBox = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
has = ValidateBox(
iBox,
unAvailableBoxes,
barIndex //
);
if (has)
{
//
AddRef(
iBox,
rsiPeakPivots //
);
}
//
iBox.Clean();
}
//
Clean(tmp);
}
//
// RSI Vale Pivot ...
//
has = HasRSIValePivots();
if (has)
{
//
// Copy Items and Cleanup Collection ...
Copy(
rsiValePivots,
tmp //
);
Clean(rsiValePivots);
//
// Do Validation ...
while (HasChild(tmp))
{
//
XBoxZone iBox = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
has = ValidateBox(
iBox,
unAvailableBoxes,
barIndex //
);
if (has)
{
//
AddRef(
iBox,
rsiValePivots //
);
}
//
iBox.Clean();
}
//
Clean(tmp);
}
//
// CCI Peak Pivot ...
//
has = HasCCIPeakPivots();
if (has)
{
//
// Copy Items and Cleanup Collection ...
Copy(
cciPeakPivots,
tmp //
);
Clean(cciPeakPivots);
//
// Do Validation ...
while (HasChild(tmp))
{
//
XBoxZone iBox = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
has = ValidateBox(
iBox,
unAvailableBoxes,
barIndex //
);
if (has)
{
//
AddRef(
iBox,
cciPeakPivots //
);
}
//
iBox.Clean();
}
//
Clean(tmp);
}
//
// CCI Vale Pivot ...
//
has = HasCCIValePivots();
if (has)
{
//
// Copy Items and Cleanup Collection ...
Copy(
cciValePivots,
tmp //
);
Clean(cciValePivots);
//
// Do Validation ...
while (HasChild(tmp))
{
//
XBoxZone iBox = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
has = ValidateBox(
iBox,
unAvailableBoxes,
barIndex //
);
if (has)
{
//
AddRef(
iBox,
cciValePivots //
);
}
//
iBox.Clean();
}
//
Clean(tmp);
}
//
// FVG Bullish ...
//
has = HasFVGBullishPivots();
if (has)
{
//
// Copy Items and Cleanup Collection ...
Copy(
fvgBullishPivots,
tmp //
);
Clean(fvgBullishPivots);
//
// Do Validation ...
while (HasChild(tmp))
{
//
XBoxZone iBox = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
has = ValidateBox(
iBox,
unAvailableBoxes,
barIndex //
);
if (has)
{
//
AddRef(
iBox,
fvgBullishPivots //
);
}
//
iBox.Clean();
}
//
Clean(tmp);
}
//
// FVG Bearish ...
//
has = HasFVGBearishPivots();
if (has)
{
//
// Copy Items and Cleanup Collection ...
Copy(
fvgBearishPivots,
tmp //
);
Clean(fvgBearishPivots);
//
// Do Validation ...
while (HasChild(tmp))
{
//
XBoxZone iBox = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
has = ValidateBox(
iBox,
unAvailableBoxes,
barIndex //
);
if (has)
{
//
AddRef(
iBox,
fvgBearishPivots //
);
}
//
iBox.Clean();
}
//
Clean(tmp);
}
//
// VALE Pivot Support Swing Low ...
//
has = HasValeSupSWLPivots();
if (has)
{
//
// Copy Items and Cleanup Collection ...
Copy(
valeSupSWLPivots,
tmp //
);
Clean(valeSupSWLPivots);
//
// Do Validation ...
while (HasChild(tmp))
{
//
XBoxZone iBox = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
has = ValidateBox(
iBox,
unAvailableBoxes,
barIndex //
);
if (has)
{
//
AddRef(
iBox,
valeSupSWLPivots //
);
}
//
iBox.Clean();
}
//
Clean(tmp);
}
//
// PEAK Pivot Resistance Swing High ...
//
has = HasPeakResSWHPivots();
if (has)
{
//
// Copy Items and Cleanup Collection ...
Copy(
peakResSWHPivots,
tmp //
);
Clean(peakResSWHPivots);
//
// Do Validation ...
while (HasChild(tmp))
{
//
XBoxZone iBox = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
has = ValidateBox(
iBox,
unAvailableBoxes,
barIndex //
);
if (has)
{
//
AddRef(
iBox,
peakResSWHPivots //
);
}
//
iBox.Clean();
}
//
Clean(tmp);
}
//
// PVFVG Bullish ...
//
has = HasPVFVGBullishPivots();
if (has)
{
//
XCAPVFVG tmpPVFVG[];
//
// Copy Items and Cleanup Collection ...
Copy(
pvFVGBullishPivots,
tmpPVFVG //
);
Clean(pvFVGBullishPivots);
//
// Do Validation ...
while (HasChild(tmpPVFVG))
{
//
XCAPVFVG iPVFVG = tmpPVFVG[0];
ArrayRemove(
tmpPVFVG,
0,
1 //
);
Copy(
iPVFVG.fvgs,
tmp //
);
Clean(iPVFVG.fvgs);
while (HasChild(tmp))
{
//
XBoxZone iBox = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
has = ValidateBox(
iBox,
unAvailableBoxes,
barIndex //
);
if (has)
{
//
AddRef(
iBox,
iPVFVG.fvgs //
);
}
//
iBox.Clean();
}
//
if (iPVFVG.IsValid())
{
//
AddRef(
iPVFVG,
pvFVGBullishPivots //
);
}
}
//
Clean(tmp);
Clean(tmpPVFVG);
}
//
// PVFVG Bearish ...
//
has = HasPVFVGBearishPivots();
if (has)
{
//
XCAPVFVG tmpPVFVG[];
//
// Copy Items and Cleanup Collection ...
Copy(
pvFVGBearishPivots,
tmpPVFVG //
);
Clean(pvFVGBearishPivots);
//
// Do Validation ...
while (HasChild(tmpPVFVG))
{
//
XCAPVFVG iPVFVG = tmpPVFVG[0];
ArrayRemove(
tmpPVFVG,
0,
1 //
);
Copy(
iPVFVG.fvgs,
tmp //
);
Clean(iPVFVG.fvgs);
while (HasChild(tmp))
{
//
XBoxZone iBox = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
has = ValidateBox(
iBox,
unAvailableBoxes,
barIndex //
);
if (has)
{
//
AddRef(
iBox,
iPVFVG.fvgs //
);
}
//
iBox.Clean();
}
//
if (iPVFVG.IsValid())
{
//
AddRef(
iPVFVG,
pvFVGBearishPivots //
);
}
}
//
Clean(tmp);
Clean(tmpPVFVG);
}
//
Clean(tmp);
//
ReversePivots();
//
}
//
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(
rsiValePivots,
pivots,
false //
);
//
Copy(
cciValePivots,
pivots,
false //
);
//
Copy(
fvgBullishPivots,
pivots,
false //
);
//
Copy(
valeSupSWLPivots,
pivots,
false //
);
//
has = HasPVFVGBullishPivots();
if (has)
{
//
count = CountPVFVGBullishPivots();
for (int i = 0; i < count; i++)
{
//
XBoxZone iBox;
has = pvFVGBullishPivots[i].GetSelectedFVG(iBox);
if (has)
{
//
AddRef(
iBox,
pivots //
);
}
//
iBox.Clean();
}
}
}
//
// Bearish ...
if (canFillBearish)
{
//
Copy(
rsiPeakPivots,
pivots,
false //
);
//
Copy(
cciPeakPivots,
pivots,
false //
);
//
Copy(
fvgBearishPivots,
pivots,
false //
);
//
Copy(
peakResSWHPivots,
pivots,
false //
);
//
has = HasPVFVGBearishPivots();
if (has)
{
//
count = CountPVFVGBearishPivots();
for (int i = 0; i < count; i++)
{
//
XBoxZone iBox;
has = pvFVGBearishPivots[i].GetSelectedFVG(iBox);
if (has)
{
//
AddRef(
iBox,
pivots //
);
}
//
iBox.Clean();
}
}
}
//
result = ArraySize(pivots);
//
return result;
}
//
// Counters ...
//
// RSI Peak Pivot ...
//
bool HasRSIPeakPivots()
{
return HasChild(rsiPeakPivots);
}
//
int CountRSIPeakPivots()
{
return ArraySize(rsiPeakPivots);
}
//
// RSI Vale Pivot ...
//
bool HasRSIValePivots()
{
return HasChild(rsiValePivots);
}
//
int CountRSIValePivots()
{
return ArraySize(rsiValePivots);
}
//
// CCI Peak Pivot ...
//
bool HasCCIPeakPivots()
{
return HasChild(cciPeakPivots);
}
//
int CountCCIPeakPivots()
{
return ArraySize(cciPeakPivots);
}
//
// CCI Vale Pivot ...
//
bool HasCCIValePivots()
{
return HasChild(cciValePivots);
}
//
int CountCCIValePivots()
{
return ArraySize(cciValePivots);
}
//
// FVG Bullish ...
//
bool HasFVGBullishPivots()
{
return HasChild(fvgBullishPivots);
}
//
int CountFVGBullishPivots()
{
return ArraySize(fvgBullishPivots);
}
//
// FVG Bearish ...
//
bool HasFVGBearishPivots()
{
return HasChild(fvgBearishPivots);
}
//
int CountFVGBearishPivots()
{
return ArraySize(fvgBearishPivots);
}
//
// VALE Pivot Support Swing Low ...
//
bool HasValeSupSWLPivots()
{
return HasChild(valeSupSWLPivots);
}
//
int CountValeSupSWLPivots()
{
return ArraySize(valeSupSWLPivots);
}
//
// PEAK Pivot Resistance Swing High ...
//
bool HasPeakResSWHPivots()
{
return HasChild(peakResSWHPivots);
}
//
int CountPeakResSWHPivots()
{
return ArraySize(peakResSWHPivots);
}
//
// PVFVG Bullish ...
//
bool HasPVFVGBullishPivots()
{
return HasChild(pvFVGBullishPivots);
}
//
int CountPVFVGBullishPivots()
{
return ArraySize(pvFVGBullishPivots);
}
//
// PVFVG Bearish ...
//
bool HasPVFVGBearishPivots()
{
return HasChild(pvFVGBearishPivots);
}
//
int CountPVFVGBearishPivots()
{
return ArraySize(pvFVGBearishPivots);
}
//
// Protected ...
protected:
//
// Props ...
//
// Prrivate ...
private:
//
// Props ...
//
XCPOIDrawer *drawer;
XCXCAEAHelper *helper;
XCBarAnalyser *barAnalyser;
//
bool AddBox(
XBoxZone &box,
XBoxZone &boxes[],
int maxAllowed = 0 //
)
{
//
bool result = false;
//
if (maxAllowed <= 0)
{
maxAllowed = maxAllowedPivots;
}
//
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);
if (IsValidSize(before))
{
ArrayReverse(boxes);
}
//
AddRef(
box,
boxes //
);
int after = ArraySize(boxes);
//
result = after > before;
if (result)
{
//
ArrayReverse(boxes);
//
CleanupArray(
boxes,
maxAllowed //
);
}
//
return result;
}
//
bool ValidateBox(
XBoxZone &box,
XBoxZone &unAvailableBoxes[],
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(unAvailableBoxes);
if (canCheckUnAvailableBoxes)
{
//
int idx = -1;
bool isUnAvailable = FindBoxIndex(
idx,
box,
unAvailableBoxes //
);
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;
//
// Cleanup Resource ...
//
cBar.Clean();
pBar.Clean();
p2Bar.Clean();
//
return result;
}
//
void CleanPivots()
{
//
Clean(rsiPeakPivots);
Clean(rsiValePivots);
Clean(cciPeakPivots);
Clean(cciValePivots);
Clean(fvgBullishPivots);
Clean(fvgBearishPivots);
Clean(valeSupSWLPivots);
Clean(peakResSWHPivots);
Clean(pvFVGBullishPivots);
Clean(pvFVGBearishPivots);
}
//
void ReversePivots()
{
//
ArrayReverse(rsiPeakPivots);
ArrayReverse(rsiValePivots);
ArrayReverse(cciPeakPivots);
ArrayReverse(cciValePivots);
ArrayReverse(fvgBullishPivots);
ArrayReverse(fvgBearishPivots);
ArrayReverse(valeSupSWLPivots);
ArrayReverse(peakResSWHPivots);
ArrayReverse(pvFVGBullishPivots);
ArrayReverse(pvFVGBearishPivots);
}
//
};
//