2738 lines
55 KiB
Plaintext
2738 lines
55 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Class
|
|
// -------------------------------------------------
|
|
// Name: XCXCAYBEAPOIDetector ...
|
|
// Description: Class for XCATBEA POI Detector ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://saherelm.ir"
|
|
#property version "1.00"
|
|
#property description "SaherElm Class for XCATBEA POI Detector"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5"
|
|
#include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5"
|
|
#include "../../Libraries/x-saherelm.x-poi.extensions.lib.mq5"
|
|
|
|
//
|
|
// Definitions ...
|
|
|
|
//
|
|
enum ENUM_XCATB_PIVOTS
|
|
{
|
|
XCATB_NONE, // None
|
|
XCATB_PEAK, // Peak
|
|
XCATB_VALE, // Vale
|
|
XCATB_BULLISH_MT, // MTBull
|
|
XCATB_BEARISH_MT, // MTBear
|
|
XCATB_BULLISH_OB, // OBBull
|
|
XCATB_BEARISH_OB, // OBBear
|
|
};
|
|
|
|
//
|
|
bool IsValid(ENUM_XCATB_PIVOTS value)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value != XCATB_NONE;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string ToString(ENUM_XCATB_PIVOTS value)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
result = EnumToString(value);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION GetDirection(ENUM_XCATB_PIVOTS value)
|
|
{
|
|
//
|
|
ENUM_X_DIRECTION result = X_DIRECTION_NONE;
|
|
|
|
//
|
|
switch (value)
|
|
{
|
|
//
|
|
case XCATB_VALE:
|
|
case XCATB_BULLISH_MT:
|
|
case XCATB_BULLISH_OB:
|
|
result = X_DIRECTION_BULLISH;
|
|
break;
|
|
|
|
//
|
|
case XCATB_PEAK:
|
|
case XCATB_BEARISH_MT:
|
|
case XCATB_BEARISH_OB:
|
|
result = X_DIRECTION_BEARISH;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string GetBoxType(ENUM_XCATB_PIVOTS value)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
switch (value)
|
|
{
|
|
//
|
|
case XCATB_VALE:
|
|
case XCATB_PEAK:
|
|
result = ToString(value);
|
|
break;
|
|
|
|
//
|
|
case XCATB_BULLISH_MT:
|
|
case XCATB_BEARISH_MT:
|
|
result = "XMT";
|
|
break;
|
|
|
|
//
|
|
case XCATB_BULLISH_OB:
|
|
case XCATB_BEARISH_OB:
|
|
result = "XOB";
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_XCATB_PIVOTS GetPivotType(XBoxZone &value)
|
|
{
|
|
//
|
|
ENUM_XCATB_PIVOTS result = XCATB_NONE;
|
|
|
|
//
|
|
bool has = value.IsValid();
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isPeak = value.type == GetBoxType(XCATB_PEAK) &&
|
|
value.dir == GetDirection(XCATB_PEAK);
|
|
bool isVale = value.type == GetBoxType(XCATB_VALE) &&
|
|
value.dir == GetDirection(XCATB_VALE);
|
|
bool isBullishMT = value.type == GetBoxType(XCATB_BULLISH_MT) &&
|
|
value.dir == GetDirection(XCATB_BULLISH_MT);
|
|
bool isBearishMT = value.type == GetBoxType(XCATB_BEARISH_MT) &&
|
|
value.dir == GetDirection(XCATB_BEARISH_MT);
|
|
bool isBullishOB = value.type == GetBoxType(XCATB_BULLISH_OB) &&
|
|
value.dir == GetDirection(XCATB_BULLISH_OB);
|
|
bool isBearishOB = value.type == GetBoxType(XCATB_BEARISH_OB) &&
|
|
value.dir == GetDirection(XCATB_BEARISH_OB);
|
|
|
|
//
|
|
if (isPeak)
|
|
{
|
|
result = XCATB_PEAK;
|
|
}
|
|
else if (isVale)
|
|
{
|
|
result = XCATB_VALE;
|
|
}
|
|
else if (isBullishMT)
|
|
{
|
|
result = XCATB_BULLISH_MT;
|
|
}
|
|
else if (isBearishMT)
|
|
{
|
|
result = XCATB_BEARISH_MT;
|
|
}
|
|
else if (isBullishOB)
|
|
{
|
|
result = XCATB_BULLISH_OB;
|
|
}
|
|
else if (isBearishOB)
|
|
{
|
|
result = XCATB_BEARISH_OB;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
struct XCATBPivot
|
|
{
|
|
//
|
|
// Props ...
|
|
datetime to;
|
|
double value;
|
|
string symbol;
|
|
datetime from;
|
|
double reserve;
|
|
ENUM_XCATB_PIVOTS type;
|
|
ENUM_TIMEFRAMES period;
|
|
|
|
//
|
|
double values[];
|
|
|
|
//
|
|
// Constructor ...
|
|
XCATBPivot()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
/**
|
|
* Cleanup ...
|
|
*/
|
|
void Clean()
|
|
{
|
|
//
|
|
value = 0;
|
|
to = NULL;
|
|
reserve = 0;
|
|
from = NULL;
|
|
symbol = NULL;
|
|
period = NULL;
|
|
type = XCATB_NONE;
|
|
|
|
//
|
|
Clean(values);
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
/**
|
|
* Validate ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
from < to &&
|
|
value != 0 &&
|
|
IsValid(to) &&
|
|
IsValid(from) &&
|
|
IsValid(type) &&
|
|
IsValid(symbol) &&
|
|
IsValid(period);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Model is Same as this or not ...
|
|
*
|
|
* @param pivot: XCATBPivot ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsSameAs(XCATBPivot &pivot)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
IsValid() &&
|
|
pivot.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
to == pivot.to &&
|
|
from == pivot.from &&
|
|
type == pivot.type &&
|
|
value == pivot.value &&
|
|
symbol == pivot.symbol &&
|
|
period == pivot.period;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve To Index ...
|
|
*
|
|
* @param forPeriod: ENUM_TIMEFRAMES, Specified Period ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ToIndex(
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
result = GetBarIndex(
|
|
symbol,
|
|
forPeriod,
|
|
to //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve From Index ...
|
|
*
|
|
* @param forPeriod: ENUM_TIMEFRAMES, Specified Period ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int FromIndex(
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
result = GetBarIndex(
|
|
symbol,
|
|
forPeriod,
|
|
from //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve Age of Pivot ...
|
|
*
|
|
* @param forPeriod: ENUM_TIMEFRAMES, Specified Period ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetAge(
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
int toIDX = ToIndex(forPeriod);
|
|
int fromIDX = FromIndex(forPeriod);
|
|
|
|
//
|
|
result = fromIDX - toIDX;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts Pivot to Box ...
|
|
*
|
|
* @param box: XBoxZone instance reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool AsBox(
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION iDir = GetDirection(type);
|
|
|
|
//
|
|
result = HasDirection(iDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish =
|
|
IsBullish(iDir) &&
|
|
value < reserve;
|
|
|
|
//
|
|
bool isBearish =
|
|
IsBearish(iDir) &&
|
|
value > reserve;
|
|
|
|
//
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = to;
|
|
box.dir = iDir;
|
|
box.from = from;
|
|
box.symbol = symbol;
|
|
box.period = period;
|
|
|
|
//
|
|
string typeStr = GetBoxType(type);
|
|
box.type = typeStr;
|
|
|
|
//
|
|
box.upper =
|
|
isBullish
|
|
? reserve
|
|
: value;
|
|
box.lower =
|
|
isBullish
|
|
? value
|
|
: reserve;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
box.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
// Implementations ...
|
|
class XCXCATBEAPOIDetector : public XCBase
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
// Props ...
|
|
int maxAllowedPivots; // Max Allowed Holding Pibots ...
|
|
int pivotVerifications; // Pivots Verifications ...
|
|
int pivotDetectionLoopbac; // Pivots Detection Loopback ...
|
|
|
|
//
|
|
// Breaked Pivots ...
|
|
XBoxZone invalidPivots[];
|
|
|
|
//
|
|
// Constructors ...
|
|
XCXCATBEAPOIDetector(
|
|
XCX121XCatbHelper *_helper //
|
|
)
|
|
{
|
|
//
|
|
helper = _helper;
|
|
barAnalyser = new XCBarAnalyser();
|
|
|
|
//
|
|
Default();
|
|
}
|
|
|
|
//
|
|
// De Constructors ...
|
|
~XCXCATBEAPOIDetector()
|
|
{
|
|
//
|
|
CleanPivots();
|
|
|
|
//
|
|
ZeroMemory(helper);
|
|
|
|
//
|
|
delete barAnalyser;
|
|
ZeroMemory(barAnalyser);
|
|
}
|
|
|
|
//
|
|
// Properties ...
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
virtual void Default()
|
|
{
|
|
//
|
|
// COMMON ...
|
|
|
|
//
|
|
maxAllowedPivots = 50;
|
|
pivotVerifications = 5;
|
|
pivotDetectionLoopbac = 100;
|
|
|
|
//
|
|
// PV ...
|
|
|
|
//
|
|
maxAllowedPVLifetime = 0;
|
|
selectRejectedPVPivots = false;
|
|
selectEngulfedPVPivots = false;
|
|
|
|
//
|
|
detectPeakPivots = false;
|
|
detectValePivots = false;
|
|
|
|
//
|
|
detectMTBullishPivots = false;
|
|
detectMTBearishPivots = false;
|
|
|
|
//
|
|
detectOBBullishPivots = false;
|
|
detectOBBearishPivots = false;
|
|
}
|
|
|
|
//
|
|
void Detect(
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
int loopback = pivotDetectionLoopbac;
|
|
loopback = NormalizeInt(loopback, 50);
|
|
|
|
//
|
|
int idx = -1;
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
int zIDX = 0;
|
|
int cIDX = zIDX + 1;
|
|
int pIDX = cIDX + 1;
|
|
int p2IDX = pIDX + 1;
|
|
int p3IDX = p2IDX + 1;
|
|
|
|
//
|
|
newPeakPivotDetected = false;
|
|
newValePivotDetected = false;
|
|
newMTBullishPivotDetected = false;
|
|
newMTBearishPivotDetected = false;
|
|
newOBBullishPivotDetected = false;
|
|
newOBBearishPivotDetected = false;
|
|
|
|
//
|
|
int index = barIndex;
|
|
int start = index;
|
|
int end = index + loopback;
|
|
while (start < end)
|
|
{
|
|
//
|
|
// Retrieve Conditions ...
|
|
X121XCatbConditions conditions;
|
|
has = helper.GetConditions(
|
|
conditions,
|
|
start,
|
|
10 //
|
|
);
|
|
if (!has)
|
|
{
|
|
conditions.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Retrieve Bars ...
|
|
XOHCL zBar;
|
|
XOHCL cBar;
|
|
XOHCL pBar;
|
|
XOHCL p2Bar;
|
|
has = zBar.Init(
|
|
conditions.symbol,
|
|
conditions.period,
|
|
start //
|
|
);
|
|
has =
|
|
has &&
|
|
zBar.GetPreviousBar(cBar);
|
|
has =
|
|
has &&
|
|
cBar.GetPreviousBar(pBar);
|
|
has =
|
|
has &&
|
|
pBar.GetPreviousBar(p2Bar);
|
|
if (!has)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
conditions.Clean();
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Checking Pivots ...
|
|
|
|
//
|
|
// PV ...
|
|
|
|
//
|
|
// PEAK ...
|
|
if (detectPeakPivots)
|
|
{
|
|
//
|
|
newPeakPivotDetected = DetectPeakAndValePivot(
|
|
barIndex,
|
|
X_DIRECTION_BEARISH,
|
|
zBar,
|
|
cBar,
|
|
pBar,
|
|
p2Bar,
|
|
conditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
// VALE ...
|
|
if (detectValePivots)
|
|
{
|
|
//
|
|
newValePivotDetected = DetectPeakAndValePivot(
|
|
barIndex,
|
|
X_DIRECTION_BULLISH,
|
|
zBar,
|
|
cBar,
|
|
pBar,
|
|
p2Bar,
|
|
conditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
// MT ...
|
|
|
|
//
|
|
// Bullish ...
|
|
if (detectMTBullishPivots)
|
|
{
|
|
//
|
|
newMTBullishPivotDetected = DetectMTPivot(
|
|
barIndex,
|
|
X_DIRECTION_BULLISH,
|
|
zBar,
|
|
cBar,
|
|
pBar,
|
|
p2Bar,
|
|
conditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
if (detectMTBearishPivots)
|
|
{
|
|
//
|
|
newMTBearishPivotDetected = DetectMTPivot(
|
|
barIndex,
|
|
X_DIRECTION_BEARISH,
|
|
zBar,
|
|
cBar,
|
|
pBar,
|
|
p2Bar,
|
|
conditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
// OB ...
|
|
|
|
//
|
|
// Bullish ...
|
|
if (detectOBBullishPivots)
|
|
{
|
|
//
|
|
newOBBullishPivotDetected = DetectOBPivot(
|
|
barIndex,
|
|
X_DIRECTION_BULLISH,
|
|
zBar,
|
|
cBar,
|
|
pBar,
|
|
p2Bar,
|
|
conditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
if (detectOBBearishPivots)
|
|
{
|
|
//
|
|
newOBBearishPivotDetected = DetectOBPivot(
|
|
barIndex,
|
|
X_DIRECTION_BEARISH,
|
|
zBar,
|
|
cBar,
|
|
pBar,
|
|
p2Bar,
|
|
conditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Others ...
|
|
|
|
//
|
|
start++;
|
|
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
conditions.Clean();
|
|
}
|
|
|
|
//
|
|
SortPivots();
|
|
}
|
|
|
|
//
|
|
void Validate(
|
|
XBoxZone &unavailables[],
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
// Implement Validation Senarios ...
|
|
|
|
//
|
|
// PV ...
|
|
ValidatePeakValePivots(
|
|
unavailables,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
// MT ...
|
|
ValidateMTPivots(
|
|
unavailables,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
// OB ...
|
|
ValidateOBPivots(
|
|
unavailables,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
SortPivots();
|
|
}
|
|
|
|
//
|
|
void CleanPivots()
|
|
{
|
|
//
|
|
Clean(invalidPivots);
|
|
|
|
//
|
|
peakPivot.Clean();
|
|
valePivot.Clean();
|
|
|
|
//
|
|
Clean(peakPivots);
|
|
Clean(valePivots);
|
|
|
|
//
|
|
Clean(mtBullishPivots);
|
|
Clean(mtBearishPivots);
|
|
|
|
//
|
|
Clean(obBullishPivots);
|
|
Clean(obBearishPivots);
|
|
}
|
|
|
|
//
|
|
// Pivots ...
|
|
|
|
//
|
|
// INVALID Pivots ...
|
|
|
|
//
|
|
bool HasInvalidPivots()
|
|
{
|
|
return HasChild(invalidPivots);
|
|
}
|
|
|
|
//
|
|
int CountInvalidPivots()
|
|
{
|
|
return ArraySize(invalidPivots);
|
|
}
|
|
|
|
//
|
|
// PV ...
|
|
|
|
//
|
|
int maxAllowedPVLifetime; // Max Allowed PV Life ...
|
|
bool selectRejectedPVPivots; // Select Rejected PV Pivots ...
|
|
bool selectEngulfedPVPivots; // Select Engulfed PV Pivots ...
|
|
|
|
//
|
|
bool DetectPeakAndValePivot(
|
|
int barIndex,
|
|
ENUM_X_DIRECTION forDir,
|
|
XOHCL &zBar,
|
|
XOHCL &cBar,
|
|
XOHCL &pBar,
|
|
XOHCL &p2Bar,
|
|
X121XCatbConditions &conditions //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Checking Direction ...
|
|
result = HasDirection(forDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool forBullish = IsBullish(forDir);
|
|
bool forBearish = IsBearish(forDir);
|
|
|
|
//
|
|
// Check Allowed ...
|
|
result =
|
|
forBullish
|
|
? detectValePivots
|
|
: detectPeakPivots;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Args ...
|
|
result =
|
|
//
|
|
barIndex >= 0 &&
|
|
zBar.IsValid() &&
|
|
cBar.IsValid() &&
|
|
pBar.IsValid() &&
|
|
p2Bar.IsValid()
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Define Requirements ...
|
|
|
|
//
|
|
int zIDX = 0;
|
|
int cIDX = zIDX + 1;
|
|
int pIDX = cIDX + 1;
|
|
int p2IDX = pIDX + 1;
|
|
|
|
//
|
|
datetime cTime = zBar.time;
|
|
string symbol = zBar.symbol;
|
|
ENUM_TIMEFRAMES period = zBar.period;
|
|
double points = GetPoints(symbol);
|
|
|
|
//
|
|
// Reading Conditional Values ...
|
|
|
|
//
|
|
// PEAK ...
|
|
double zPeak = conditions.peakBuffer[zIDX];
|
|
double cPeak = conditions.peakBuffer[cIDX];
|
|
double pPeak = conditions.peakBuffer[pIDX];
|
|
double p2Peak = conditions.peakBuffer[p2IDX];
|
|
|
|
//
|
|
// PEAK Golden ...
|
|
double zPeakGolden = conditions.peakGoldenBuffer[zIDX];
|
|
double cPeakGolden = conditions.peakGoldenBuffer[cIDX];
|
|
double pPeakGolden = conditions.peakGoldenBuffer[pIDX];
|
|
double p2PeakGolden = conditions.peakGoldenBuffer[p2IDX];
|
|
|
|
//
|
|
// VALE ...
|
|
double zVale = conditions.valeBuffer[zIDX];
|
|
double cVale = conditions.valeBuffer[cIDX];
|
|
double pVale = conditions.valeBuffer[pIDX];
|
|
double p2Vale = conditions.valeBuffer[p2IDX];
|
|
|
|
//
|
|
// VALE Golden ...
|
|
double zValeGolden = conditions.valeGoldenBuffer[zIDX];
|
|
double cValeGolden = conditions.valeGoldenBuffer[cIDX];
|
|
double pValeGolden = conditions.valeGoldenBuffer[pIDX];
|
|
double p2ValeGolden = conditions.valeGoldenBuffer[p2IDX];
|
|
|
|
//
|
|
// Detecting Bar Conditions ...
|
|
|
|
//
|
|
ENUM_X_DIRECTION cBarDir;
|
|
|
|
//
|
|
// Rejected ...
|
|
bool isCBarRejected = barAnalyser
|
|
.IsRejected(
|
|
cBar,
|
|
cBarDir,
|
|
false, // Force Type ...
|
|
false // Force Fibo Pressure ...
|
|
);
|
|
|
|
//
|
|
bool isCBarBullishRejected =
|
|
forBullish &&
|
|
isCBarRejected &&
|
|
IsBullish(cBarDir);
|
|
bool isCBarBearishRejected =
|
|
forBearish &&
|
|
isCBarRejected &&
|
|
IsBearish(cBarDir);
|
|
|
|
//
|
|
bool isPBarRejected = barAnalyser
|
|
.IsRejected(
|
|
pBar,
|
|
cBarDir,
|
|
false, // Force Type ...
|
|
false // Force Fibo Pressure ...
|
|
);
|
|
bool isPBarBullishRejected =
|
|
forBullish &&
|
|
isPBarRejected &&
|
|
IsBullish(cBarDir);
|
|
bool isPBarBearishRejected =
|
|
forBearish &&
|
|
isPBarRejected &&
|
|
IsBearish(cBarDir);
|
|
|
|
//
|
|
bool isBarBullishRejected =
|
|
forBullish &&
|
|
(isCBarBullishRejected ||
|
|
isPBarBullishRejected);
|
|
|
|
//
|
|
bool isBarBearishRejected =
|
|
forBearish &&
|
|
(isCBarBearishRejected ||
|
|
isPBarBearishRejected);
|
|
|
|
//
|
|
// Engulfed ...
|
|
bool isCBarEngulfed = barAnalyser
|
|
.IsEngulfed(
|
|
cBar,
|
|
cBarDir //
|
|
);
|
|
bool isCBarBullishEngulfed =
|
|
forBullish &&
|
|
isCBarEngulfed &&
|
|
IsBullish(cBarDir);
|
|
bool isCBarBearishEngulfed =
|
|
forBearish &&
|
|
isCBarEngulfed &&
|
|
IsBearish(cBarDir);
|
|
|
|
//
|
|
bool isPBarEngulfed = barAnalyser
|
|
.IsEngulfed(
|
|
pBar,
|
|
cBarDir //
|
|
);
|
|
bool isPBarBullishEngulfed =
|
|
forBullish &&
|
|
isPBarEngulfed &&
|
|
IsBullish(cBarDir);
|
|
bool isPBarBearishEngulfed =
|
|
forBearish &&
|
|
isPBarEngulfed &&
|
|
IsBearish(cBarDir);
|
|
|
|
//
|
|
bool isBarBullishEngulfed =
|
|
forBullish &&
|
|
(isCBarBullishEngulfed ||
|
|
isPBarBullishEngulfed);
|
|
|
|
//
|
|
bool isBarBearishEngulfed =
|
|
forBearish &&
|
|
(isCBarBearishEngulfed ||
|
|
isPBarBearishEngulfed);
|
|
|
|
//
|
|
// Prepare Conditinal Conditions ...
|
|
|
|
//
|
|
// PEAK ...
|
|
|
|
//
|
|
bool isPeakSameLast = cPeak == pPeak;
|
|
bool isPeakSameLastPrev = pPeak == p2Peak;
|
|
|
|
//
|
|
bool isPeakSwitchedToSameLast = isPeakSameLast &&
|
|
!isPeakSameLastPrev;
|
|
bool isPeakFinishedFromSameLast = !isPeakSameLast &&
|
|
isPeakSameLastPrev;
|
|
|
|
//
|
|
// VALE ...
|
|
|
|
//
|
|
bool isValeSameLast = cVale == pVale;
|
|
bool isValeSameLastPrev = pVale == p2Vale;
|
|
|
|
//
|
|
bool isValeSwitchedToSameLast = isValeSameLast &&
|
|
!isValeSameLastPrev;
|
|
bool isValeFinishedFromSameLast = !isValeSameLast &&
|
|
isValeSameLastPrev;
|
|
|
|
//
|
|
// Summarizing Conditions ...
|
|
|
|
//
|
|
result = false;
|
|
|
|
//
|
|
bool hasStartCondition =
|
|
//
|
|
forBullish
|
|
? isValeFinishedFromSameLast
|
|
: isPeakFinishedFromSameLast
|
|
//
|
|
;
|
|
|
|
//
|
|
bool hasContinuationCondition =
|
|
//
|
|
forBullish
|
|
? isValeSameLast
|
|
: isPeakSameLast
|
|
//
|
|
;
|
|
|
|
//
|
|
bool hasEndCondition =
|
|
//
|
|
forBullish
|
|
? isValeSwitchedToSameLast
|
|
: isPeakSwitchedToSameLast
|
|
//
|
|
;
|
|
|
|
//
|
|
// Apply Validations ...
|
|
if (hasEndCondition)
|
|
{
|
|
//
|
|
bool hasSelectionType = selectRejectedPVPivots ||
|
|
selectEngulfedPVPivots;
|
|
|
|
//
|
|
bool isPVRejected =
|
|
forBullish
|
|
? (isBarBullishRejected &&
|
|
selectRejectedPVPivots)
|
|
: (isBarBearishRejected &&
|
|
selectRejectedPVPivots);
|
|
|
|
//
|
|
bool isPVEngulfed =
|
|
forBullish
|
|
? (isBarBullishEngulfed &&
|
|
selectEngulfedPVPivots)
|
|
: (isBarBearishEngulfed &&
|
|
selectEngulfedPVPivots);
|
|
|
|
//
|
|
bool isBarPassed =
|
|
!hasSelectionType
|
|
? true
|
|
: isPVRejected ||
|
|
isPVEngulfed;
|
|
|
|
//
|
|
hasEndCondition =
|
|
isBarPassed &&
|
|
hasEndCondition;
|
|
if (!hasEndCondition)
|
|
{
|
|
//
|
|
// VALE ...
|
|
if (forBullish)
|
|
{
|
|
valePivot.Clean();
|
|
}
|
|
|
|
//
|
|
// PEAK ...
|
|
if (forBearish)
|
|
{
|
|
peakPivot.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
//
|
|
// ReInstance Pivot ...
|
|
if (hasStartCondition)
|
|
{
|
|
//
|
|
// VALE ...
|
|
if (forBullish)
|
|
{
|
|
//
|
|
valePivot.Clean();
|
|
|
|
//
|
|
valePivot.type = XCATB_VALE;
|
|
valePivot.symbol = symbol;
|
|
valePivot.period = period;
|
|
|
|
//
|
|
valePivot.to = pBar.time;
|
|
valePivot.from = pBar.time;
|
|
valePivot.value = pVale;
|
|
valePivot.reserve = pValeGolden;
|
|
}
|
|
|
|
//
|
|
// PEAK ...
|
|
if (forBearish)
|
|
{
|
|
//
|
|
peakPivot.Clean();
|
|
|
|
//
|
|
peakPivot.type = XCATB_PEAK;
|
|
peakPivot.symbol = symbol;
|
|
peakPivot.period = period;
|
|
|
|
//
|
|
peakPivot.to = pBar.time;
|
|
peakPivot.from = pBar.time;
|
|
peakPivot.value = pPeak;
|
|
peakPivot.reserve = pPeakGolden;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Calculate and Fill Pivot Requirements ...
|
|
if (hasContinuationCondition)
|
|
{
|
|
//
|
|
// VALE ...
|
|
if (forBullish)
|
|
{
|
|
//
|
|
valePivot.from = pBar.time;
|
|
|
|
//
|
|
valePivot.reserve =
|
|
valePivot.reserve == 0
|
|
? pValeGolden
|
|
: MathMin(valePivot.reserve, pValeGolden);
|
|
}
|
|
|
|
//
|
|
// PEAK ...
|
|
if (forBearish)
|
|
{
|
|
//
|
|
peakPivot.from = pBar.time;
|
|
|
|
//
|
|
peakPivot.reserve =
|
|
peakPivot.reserve == 0
|
|
? pPeakGolden
|
|
: MathMax(peakPivot.reserve, pPeakGolden);
|
|
}
|
|
}
|
|
|
|
//
|
|
// End up Pivot and Store it ...
|
|
if (hasEndCondition)
|
|
{
|
|
//
|
|
// VALE ...
|
|
if (forBullish)
|
|
{
|
|
//
|
|
result =
|
|
valePivot.IsValid() &&
|
|
valePivot.GetAge() >= pivotVerifications;
|
|
if (result)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
result = valePivot.AsBox(iBox);
|
|
if (result)
|
|
{
|
|
//
|
|
newValePivotDetected = AddBox(
|
|
iBox,
|
|
valePivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
valePivot.Clean();
|
|
}
|
|
|
|
//
|
|
// PEAK ...
|
|
if (forBearish)
|
|
{
|
|
//
|
|
result =
|
|
peakPivot.IsValid() &&
|
|
peakPivot.GetAge() >= pivotVerifications;
|
|
if (result)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
result = peakPivot.AsBox(iBox);
|
|
if (result)
|
|
{
|
|
//
|
|
newPeakPivotDetected = AddBox(
|
|
iBox,
|
|
peakPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
peakPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void ValidatePeakValePivots(
|
|
XBoxZone &unavailables[],
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool has = false;
|
|
|
|
//
|
|
bool applyLifetimeValidating = maxAllowedPVLifetime > 0;
|
|
|
|
//
|
|
// PEAK ...
|
|
has = HasPeakPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBoxes(
|
|
peakPivots,
|
|
unavailables,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
if (applyLifetimeValidating)
|
|
{
|
|
//
|
|
ApplyLifeTimeValidationOnBoxes(
|
|
peakPivots,
|
|
maxAllowedPVLifetime,
|
|
barIndex //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// VALE ...
|
|
has = HasValePivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBoxes(
|
|
valePivots,
|
|
unavailables,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
if (applyLifetimeValidating)
|
|
{
|
|
//
|
|
ApplyLifeTimeValidationOnBoxes(
|
|
valePivots,
|
|
maxAllowedPVLifetime,
|
|
barIndex //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// PEAK ...
|
|
|
|
//
|
|
XCATBPivot peakPivot;
|
|
bool detectPeakPivots;
|
|
XBoxZone peakPivots[];
|
|
bool newPeakPivotDetected;
|
|
|
|
//
|
|
bool HasPeakPivots()
|
|
{
|
|
return HasChild(peakPivots);
|
|
}
|
|
|
|
//
|
|
int CountPeakPivots()
|
|
{
|
|
return ArraySize(peakPivots);
|
|
}
|
|
|
|
//
|
|
int FillPeakPivots(XBoxZone &pivots[])
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(pivots);
|
|
|
|
//
|
|
if (!HasPeakPivots())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = CountPeakPivots();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iPivot = peakPivots[i];
|
|
|
|
//
|
|
AddRef(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
iPivot.Clean();
|
|
}
|
|
|
|
//
|
|
result = ArraySize(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// VALE ...
|
|
|
|
//
|
|
XCATBPivot valePivot;
|
|
bool detectValePivots;
|
|
XBoxZone valePivots[];
|
|
bool newValePivotDetected;
|
|
|
|
//
|
|
bool HasValePivots()
|
|
{
|
|
return HasChild(valePivots);
|
|
}
|
|
|
|
//
|
|
int CountValePivots()
|
|
{
|
|
return ArraySize(valePivots);
|
|
}
|
|
|
|
//
|
|
int FillValePivots(XBoxZone &pivots[])
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(pivots);
|
|
|
|
//
|
|
if (!HasValePivots())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = CountValePivots();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iPivot = valePivots[i];
|
|
|
|
//
|
|
AddRef(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
iPivot.Clean();
|
|
}
|
|
|
|
//
|
|
result = ArraySize(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// MITIGATIONBLOCK ...
|
|
|
|
//
|
|
int maxAllowedMTLifetime; // Max Allowed MT Life ...
|
|
|
|
//
|
|
bool DetectMTPivot(
|
|
int barIndex,
|
|
ENUM_X_DIRECTION forDir,
|
|
XOHCL &zBar,
|
|
XOHCL &cBar,
|
|
XOHCL &pBar,
|
|
XOHCL &p2Bar,
|
|
X121XCatbConditions &conditions //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Checking Direction ...
|
|
result = HasDirection(forDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool forBullish = IsBullish(forDir);
|
|
bool forBearish = IsBearish(forDir);
|
|
|
|
//
|
|
// Check Allowed ...
|
|
result =
|
|
forBullish
|
|
? detectMTBullishPivots
|
|
: detectMTBearishPivots;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Args ...
|
|
result =
|
|
//
|
|
barIndex >= 0 &&
|
|
zBar.IsValid() &&
|
|
cBar.IsValid() &&
|
|
pBar.IsValid() &&
|
|
p2Bar.IsValid()
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Define Requirements ...
|
|
|
|
//
|
|
int zIDX = 0;
|
|
int cIDX = zIDX + 1;
|
|
int pIDX = cIDX + 1;
|
|
int p2IDX = pIDX + 1;
|
|
|
|
//
|
|
datetime cTime = zBar.time;
|
|
string symbol = zBar.symbol;
|
|
ENUM_TIMEFRAMES period = zBar.period;
|
|
double points = GetPoints(symbol);
|
|
|
|
//
|
|
// Detecting Bar Conditions ...
|
|
|
|
//
|
|
ENUM_X_DIRECTION cBarDir;
|
|
|
|
//
|
|
// Rejected ...
|
|
bool isCBarRejected = barAnalyser
|
|
.IsRejected(
|
|
cBar,
|
|
cBarDir,
|
|
false, // Force Type ...
|
|
true // Force Fibo Pressure ...
|
|
);
|
|
|
|
//
|
|
bool isCBarBullishRejected =
|
|
forBullish &&
|
|
isCBarRejected &&
|
|
IsBullish(cBarDir);
|
|
bool isCBarBearishRejected =
|
|
forBearish &&
|
|
isCBarRejected &&
|
|
IsBearish(cBarDir);
|
|
|
|
//
|
|
// Prepare Conditinal Conditions ...
|
|
|
|
//
|
|
// Summarizing Conditions ...
|
|
|
|
//
|
|
result = false;
|
|
|
|
//
|
|
bool hasEndCondition =
|
|
//
|
|
forBullish
|
|
? isCBarBullishRejected
|
|
: isCBarBearishRejected
|
|
//
|
|
;
|
|
|
|
//
|
|
// End up Pivot and Store it ...
|
|
if (hasEndCondition)
|
|
{
|
|
//
|
|
XBoxZone iPivot;
|
|
iPivot.to = zBar.time;
|
|
iPivot.from = cBar.time;
|
|
iPivot.symbol = cBar.symbol;
|
|
iPivot.period = cBar.period;
|
|
|
|
//
|
|
// Bullish ...
|
|
if (forBullish)
|
|
{
|
|
//
|
|
iPivot.lower = cBar.low;
|
|
iPivot.upper = cBar.GetDown();
|
|
iPivot.dir = X_DIRECTION_BULLISH;
|
|
iPivot.type = GetBoxType(XCATB_BULLISH_MT);
|
|
|
|
//
|
|
result = iPivot.IsValid();
|
|
if (result)
|
|
{
|
|
//
|
|
newMTBullishPivotDetected = AddBox(
|
|
iPivot,
|
|
mtBullishPivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
if (forBearish)
|
|
{
|
|
//
|
|
iPivot.upper = cBar.high;
|
|
iPivot.lower = cBar.GetUp();
|
|
iPivot.dir = X_DIRECTION_BEARISH;
|
|
iPivot.type = GetBoxType(XCATB_BEARISH_MT);
|
|
|
|
//
|
|
result = iPivot.IsValid();
|
|
if (result)
|
|
{
|
|
//
|
|
newMTBearishPivotDetected = AddBox(
|
|
iPivot,
|
|
mtBearishPivots //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void ValidateMTPivots(
|
|
XBoxZone &unavailables[],
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool has = false;
|
|
|
|
//
|
|
bool applyLifetimeValidating = maxAllowedMTLifetime > 0;
|
|
|
|
//
|
|
// Bullish ...
|
|
has = HasMTBullishPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBoxes(
|
|
mtBullishPivots,
|
|
unavailables,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
if (applyLifetimeValidating)
|
|
{
|
|
//
|
|
ApplyLifeTimeValidationOnBoxes(
|
|
mtBullishPivots,
|
|
maxAllowedMTLifetime,
|
|
barIndex //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
has = HasMTBearishPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBoxes(
|
|
mtBearishPivots,
|
|
unavailables,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
if (applyLifetimeValidating)
|
|
{
|
|
//
|
|
ApplyLifeTimeValidationOnBoxes(
|
|
mtBearishPivots,
|
|
maxAllowedMTLifetime,
|
|
barIndex //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bullish ...
|
|
XBoxZone mtBullishPivots[];
|
|
bool detectMTBullishPivots;
|
|
bool newMTBullishPivotDetected;
|
|
|
|
//
|
|
bool HasMTBullishPivots()
|
|
{
|
|
return HasChild(mtBullishPivots);
|
|
}
|
|
|
|
//
|
|
int CountMTBullishPivots()
|
|
{
|
|
return ArraySize(mtBullishPivots);
|
|
}
|
|
|
|
//
|
|
int FillMTBullishPivots(XBoxZone &pivots[])
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(pivots);
|
|
|
|
//
|
|
if (!HasMTBullishPivots())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = CountMTBullishPivots();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iPivot = mtBullishPivots[i];
|
|
|
|
//
|
|
AddRef(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
iPivot.Clean();
|
|
}
|
|
|
|
//
|
|
result = ArraySize(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
XBoxZone mtBearishPivots[];
|
|
bool detectMTBearishPivots;
|
|
bool newMTBearishPivotDetected;
|
|
|
|
//
|
|
bool HasMTBearishPivots()
|
|
{
|
|
return HasChild(mtBearishPivots);
|
|
}
|
|
|
|
//
|
|
int CountMTBearishPivots()
|
|
{
|
|
return ArraySize(mtBearishPivots);
|
|
}
|
|
|
|
//
|
|
int FillMTBearishPivots(XBoxZone &pivots[])
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(pivots);
|
|
|
|
//
|
|
if (!HasMTBearishPivots())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = CountMTBearishPivots();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iPivot = mtBearishPivots[i];
|
|
|
|
//
|
|
AddRef(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
iPivot.Clean();
|
|
}
|
|
|
|
//
|
|
result = ArraySize(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// ORDERBLOCK ...
|
|
|
|
//
|
|
int maxAllowedOBLifetime; // Max Allowed MT Life ...
|
|
|
|
//
|
|
bool DetectOBPivot(
|
|
int barIndex,
|
|
ENUM_X_DIRECTION forDir,
|
|
XOHCL &zBar,
|
|
XOHCL &cBar,
|
|
XOHCL &pBar,
|
|
XOHCL &p2Bar,
|
|
X121XCatbConditions &conditions //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Checking Direction ...
|
|
result = HasDirection(forDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool forBullish = IsBullish(forDir);
|
|
bool forBearish = IsBearish(forDir);
|
|
|
|
//
|
|
// Check Allowed ...
|
|
result =
|
|
forBullish
|
|
? detectOBBullishPivots
|
|
: detectOBBearishPivots;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Args ...
|
|
result =
|
|
//
|
|
barIndex >= 0 &&
|
|
zBar.IsValid() &&
|
|
cBar.IsValid() &&
|
|
pBar.IsValid() &&
|
|
p2Bar.IsValid()
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Define Requirements ...
|
|
|
|
//
|
|
int zIDX = 0;
|
|
int cIDX = zIDX + 1;
|
|
int pIDX = cIDX + 1;
|
|
int p2IDX = pIDX + 1;
|
|
|
|
//
|
|
datetime cTime = zBar.time;
|
|
string symbol = zBar.symbol;
|
|
ENUM_TIMEFRAMES period = zBar.period;
|
|
double points = GetPoints(symbol);
|
|
|
|
//
|
|
XBoxZone iPivot;
|
|
|
|
//
|
|
// Detecting Bar Conditions ...
|
|
|
|
//
|
|
|
|
//
|
|
// OB ...
|
|
bool isOB = barAnalyser
|
|
.IsOB(
|
|
cBar,
|
|
iPivot,
|
|
false,
|
|
false //
|
|
);
|
|
|
|
//
|
|
bool isBullishOB =
|
|
isOB &&
|
|
iPivot.IsBullish();
|
|
bool isBearishOB =
|
|
isOB &&
|
|
iPivot.IsBearish();
|
|
|
|
//
|
|
// Prepare Conditinal Conditions ...
|
|
|
|
//
|
|
// Summarizing Conditions ...
|
|
|
|
//
|
|
result = false;
|
|
|
|
//
|
|
bool hasEndCondition =
|
|
//
|
|
forBullish
|
|
? isBullishOB
|
|
: isBearishOB
|
|
//
|
|
;
|
|
|
|
//
|
|
// End up Pivot and Store it ...
|
|
if (hasEndCondition)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
if (forBullish)
|
|
{
|
|
//
|
|
iPivot.type = GetBoxType(XCATB_BULLISH_OB);
|
|
|
|
//
|
|
result = iPivot.IsValid();
|
|
if (result)
|
|
{
|
|
//
|
|
newOBBullishPivotDetected = AddBox(
|
|
iPivot,
|
|
obBullishPivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
if (forBearish)
|
|
{
|
|
//
|
|
iPivot.type = GetBoxType(XCATB_BEARISH_OB);
|
|
|
|
//
|
|
result = iPivot.IsValid();
|
|
if (result)
|
|
{
|
|
//
|
|
newOBBearishPivotDetected = AddBox(
|
|
iPivot,
|
|
obBearishPivots //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void ValidateOBPivots(
|
|
XBoxZone &unavailables[],
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool has = false;
|
|
|
|
//
|
|
bool applyLifetimeValidating = maxAllowedOBLifetime > 0;
|
|
|
|
//
|
|
// Bullish ...
|
|
has = HasOBBullishPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBoxes(
|
|
obBullishPivots,
|
|
unavailables,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
if (applyLifetimeValidating)
|
|
{
|
|
//
|
|
ApplyLifeTimeValidationOnBoxes(
|
|
obBullishPivots,
|
|
maxAllowedOBLifetime,
|
|
barIndex //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
has = HasOBBearishPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBoxes(
|
|
obBearishPivots,
|
|
unavailables,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
if (applyLifetimeValidating)
|
|
{
|
|
//
|
|
ApplyLifeTimeValidationOnBoxes(
|
|
obBearishPivots,
|
|
maxAllowedOBLifetime,
|
|
barIndex //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bullish ...
|
|
XBoxZone obBullishPivots[];
|
|
bool detectOBBullishPivots;
|
|
bool newOBBullishPivotDetected;
|
|
|
|
//
|
|
bool HasOBBullishPivots()
|
|
{
|
|
return HasChild(obBullishPivots);
|
|
}
|
|
|
|
//
|
|
int CountOBBullishPivots()
|
|
{
|
|
return ArraySize(obBullishPivots);
|
|
}
|
|
|
|
//
|
|
int FillOBBullishPivots(XBoxZone &pivots[])
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(pivots);
|
|
|
|
//
|
|
if (!HasOBBullishPivots())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = CountOBBullishPivots();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iPivot = obBullishPivots[i];
|
|
|
|
//
|
|
AddRef(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
iPivot.Clean();
|
|
}
|
|
|
|
//
|
|
result = ArraySize(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
XBoxZone obBearishPivots[];
|
|
bool detectOBBearishPivots;
|
|
bool newOBBearishPivotDetected;
|
|
|
|
//
|
|
bool HasOBBearishPivots()
|
|
{
|
|
return HasChild(obBearishPivots);
|
|
}
|
|
|
|
//
|
|
int CountOBBearishPivots()
|
|
{
|
|
return ArraySize(obBearishPivots);
|
|
}
|
|
|
|
//
|
|
int FillOBBearishPivots(XBoxZone &pivots[])
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(pivots);
|
|
|
|
//
|
|
if (!HasOBBearishPivots())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = CountOBBearishPivots();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iPivot = obBearishPivots[i];
|
|
|
|
//
|
|
AddRef(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
iPivot.Clean();
|
|
}
|
|
|
|
//
|
|
result = ArraySize(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
bool AddBox(
|
|
XBoxZone &box,
|
|
XBoxZone &boxes[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
bool isExists = 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 SortPivots()
|
|
{
|
|
//
|
|
bool has = false;
|
|
|
|
//
|
|
// Invalid Pivots ...
|
|
has = HasInvalidPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBoxes(invalidPivots);
|
|
}
|
|
|
|
//
|
|
// PV ...
|
|
|
|
//
|
|
// PEAK ...
|
|
has = HasPeakPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBoxes(peakPivots);
|
|
}
|
|
|
|
//
|
|
// VALE ...
|
|
has = HasValePivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBoxes(valePivots);
|
|
}
|
|
|
|
//
|
|
// MT Bullish ...
|
|
has = HasMTBullishPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBoxes(mtBullishPivots);
|
|
}
|
|
|
|
//
|
|
// MT Bearish ...
|
|
has = HasMTBearishPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBoxes(mtBearishPivots);
|
|
}
|
|
|
|
//
|
|
// OB Bullish ...
|
|
has = HasOBBullishPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBoxes(obBullishPivots);
|
|
}
|
|
|
|
//
|
|
// OB Bearish ...
|
|
has = HasOBBearishPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBoxes(obBearishPivots);
|
|
}
|
|
}
|
|
|
|
//
|
|
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);
|
|
}
|
|
|
|
//
|
|
// Prrivate ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
XCX121XCatbHelper *helper;
|
|
XCBarAnalyser *barAnalyser;
|
|
|
|
//
|
|
};
|
|
|
|
// |