3471 lines
55 KiB
Plaintext
3471 lines
55 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Seriallize Library
|
|
// ---------------------------------------
|
|
// Name: XPOILib
|
|
// Description: All models related to POIs ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright `023, SaherElm IT Center"
|
|
#property link "https://www.saherelm.ir"
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
#include "../Libraries/x-saherelm.x-poi.lib.mq5"
|
|
|
|
//
|
|
// Extensions ...
|
|
|
|
template <typename T>
|
|
bool ToZone(
|
|
T *&source[],
|
|
XCZone *&dest[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(dest);
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
result = IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
T *item = source[i];
|
|
|
|
//
|
|
if (item != NULL)
|
|
{
|
|
//
|
|
Add(
|
|
(XCZone *)item,
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
int destCount = ArraySize(dest);
|
|
result = IsValidSize(destCount);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool ToBox(
|
|
T *&source[],
|
|
XBoxZone &dest[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(dest);
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
result = IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
T *item = source[i];
|
|
|
|
//
|
|
if (item != NULL)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
bool hasBox = ToBox(
|
|
iBox,
|
|
item //
|
|
);
|
|
|
|
//
|
|
if (hasBox)
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
int destCount = ArraySize(dest);
|
|
result = IsValidSize(destCount);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetOldest(
|
|
T *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetOldest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetYoungest(
|
|
T *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetYoungest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetLowest(
|
|
T *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetLowest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetHighest(
|
|
T *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetHighest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsSame(
|
|
T *source,
|
|
T *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = sourceBox.IsSameAs(destBox);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename F>
|
|
bool IsSameDiff(
|
|
T *source,
|
|
F *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = sourceBox.IsSame(destBox);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsBelow(
|
|
T *source,
|
|
T *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxBelow(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename F>
|
|
bool IsBelowDiff(
|
|
T *source,
|
|
F *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxBelow(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsAbove(
|
|
T *source,
|
|
T *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxAbove(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename F>
|
|
bool IsAboveDiff(
|
|
T *source,
|
|
F *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxAbove(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsInside(
|
|
T *source,
|
|
T *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxInside(
|
|
sourceBox,
|
|
destBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsInsideOr(
|
|
T *source,
|
|
T *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxInsideOr(
|
|
sourceBox,
|
|
destBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename F>
|
|
bool IsInsideDiff(
|
|
T *source,
|
|
F *dest,
|
|
bool forceSideOut = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxInside(
|
|
sourceBox,
|
|
destBox,
|
|
forceSideOut //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename F>
|
|
bool IsInsideOrDiff(
|
|
T *source,
|
|
F *dest,
|
|
bool forceSideOut = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxInsideOr(
|
|
sourceBox,
|
|
destBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool FindIndex(
|
|
int &index,
|
|
T *item,
|
|
T *&items[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
XBoxZone itemBox;
|
|
result = ToBox(
|
|
itemBox,
|
|
item //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone itemsBox[];
|
|
result = ToBox(
|
|
items,
|
|
itemsBox //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = FindBoxIndex(
|
|
index,
|
|
itemBox,
|
|
itemsBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsInside(
|
|
double value,
|
|
T *source //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsInsideBox(
|
|
value,
|
|
sourceBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsAbove(
|
|
double value,
|
|
T *source //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsAboveBox(
|
|
value,
|
|
sourceBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsBelow(
|
|
double value,
|
|
T *source //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBelowBox(
|
|
value,
|
|
sourceBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Find Specified Box Index inside a Collection of Boxes ...
|
|
*
|
|
* @param box: XBoxZone instance Reference ...
|
|
* @param boxes: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
bool FindBoxIndex(
|
|
int &index,
|
|
XBoxZone &box,
|
|
XBoxZone &boxes[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
int count = ArraySize(boxes);
|
|
result = box.IsValid() &&
|
|
IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = boxes[i];
|
|
|
|
//
|
|
bool isSame = box.IsSameAs(iBox);
|
|
if (isSame)
|
|
{
|
|
//
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Source Box is Below Dest ...
|
|
*
|
|
* @param source: XBoxZone instance Reference ...
|
|
* @param dest: XBoxZone instance Reference ...
|
|
* @param ignoreInside: bool ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxBelow(
|
|
XBoxZone &source,
|
|
XBoxZone &dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSameAs(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!ignoreInside)
|
|
{
|
|
result = source.upper < dest.lower;
|
|
}
|
|
else
|
|
{
|
|
result = (source.upper < dest.lower ||
|
|
source.upper >= dest.upper) &&
|
|
source.lower < dest.lower;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Source Box is Above Dest ...
|
|
*
|
|
* @param source: XBoxZone instance Reference ...
|
|
* @param dest: XBoxZone instance Reference ...
|
|
* @param ignoreInside: bool ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxAbove(
|
|
XBoxZone &source,
|
|
XBoxZone &dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSameAs(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!ignoreInside)
|
|
{
|
|
result = source.lower > dest.upper;
|
|
}
|
|
else
|
|
{
|
|
result = (source.lower > dest.upper ||
|
|
source.lower <= dest.upper) &&
|
|
source.upper > dest.upper;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Source Box is Inside Dest ...
|
|
*
|
|
* @param source: XBoxZone instance Reference ...
|
|
* @param dest: XBoxZone instance Reference ...
|
|
* @param forceSideOut: bool, force check Box has One Side Out ...
|
|
* @param ignoreSideOut: bool, Accept if source Box one Side is out of Dest Box ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxInside(
|
|
XBoxZone &source,
|
|
XBoxZone &dest,
|
|
bool forceSideOut = false, //
|
|
bool ignoreSideOut = true //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSameAs(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(dest.dir);
|
|
|
|
//
|
|
if (!forceSideOut)
|
|
{
|
|
//
|
|
if (ignoreSideOut)
|
|
{
|
|
//
|
|
result = source.lower >= dest.lower &&
|
|
source.upper <= dest.upper;
|
|
}
|
|
else
|
|
{
|
|
result = source.lower >= dest.lower ||
|
|
source.upper <= dest.upper;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
bool hasSideIn =
|
|
isBullish
|
|
? source.lower >= dest.lower
|
|
: source.upper <= dest.upper;
|
|
bool hasSideOut =
|
|
isBullish
|
|
? source.upper >= dest.upper
|
|
: source.lower <= dest.lower;
|
|
result =
|
|
hasSideIn &&
|
|
hasSideOut;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect source BoX is Inside Dest Box or Have a Side Out on it ...
|
|
*
|
|
* @param source: XBoxZone instance, source box which checks by dest ...
|
|
* @param dest: XBoxZone instance, dest Box which compares source with it ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxInsideOr(
|
|
XBoxZone &source,
|
|
XBoxZone &dest,
|
|
bool forceInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSameAs(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isInside =
|
|
source.upper <= dest.upper &&
|
|
source.upper >= dest.lower &&
|
|
source.lower >= dest.lower &&
|
|
source.lower <= dest.upper;
|
|
bool isUpperInside =
|
|
source.upper <= dest.upper &&
|
|
source.upper >= dest.lower;
|
|
bool isLowerInside =
|
|
source.lower >= dest.lower &&
|
|
source.lower <= dest.upper;
|
|
|
|
//
|
|
result =
|
|
forceInside
|
|
? isInside
|
|
: (isInside ||
|
|
isLowerInside ||
|
|
isUpperInside);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Value is Inside Specified Box ...
|
|
*
|
|
* @param value: double ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsInsideBox(
|
|
double value,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value > 0 &&
|
|
box.IsValid() &&
|
|
value <= box.upper &&
|
|
value >= box.lower;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Bar is Inside Specified Box ...
|
|
*
|
|
* @param bar: XOHCL instance reference, Specified Bar ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsInsideBox(
|
|
XOHCL &bar,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
result = bar.IsValid() &&
|
|
box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
bar.close <= box.upper &&
|
|
bar.close >= box.lower;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Value is Above Specified Box ...
|
|
*
|
|
* @param value: double ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsAboveBox(
|
|
double value,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value > 0 &&
|
|
box.IsValid() &&
|
|
value > box.upper;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Value is Below Specified Box ...
|
|
*
|
|
* @param value: double ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBelowBox(
|
|
double value,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value > 0 &&
|
|
box.IsValid() &&
|
|
value < box.lower;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Box is Used or not ...
|
|
*
|
|
* @param box: XBoxZone instance Reference ...
|
|
* @param fromIndex: int ...
|
|
* @param toIndex: int
|
|
* @param forPeriod: Specified Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxUsed(
|
|
XBoxZone &box,
|
|
int fromIndex,
|
|
int toIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (toIndex < 0)
|
|
{
|
|
toIndex = 0;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
box.IsValid() &&
|
|
fromIndex > 0 &&
|
|
fromIndex > toIndex
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = box.period;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION forDir = box.dir;
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
bool isTouched = false;
|
|
for (int i = fromIndex; i >= toIndex; i--)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
box.symbol,
|
|
forPeriod,
|
|
i //
|
|
);
|
|
|
|
//
|
|
isTouched =
|
|
isInited &&
|
|
(isBullish
|
|
? iBar.low > box.upper
|
|
: iBar.high < box.lower);
|
|
if (!isTouched)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = isTouched;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Validate Box ...
|
|
*
|
|
* @param box: XBoxZone instance ...
|
|
* @param barIndex: int, Current Bar Index ...
|
|
* @param forPeriod: Testing Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxValid(
|
|
XBoxZone &box,
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = box.period;
|
|
}
|
|
|
|
//
|
|
int toIndex = iBarShift(
|
|
box.symbol,
|
|
forPeriod,
|
|
box.to //
|
|
);
|
|
result = IsValidIndex(toIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isBullish = box.IsBullish();
|
|
for (int i = barIndex; i < toIndex; i++)
|
|
{
|
|
//
|
|
result = iBar.Init(
|
|
box.symbol,
|
|
forPeriod,
|
|
i //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result =
|
|
isBullish
|
|
? iBar.low > box.upper
|
|
: iBar.high < box.lower;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Box Breaked ...
|
|
*
|
|
* @param box: XBoxZone instance ...
|
|
* @param barIndex: int, Current Bar Index ...
|
|
* @param forPeriod: Testing Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxBreaked(
|
|
XBoxZone &box,
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = box.period;
|
|
}
|
|
|
|
//
|
|
int toIndex = iBarShift(
|
|
box.symbol,
|
|
forPeriod,
|
|
box.to //
|
|
);
|
|
result = IsValidIndex(toIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isBullish = box.IsBullish();
|
|
for (int i = barIndex; i < toIndex; i++)
|
|
{
|
|
//
|
|
result = iBar.Init(
|
|
box.symbol,
|
|
forPeriod,
|
|
i //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result =
|
|
isBullish
|
|
? iBar.high < box.lower
|
|
: iBar.low > box.upper;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Box is Breaked or not ...
|
|
*
|
|
* @param box: XBoxZone instance Reference ...
|
|
* @param fromIndex: int ...
|
|
* @param toIndex: int
|
|
* @param forPeriod: Specified Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxBreaked(
|
|
XBoxZone &box,
|
|
int fromIndex,
|
|
int toIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (toIndex < 0)
|
|
{
|
|
toIndex = 0;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
box.IsValid() &&
|
|
fromIndex > 0 &&
|
|
fromIndex > toIndex
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = box.period;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION forDir = box.dir;
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
bool isBreaked = false;
|
|
for (int i = fromIndex; i >= toIndex; i--)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
box.symbol,
|
|
forPeriod,
|
|
i //
|
|
);
|
|
|
|
//
|
|
isBreaked =
|
|
isInited &&
|
|
(isBullish
|
|
? iBar.high <= box.lower
|
|
: iBar.low >= box.upper);
|
|
if (!isBreaked)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = isBreaked;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Find an Inside Box of source in a Collection ...
|
|
*
|
|
* @param index: int, Founded Index ...
|
|
* @param source: XBoxZone instance ...
|
|
* @param dest: XBoxZone instance Collection ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasInsideBox(
|
|
int &index,
|
|
XBoxZone &source,
|
|
XBoxZone &dest[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
HasChild(dest);
|
|
|
|
//
|
|
int count = ArraySize(dest);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = dest[i];
|
|
|
|
//
|
|
bool isInside = !iBox.IsSameAs(source) &&
|
|
IsBoxInsideOr(
|
|
iBox,
|
|
source //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
index = i;
|
|
iBox.Clean();
|
|
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCOrderBlock *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = item.IsBullish()
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCFVG *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = item.IsBullish()
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCSupportZone *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCResistanceZone *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCSupplyZone *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCDemandZone *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XConsolidationZone &item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.to;
|
|
box.dir = item.dir;
|
|
box.from = item.from;
|
|
box.upper = item.upper;
|
|
box.lower = item.lower;
|
|
box.symbol = item.symbol;
|
|
box.period = item.period;
|
|
box.type = IsBullish(item.dir)
|
|
? ToString(X_BULLISH_CONSOLIDATION_ZONE)
|
|
: ToString(X_BEARISH_CONSOLIDATION_ZONE);
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
int ToBox(
|
|
XConsolidationZone &source[],
|
|
XBoxZone &dest[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(dest);
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XConsolidationZone iZone = source[i];
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
bool hasBox = ToBox(
|
|
iBox,
|
|
iZone //
|
|
);
|
|
|
|
//
|
|
if (hasBox)
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
dest //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
iZone.Clean();
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Oldest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from > iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from < iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Highest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.upper < iBox.upper;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Lowest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.lower > iBox.lower;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
/**
|
|
* Get Oldest Index ...
|
|
*
|
|
* @param source: XConsolidationZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldest(
|
|
XConsolidationZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone tmpBoxes[];
|
|
int boxesCount = ToBox(
|
|
source,
|
|
tmpBoxes //
|
|
);
|
|
if (!IsValidSize(boxesCount))
|
|
{
|
|
//
|
|
Clean(tmpBoxes);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < boxesCount; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = tmpBoxes[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from > iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(tmpBoxes);
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Index ...
|
|
*
|
|
* @param source: XConsolidationZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungest(
|
|
XConsolidationZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone tmpBoxes[];
|
|
int boxesCount = ToBox(
|
|
source,
|
|
tmpBoxes //
|
|
);
|
|
if (!IsValidSize(boxesCount))
|
|
{
|
|
//
|
|
Clean(tmpBoxes);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < boxesCount; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = tmpBoxes[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from < iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(tmpBoxes);
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Highest Index ...
|
|
*
|
|
* @param source: XConsolidationZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighest(
|
|
XConsolidationZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone tmpBoxes[];
|
|
int boxesCount = ToBox(
|
|
source,
|
|
tmpBoxes //
|
|
);
|
|
if (!IsValidSize(boxesCount))
|
|
{
|
|
//
|
|
Clean(tmpBoxes);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < boxesCount; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = tmpBoxes[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.upper < iBox.upper;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(tmpBoxes);
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Lowest Index ...
|
|
*
|
|
* @param source: XConsolidationZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowest(
|
|
XConsolidationZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone tmpBoxes[];
|
|
int boxesCount = ToBox(
|
|
source,
|
|
tmpBoxes //
|
|
);
|
|
if (!IsValidSize(boxesCount))
|
|
{
|
|
//
|
|
Clean(tmpBoxes);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < boxesCount; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = tmpBoxes[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.lower > iBox.lower;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(tmpBoxes);
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
//
|
|
template <typename T>
|
|
void SortZones(
|
|
T *&source[],
|
|
ENUM_X_DIRECTION forDir,
|
|
bool ignoreInside = true //
|
|
)
|
|
{
|
|
//
|
|
int idx = -1;
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
has = HasDirection(forDir);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
count = ArraySize(source);
|
|
has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
T *tmpItems[];
|
|
T *last = NULL;
|
|
bool hasLast = false;
|
|
while (HasChild(source))
|
|
{
|
|
//
|
|
if (!hasLast)
|
|
{
|
|
//
|
|
idx = GetOldest(source);
|
|
hasLast = IsValidIndex(idx);
|
|
if (hasLast)
|
|
{
|
|
//
|
|
last = source[idx];
|
|
ArrayRemove(
|
|
source,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
last,
|
|
tmpItems //
|
|
);
|
|
}
|
|
|
|
//
|
|
count = ArraySize(source);
|
|
has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
//
|
|
ZeroMemory(last);
|
|
break;
|
|
}
|
|
}
|
|
if (!hasLast)
|
|
{
|
|
//
|
|
ZeroMemory(last);
|
|
break;
|
|
}
|
|
|
|
//
|
|
T *item = NULL;
|
|
idx = GetOldest(source);
|
|
has = IsValidIndex(idx);
|
|
if (!has)
|
|
{
|
|
//
|
|
ZeroMemory(last);
|
|
ZeroMemory(item);
|
|
break;
|
|
}
|
|
item = source[idx];
|
|
ArrayRemove(
|
|
source,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
bool isAbove = IsAbove(
|
|
item,
|
|
last,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
bool isBelow = IsBelow(
|
|
item,
|
|
last,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
has =
|
|
isBullish
|
|
? isAbove
|
|
: isBelow;
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
item,
|
|
tmpItems //
|
|
);
|
|
|
|
//
|
|
last = item;
|
|
hasLast = item != NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(source);
|
|
Copy(
|
|
tmpItems,
|
|
source //
|
|
);
|
|
|
|
//
|
|
Clean(tmpItems);
|
|
}
|
|
|
|
/**
|
|
* Extract all Zones Which provided bar is Inside it ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
template <typename T>
|
|
int ExtractInsideZones(
|
|
XOHCL &bar, // Bar ...
|
|
T *&zones[], // Source of Zones ...
|
|
T *&dest[] // Dest (all inside Zones) ...
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(dest);
|
|
|
|
//
|
|
int count = ArraySize(zones);
|
|
bool isValid = bar.IsValid() &&
|
|
IsValidSize(count);
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
T *iZone = zones[i];
|
|
|
|
//
|
|
bool isHighInside = IsInside(
|
|
bar.high,
|
|
iZone //
|
|
);
|
|
|
|
//
|
|
bool isLowInside = IsInside(
|
|
bar.low,
|
|
iZone //
|
|
);
|
|
|
|
//
|
|
bool isInside =
|
|
isLowInside &&
|
|
isHighInside;
|
|
|
|
//
|
|
if (isInside)
|
|
{
|
|
//
|
|
Add(
|
|
iZone,
|
|
dest //
|
|
);
|
|
}
|
|
|
|
//
|
|
ZeroMemory(iZone);
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Add Specific Item into a Collection Reference only if it's not Exists ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
template <typename T>
|
|
bool AddIfNotExists(
|
|
T *item,
|
|
T *&items[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = item != NULL;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(items);
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
item,
|
|
items //
|
|
);
|
|
bool has = IsValidIndex(idx);
|
|
result = !has;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
item,
|
|
items //
|
|
);
|
|
|
|
//
|
|
int after = ArraySize(items);
|
|
|
|
//
|
|
result = after > before;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool AddIfNotExists(
|
|
XConsolidationZone &item,
|
|
XConsolidationZone &items[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(items);
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
item,
|
|
items //
|
|
);
|
|
bool has = IsValidIndex(idx);
|
|
result = !has;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
item,
|
|
items //
|
|
);
|
|
|
|
//
|
|
int after = ArraySize(items);
|
|
|
|
//
|
|
result = after > before;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Add items Collection reference Members into source Collection only if it's not Exists ...alignas
|
|
* @return ( int )
|
|
*/
|
|
template <typename T>
|
|
int AddIfNotExists(
|
|
T *&items[],
|
|
T *&sources[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
bool has = HasChild(items);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(sources);
|
|
|
|
//
|
|
int count = ArraySize(items);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = AddIfNotExists(
|
|
items[i],
|
|
sources //
|
|
);
|
|
}
|
|
|
|
//
|
|
int after = ArraySize(sources);
|
|
|
|
//
|
|
result = after > before;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
int AddIfNotExists(
|
|
XConsolidationZone &items[],
|
|
XConsolidationZone &sources[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
bool has = HasChild(items);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(sources);
|
|
|
|
//
|
|
int count = ArraySize(items);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = AddIfNotExists(
|
|
items[i],
|
|
sources //
|
|
);
|
|
}
|
|
|
|
//
|
|
int after = ArraySize(sources);
|
|
|
|
//
|
|
result = after > before;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Update to Time of Specifiex Collection ...
|
|
*
|
|
* @param items: XOBFVG instance Collection ...
|
|
* @param value: datetime ...
|
|
*/
|
|
template <typename T>
|
|
void SpecifiedUpdateTo(
|
|
T *&items[],
|
|
datetime value = NULL //
|
|
)
|
|
{
|
|
//
|
|
value = NormalizeTime(value);
|
|
|
|
//
|
|
int count = ArraySize(items);
|
|
bool has = HasChild(items);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
items[i].To(value);
|
|
}
|
|
}
|
|
|
|
//
|
|
template <typename T>
|
|
int FilterZones(
|
|
//
|
|
T *&source[],
|
|
//
|
|
ENUM_X_DIRECTION forDir,
|
|
ENUM_TIMEFRAMES forPeriod = NULL,
|
|
datetime after = NULL,
|
|
//
|
|
// Start ...
|
|
ENUM_XZONE_STATE startState = XZONE_STATE_PASSED,
|
|
bool forceStartedBodyOut = false,
|
|
//
|
|
// Activation ...
|
|
ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED,
|
|
bool forceActivatedBodyIn = false,
|
|
//
|
|
// Breaktion ...
|
|
ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED,
|
|
bool forceBreakedBodyOut = false,
|
|
//
|
|
// Works ...
|
|
ENUM_XZONE_STATE workState = XZONE_STATE_FAILED,
|
|
bool forceWorkedBodyOut = false,
|
|
//
|
|
bool applySort = false,
|
|
//
|
|
bool ignoreInside = true
|
|
//
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
int idx = -1;
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
has = HasDirection(forDir);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
count = ArraySize(source);
|
|
has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
T *tmpZones[];
|
|
XOHCL passedBar;
|
|
bool isPassed = false;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
T *iZone = source[i];
|
|
|
|
//
|
|
// Apply after Filter ...
|
|
isPassed =
|
|
!IsValid(after)
|
|
? true
|
|
: iZone.From() >= after;
|
|
if (!isPassed)
|
|
{
|
|
//
|
|
ZeroMemory(iZone);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Started State ...
|
|
if (startState == XZONE_STATE_PASSED ||
|
|
startState == XZONE_STATE_FAILED)
|
|
{
|
|
//
|
|
bool isBodyOut = false;
|
|
bool isStarted = iZone.IsStarted(
|
|
forDir,
|
|
passedBar,
|
|
isBodyOut,
|
|
forPeriod //
|
|
);
|
|
|
|
//
|
|
bool isPassed =
|
|
startState == XZONE_STATE_FAILED
|
|
? !isStarted
|
|
: !forceStartedBodyOut
|
|
? isStarted
|
|
: isStarted &&
|
|
isBodyOut;
|
|
|
|
//
|
|
passedBar.Clean();
|
|
if (!isPassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Activation State ...
|
|
if (activeState == XZONE_STATE_PASSED ||
|
|
activeState == XZONE_STATE_FAILED)
|
|
{
|
|
//
|
|
bool isBodyIn = false;
|
|
bool isActivated = iZone.IsActivated(
|
|
forDir,
|
|
passedBar,
|
|
isBodyIn,
|
|
forceStartedBodyOut,
|
|
forPeriod //
|
|
);
|
|
|
|
//
|
|
bool isPassed =
|
|
activeState == XZONE_STATE_FAILED
|
|
? !isActivated
|
|
: !forceActivatedBodyIn
|
|
? isActivated
|
|
: isActivated &&
|
|
isBodyIn;
|
|
|
|
//
|
|
passedBar.Clean();
|
|
if (!isPassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Break State ...
|
|
if (breakState == XZONE_STATE_PASSED ||
|
|
breakState == XZONE_STATE_FAILED)
|
|
{
|
|
//
|
|
bool isBodyOut = false;
|
|
bool isBreaked = iZone.IsBreaked(
|
|
forDir,
|
|
passedBar,
|
|
isBodyOut,
|
|
forceStartedBodyOut,
|
|
forPeriod //
|
|
);
|
|
|
|
//
|
|
bool isPassed =
|
|
breakState == XZONE_STATE_FAILED
|
|
? !isBreaked
|
|
: !forceBreakedBodyOut
|
|
? isBreaked
|
|
: isBreaked &&
|
|
isBodyOut;
|
|
|
|
//
|
|
passedBar.Clean();
|
|
if (!isPassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Work State ...
|
|
if (workState == XZONE_STATE_PASSED ||
|
|
workState == XZONE_STATE_FAILED)
|
|
{
|
|
//
|
|
bool ignoreActivation = activeState != XZONE_STATE_PASSED;
|
|
|
|
//
|
|
bool isBodyOut = false;
|
|
bool isWorked = iZone.IsWorked(
|
|
forDir,
|
|
passedBar,
|
|
isBodyOut,
|
|
ignoreActivation,
|
|
forceStartedBodyOut,
|
|
forceActivatedBodyIn,
|
|
forPeriod //
|
|
);
|
|
|
|
//
|
|
bool isPassed =
|
|
workState == XZONE_STATE_FAILED
|
|
? !isWorked
|
|
: !forceWorkedBodyOut
|
|
? isWorked
|
|
: isWorked &&
|
|
isBodyOut;
|
|
|
|
//
|
|
passedBar.Clean();
|
|
if (!isPassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Filtered Zone Doesn't Exists ...
|
|
has = FindIndex(
|
|
idx,
|
|
iZone,
|
|
tmpZones //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
ZeroMemory(iZone);
|
|
passedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
iZone,
|
|
tmpZones //
|
|
);
|
|
}
|
|
|
|
//
|
|
Clean(source);
|
|
|
|
//
|
|
has = HasChild(tmpZones);
|
|
if (!has)
|
|
{
|
|
//
|
|
Clean(tmpZones);
|
|
passedBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Apply Sorting ...
|
|
if (applySort)
|
|
{
|
|
//
|
|
T *last = NULL;
|
|
bool hasLast = false;
|
|
while (HasChild(tmpZones))
|
|
{
|
|
//
|
|
idx = GetYoungest(tmpZones);
|
|
hasLast = IsValidIndex(idx);
|
|
if (hasLast)
|
|
{
|
|
//
|
|
last = tmpZones[idx];
|
|
ArrayRemove(
|
|
tmpZones,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
last,
|
|
source //
|
|
);
|
|
}
|
|
|
|
//
|
|
has = HasChild(tmpZones);
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
T *zone = NULL;
|
|
bool hasZone = false;
|
|
idx = GetYoungest(tmpZones);
|
|
hasZone = IsValidIndex(idx);
|
|
if (hasZone)
|
|
{
|
|
//
|
|
zone = tmpZones[idx];
|
|
ArrayRemove(
|
|
tmpZones,
|
|
idx,
|
|
1 //
|
|
);
|
|
}
|
|
if (!hasZone)
|
|
{
|
|
//
|
|
ZeroMemory(zone);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isAbove = IsAbove(
|
|
zone,
|
|
last,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
bool isBelow = IsBelow(
|
|
zone,
|
|
last,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
isPassed =
|
|
isBullish
|
|
? isAbove
|
|
: isBelow;
|
|
if (!isPassed)
|
|
{
|
|
//
|
|
ZeroMemory(zone);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
zone,
|
|
source //
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Copy(
|
|
tmpZones,
|
|
source //
|
|
);
|
|
}
|
|
|
|
//
|
|
result = ArraySize(source);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
/**
|
|
* Detect Nearest Price Out of Specified Box ...
|
|
*
|
|
* @param box: XBoxZone instance Reference ...
|
|
* @param outSideBar: XOHCL instance Reference which Represents Out Side Bar if Exists ...
|
|
* @param forPeriod: ENUM_TIMEFRAMES member which provides time frame of Out Bar, if not Provides used box Period as Default ...
|
|
* @param forDir: ENUM_X_DIRECTION member which Specified outSide Direction, use Box Dir as Default ...
|
|
* @param forceBodyIn: bool value which Specifyed Body Breakes or not, Default is false ...
|
|
* @param barIndex: integer value which Specified Start Bar Index, Default is 0 ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectBoxNearestPriceOut(
|
|
XBoxZone &box,
|
|
XOHCL &outSideBar,
|
|
ENUM_TIMEFRAMES forPeriod = NULL,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
|
|
bool forceBodyIn = false,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
outSideBar.Clean();
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = box.period;
|
|
}
|
|
|
|
//
|
|
if (!HasDirection(forDir))
|
|
{
|
|
forDir = box.dir;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
int fromIndex = iBarShift(
|
|
box.symbol,
|
|
forPeriod,
|
|
box.from //
|
|
);
|
|
result = IsValidIndex(fromIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL iBar;
|
|
XOHCL iPBar;
|
|
bool has = false;
|
|
for (int i = barIndex; i < fromIndex; i++)
|
|
{
|
|
//
|
|
has = iBar.Init(
|
|
box.symbol,
|
|
forPeriod,
|
|
i //
|
|
);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
has = iBar.GetPreviousBar(iPBar);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isInsideFromLower =
|
|
iBar.high < box.lower &&
|
|
iPBar.high > box.lower;
|
|
|
|
//
|
|
bool isInsideFromUpper =
|
|
iBar.low > box.upper &&
|
|
iPBar.low < box.upper;
|
|
|
|
//
|
|
bool isInsideBodyFromLower =
|
|
iPBar.GetUp() > box.lower;
|
|
|
|
//
|
|
bool isInsideBodyFromUpper =
|
|
iPBar.GetDown() < box.upper;
|
|
|
|
//
|
|
result =
|
|
isBullish
|
|
? (!forceBodyIn
|
|
? isInsideFromLower
|
|
: isInsideFromLower &&
|
|
isInsideBodyFromLower)
|
|
: (!forceBodyIn
|
|
? isInsideFromUpper
|
|
: isInsideFromUpper &&
|
|
isInsideBodyFromUpper);
|
|
if (result)
|
|
{
|
|
//
|
|
outSideBar = iBar;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Count number of Box Retests ...
|
|
*
|
|
* @param box: XBoxZone instance Reference ...
|
|
* @param forDir: ENUM_X_DIRECTION member, Specified Retesting Direction ...
|
|
* @param forPeriod: ENUM_TIMEFRAMES member, Specified Retesting Period ...
|
|
* @param forceType: bool, Specified Retest Bar Direction is Same as Retesting Direction ...
|
|
* @param forcePressure: bool, Specified Retest Bar must Has Fibo Pressure or not ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int CountBoxRetest(
|
|
XBoxZone &box,
|
|
ENUM_X_DIRECTION forDir = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL,
|
|
bool forceType = false,
|
|
bool forcePressure = false //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = box.period;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forDir))
|
|
{
|
|
forDir = box.dir;
|
|
}
|
|
|
|
//
|
|
bool isValid =
|
|
box.IsValid() &&
|
|
IsValid(forDir);
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int fromIDX = GetBarIndex(
|
|
box.symbol,
|
|
forPeriod,
|
|
box.from //
|
|
);
|
|
|
|
//
|
|
int toIDX = GetBarIndex(
|
|
box.symbol,
|
|
forPeriod,
|
|
box.to //
|
|
);
|
|
|
|
//
|
|
for (int i = fromIDX; i >= toIDX; i--)
|
|
{
|
|
//
|
|
// Initialize Indexed Bar ...
|
|
XOHCL iBar;
|
|
isValid = iBar.Init(
|
|
box.symbol,
|
|
forPeriod,
|
|
i //
|
|
);
|
|
if (!isValid)
|
|
{
|
|
//
|
|
iBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isUpperBullishRejected = iBar.IsRejected(
|
|
box.upper,
|
|
X_DIRECTION_BULLISH,
|
|
forceType,
|
|
forcePressure //
|
|
);
|
|
bool isUpperBearishRejected = iBar.IsRejected(
|
|
box.upper,
|
|
X_DIRECTION_BEARISH,
|
|
forceType,
|
|
forcePressure //
|
|
);
|
|
|
|
//
|
|
bool isLowerBullishRejected = iBar.IsRejected(
|
|
box.lower,
|
|
X_DIRECTION_BULLISH,
|
|
forceType,
|
|
forcePressure //
|
|
);
|
|
bool isLowerBearishRejected = iBar.IsRejected(
|
|
box.lower,
|
|
X_DIRECTION_BEARISH,
|
|
forceType,
|
|
forcePressure //
|
|
);
|
|
|
|
//
|
|
if (forDir == X_DIRECTION_ALL ||
|
|
forDir == X_DIRECTION_BULLISH)
|
|
{
|
|
//
|
|
if (isUpperBullishRejected ||
|
|
isLowerBullishRejected)
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
if (forDir == X_DIRECTION_ALL ||
|
|
forDir == X_DIRECTION_BEARISH)
|
|
{
|
|
//
|
|
if (isUpperBearishRejected ||
|
|
isLowerBearishRejected)
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
// |