6652 lines
121 KiB
Plaintext
6652 lines
121 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-ohcl.lib.mq5"
|
|
#include "../Libraries/x-saherelm.x-poi.lib.mq5"
|
|
|
|
//
|
|
// Extensions ...
|
|
//+------------------------------------------------------------------+
|
|
//| Oldest Detection |
|
|
//+------------------------------------------------------------------+
|
|
/**
|
|
* Get Oldest Index of Specified Collection ...
|
|
*
|
|
* @param source: Specified 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++)
|
|
{
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from > source[i].from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = source[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Oldest Index of Specified Collection ...
|
|
*
|
|
* @param source: Specified Collection ...
|
|
* @param forDir: ENUM_X_DIRECTION, Specified Direction ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldestByDir(
|
|
XBoxZone &source[],
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
bool canSet =
|
|
(!HasDirection(forDir)
|
|
? true
|
|
: forDir == source[i].dir) &&
|
|
(!selected.IsValid()
|
|
? true
|
|
: selected.from > source[i].from);
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = source[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Oldest Index of Specified Collection ...
|
|
*
|
|
* @param bar: XOHCL, Specified Bar ...
|
|
* @param source: Specified Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldestByBar(
|
|
XOHCL &bar,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!bar.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, source[i]);
|
|
if (!isBoxValidForBar)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from > source[i].from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = source[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Oldest Index of Specified Collection ...
|
|
*
|
|
* @param source: Specified Collection ...
|
|
* @param type: ENUM_X_PIVOT_TYPE, Specified Points Type ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldest(
|
|
XPivot &source[],
|
|
ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
// Validate ...
|
|
if (!HasChild(source))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool has = false;
|
|
XPivot iPoint;
|
|
int count = ArraySize(source);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Passed Type ...
|
|
has = !IsXValid(type)
|
|
? true
|
|
: type == source[i].type;
|
|
|
|
//
|
|
// Check Can Assign ...
|
|
has =
|
|
has &&
|
|
(!iPoint.IsValid() ||
|
|
(iPoint.IsValid() &&
|
|
source[i].GetAge() > iPoint.GetAge()));
|
|
if (has)
|
|
{
|
|
//
|
|
result = i;
|
|
iPoint = source[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate Result ...
|
|
has =
|
|
iPoint.IsValid() &&
|
|
IsValidIndex(result);
|
|
if (!has)
|
|
{
|
|
//
|
|
result = -1;
|
|
iPoint.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
iPoint.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Youngest Detection |
|
|
//+------------------------------------------------------------------+
|
|
/**
|
|
* Get Youngest Index of Specified Collection ...
|
|
*
|
|
* @param source: Specified 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++)
|
|
{
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from < source[i].from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = source[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Index of Specified Collection ...
|
|
*
|
|
* @param source: Specified Collection ...
|
|
* @param forDir: ENUM_X_DIRECTION, Specified Direction ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungestByDir(
|
|
XBoxZone &source[],
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
bool canSet =
|
|
(!HasDirection(forDir)
|
|
? true
|
|
: forDir == source[i].dir) &&
|
|
(!selected.IsValid()
|
|
? true
|
|
: selected.from < source[i].from);
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = source[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Index of Specified Collection ...
|
|
*
|
|
* @param bar: XOHCL, Specified Bar ...
|
|
* @param source: Specified Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungestByBar(
|
|
XOHCL &bar,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!bar.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, source[i]);
|
|
if (!isBoxValidForBar)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from < source[i].from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = source[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Index of Specified Collection ...
|
|
*
|
|
* @param source: Specified Collection ...
|
|
* @param type: ENUM_X_PIVOT_TYPE, Specified Points Type ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungest(
|
|
XPivot &source[],
|
|
ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
// Validate ...
|
|
if (!HasChild(source))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool has = false;
|
|
XPivot iPoint;
|
|
int count = ArraySize(source);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Passed Type ...
|
|
has = !IsXValid(type)
|
|
? true
|
|
: type == source[i].type;
|
|
|
|
//
|
|
// Check Can Assign ...
|
|
has =
|
|
has &&
|
|
(!iPoint.IsValid() ||
|
|
(iPoint.IsValid() &&
|
|
source[i].GetAge() < iPoint.GetAge()));
|
|
if (has)
|
|
{
|
|
//
|
|
result = i;
|
|
iPoint = source[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate Result ...
|
|
has =
|
|
iPoint.IsValid() &&
|
|
IsValidIndex(result);
|
|
if (!has)
|
|
{
|
|
//
|
|
result = -1;
|
|
iPoint.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
iPoint.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Highest Detection |
|
|
//+------------------------------------------------------------------+
|
|
/**
|
|
* Get Highest Index of Specified Collection ...
|
|
*
|
|
* @param source: Specified 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++)
|
|
{
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.upper < source[i].upper;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = source[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Highest Index of Specified Collection ...
|
|
*
|
|
* @param source: Specified Collection ...
|
|
* @param forDir: ENUM_X_DIRECTION, Specified Direction ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighestByDir(
|
|
XBoxZone &source[],
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
bool canSet =
|
|
(!HasDirection(forDir)
|
|
? true
|
|
: forDir == source[i].dir) &&
|
|
(!selected.IsValid()
|
|
? true
|
|
: selected.upper < source[i].upper);
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = source[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Highest Index of Specified Collection ...
|
|
*
|
|
* @param bar: XOHCL, Specified Bar ...
|
|
* @param source: Specified Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighestByBar(
|
|
XOHCL &bar,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!bar.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox);
|
|
if (!isBoxValidForBar)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.upper < iBox.upper;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Highest Bar Price Index of Specified Collection ...
|
|
*
|
|
* @param source: reference collection, Provides Data Source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighestBarPrice(
|
|
XOHCL &source[],
|
|
ENUM_X_PRICE priceType //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = HasChild(source) &&
|
|
IsXValid(priceType);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double price = EMPTY_VALUE;
|
|
double selected = EMPTY_VALUE;
|
|
int count = ArraySize(source);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
price = source[i].GetPrice(priceType);
|
|
has = !NotEmptyZero(selected)
|
|
? true
|
|
: price > selected;
|
|
if (has)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = price;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Highest Index of Specified Collection ...
|
|
*
|
|
* @param source: Specified Collection ...
|
|
* @param type: ENUM_X_PIVOT_TYPE, Specified Points Type ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighest(
|
|
XPivot &source[],
|
|
ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
// Validate ...
|
|
if (!HasChild(source))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool has = false;
|
|
XPivot iPoint;
|
|
int count = ArraySize(source);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Passed Type ...
|
|
has = !IsXValid(type)
|
|
? true
|
|
: type == source[i].type;
|
|
|
|
//
|
|
// Check Can Assign ...
|
|
has =
|
|
has &&
|
|
(!iPoint.IsValid() ||
|
|
(iPoint.IsValid() &&
|
|
source[i].value > iPoint.value));
|
|
if (has)
|
|
{
|
|
//
|
|
result = i;
|
|
iPoint = source[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate Result ...
|
|
has =
|
|
iPoint.IsValid() &&
|
|
IsValidIndex(result);
|
|
if (!has)
|
|
{
|
|
//
|
|
result = -1;
|
|
iPoint.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
iPoint.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Loest Detection |
|
|
//+------------------------------------------------------------------+
|
|
/**
|
|
* Get Lowest Index of Specified Collection ...
|
|
*
|
|
* @param source: Specified 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;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Lowest Index of Specified Collection ...
|
|
*
|
|
* @param source: Specified Collection ...
|
|
* @param forDir: ENUM_X_DIRECTION, Specified Direction ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowestByDir(
|
|
XBoxZone &source[],
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
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 =
|
|
(!HasDirection(forDir)
|
|
? true
|
|
: forDir == source[i].dir) &&
|
|
(!selected.IsValid()
|
|
? true
|
|
: selected.lower > iBox.lower);
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Lowest Index of Specified Collection ...
|
|
*
|
|
* @param bar: XOHCL, Specified Bar ...
|
|
* @param source: Specified Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowestByBar(
|
|
XOHCL &bar,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!bar.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox);
|
|
if (!isBoxValidForBar)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.lower > iBox.lower;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Lowest Bar Price Index of Specified Collection ...
|
|
*
|
|
* @param source: reference collection, Provides Data Source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowestBarPrice(
|
|
XOHCL &source[],
|
|
ENUM_X_PRICE priceType //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = HasChild(source) &&
|
|
IsXValid(priceType);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double price = EMPTY_VALUE;
|
|
double selected = EMPTY_VALUE;
|
|
int count = ArraySize(source);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
price = source[i].GetPrice(priceType);
|
|
has = !NotEmptyZero(selected)
|
|
? true
|
|
: price < selected;
|
|
if (has)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = price;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Lowest Index of Specified Collection ...
|
|
*
|
|
* @param source: Specified Collection ...
|
|
* @param type: ENUM_X_PIVOT_TYPE, Specified Points Type ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowest(
|
|
XPivot &items[],
|
|
ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
// Validate ...
|
|
if (!HasChild(items))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool has = false;
|
|
XPivot iPoint;
|
|
int count = ArraySize(items);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Passed Type ...
|
|
has = !IsXValid(type)
|
|
? true
|
|
: type == items[i].type;
|
|
|
|
//
|
|
// Check Can Assign ...
|
|
has =
|
|
has &&
|
|
(!iPoint.IsValid() ||
|
|
(iPoint.IsValid() &&
|
|
items[i].value < iPoint.value));
|
|
if (has)
|
|
{
|
|
//
|
|
result = i;
|
|
iPoint = items[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate Result ...
|
|
has =
|
|
iPoint.IsValid() &&
|
|
IsValidIndex(result);
|
|
if (!has)
|
|
{
|
|
//
|
|
result = -1;
|
|
iPoint.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
iPoint.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Box |
|
|
//+------------------------------------------------------------------+
|
|
/**
|
|
* Extract all items which appears Before Specified Time ...
|
|
*
|
|
* @param _time: Specified Time ...
|
|
* @param dest: refrence collection to hold result ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetBeforeItems(
|
|
datetime _time,
|
|
XBoxZone &dest[],
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(dest);
|
|
|
|
//
|
|
// Validate ...
|
|
int count = ArraySize(source);
|
|
bool has = HasChild(source) &&
|
|
IsSpecifiedValid(_time);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop through Items ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = source[i].from < _time;
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
source[i],
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract all items which appears After Specified Time ...
|
|
*
|
|
* @param _time: Specified Time ...
|
|
* @param dest: refrence collection to hold result ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetAfterItems(
|
|
datetime _time,
|
|
XBoxZone &dest[],
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(dest);
|
|
|
|
//
|
|
// Validate ...
|
|
int count = ArraySize(source);
|
|
bool has = HasChild(source) &&
|
|
IsSpecifiedValid(_time);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop through Items ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = source[i].from > _time;
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
source[i],
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract all items which appears Above Specified Value ...
|
|
*
|
|
* @param _value: Specified Value ...
|
|
* @param dest: refrence collection to hold result ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetAboveItems(
|
|
double _value,
|
|
XBoxZone &dest[],
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(dest);
|
|
|
|
//
|
|
// Validate ...
|
|
int count = ArraySize(source);
|
|
bool has = HasChild(source) &&
|
|
NotEmptyZero(_value);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop through Items ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = source[i].lower > _value;
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
source[i],
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract all items which appears Below Specified Value ...
|
|
*
|
|
* @param _value: Specified Value ...
|
|
* @param dest: refrence collection to hold result ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetBelowItems(
|
|
double _value,
|
|
XBoxZone &dest[],
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(dest);
|
|
|
|
//
|
|
// Validate ...
|
|
int count = ArraySize(source);
|
|
bool has = HasChild(source) &&
|
|
NotEmptyZero(_value);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop through Items ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = source[i].upper < _value;
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
source[i],
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Oldest Item Index of all items which appears Before Specified Value ...
|
|
*
|
|
* @param _time: Specified Time ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldestBefore(
|
|
datetime _time,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetBeforeItems(
|
|
_time,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetOldest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Oldest Item Index of all items which appears After Specified Value ...
|
|
*
|
|
* @param _time: Specified Time ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldestAfter(
|
|
datetime _time,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetAfterItems(
|
|
_time,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetOldest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Oldest Item Index of all items which appears Above Specified Value ...
|
|
*
|
|
* @param _value: Specified Value ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldestAbove(
|
|
double _value,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetAboveItems(
|
|
_value,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetOldest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Oldest Item Index of all items which appears Below Specified Value ...
|
|
*
|
|
* @param _value: Specified Value ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldestBelow(
|
|
double _value,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetBelowItems(
|
|
_value,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetOldest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Item Index of all items which appears Before Specified Value ...
|
|
*
|
|
* @param _time: Specified Time ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungestBefore(
|
|
datetime _time,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetBeforeItems(
|
|
_time,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetYoungest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Item Index of all items which appears After Specified Value ...
|
|
*
|
|
* @param _time: Specified Time ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungestAfter(
|
|
datetime _time,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetAfterItems(
|
|
_time,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetYoungest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Item Index of all items which appears Above Specified Value ...
|
|
*
|
|
* @param _value: Specified Value ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungestAbove(
|
|
double _value,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetAboveItems(
|
|
_value,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetYoungest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Item Index of all items which appears Below Specified Value ...
|
|
*
|
|
* @param _value: Specified Value ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungestBelow(
|
|
double _value,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetBelowItems(
|
|
_value,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetYoungest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Highest Item Index of all items which appears Before Specified Value ...
|
|
*
|
|
* @param _time: Specified Time ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighestBefore(
|
|
datetime _time,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetBeforeItems(
|
|
_time,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetHighest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Highest Item Index of all items which appears After Specified Value ...
|
|
*
|
|
* @param _time: Specified Time ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighestAfter(
|
|
datetime _time,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetAfterItems(
|
|
_time,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetHighest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Highest Item Index of all items which appears Above Specified Value ...
|
|
*
|
|
* @param _value: Specified Value ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighestAbove(
|
|
double _value,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetAboveItems(
|
|
_value,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetHighest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Highest Item Index of all items which appears Below Specified Value ...
|
|
*
|
|
* @param _value: Specified Value ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighestBelow(
|
|
double _value,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetBelowItems(
|
|
_value,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetHighest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Lowest Item Index of all items which appears Before Specified Value ...
|
|
*
|
|
* @param _time: Specified Time ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowestBefore(
|
|
datetime _time,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetBeforeItems(
|
|
_time,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetLowest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Lowest Item Index of all items which appears After Specified Value ...
|
|
*
|
|
* @param _time: Specified Time ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowestAfter(
|
|
datetime _time,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetAfterItems(
|
|
_time,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetLowest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Lowest Item Index of all items which appears Above Specified Value ...
|
|
*
|
|
* @param _value: Specified Value ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowestAbove(
|
|
double _value,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetAboveItems(
|
|
_value,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetLowest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Lowest Item Index of all items which appears Below Specified Value ...
|
|
*
|
|
* @param _value: Specified Value ...
|
|
* @param source: refrence collection to provides data source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowestBelow(
|
|
double _value,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
int tmpsCount = GetBelowItems(
|
|
_value,
|
|
tmps, // Dest ...
|
|
source // Source ...
|
|
);
|
|
bool has = IsValidSize(tmpsCount);
|
|
int idx = GetLowest(tmps);
|
|
has =
|
|
has &&
|
|
IsValidIndex(idx) &&
|
|
FindIndex(
|
|
result,
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
SpecifiedClean(tmps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Validate an Item Strength ...
|
|
*
|
|
* @param item: Specified Item for Validating ...
|
|
* @param minAllowedStrength: int, Minimum required Strength in Point ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ValidateStrength(
|
|
XBoxZone &item,
|
|
int minAllowedStrength = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
minAllowedStrength = NormalizeInt(minAllowedStrength, 0);
|
|
|
|
//
|
|
// Validate ...
|
|
result = item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// If doent provide Specified Strength Validate Zone ...
|
|
result = minAllowedStrength <= 0;
|
|
if (result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double points = GetPoints(item.symbol);
|
|
double requiredStrength = minAllowedStrength * points;
|
|
double itemStrength = item.upper - item.lower;
|
|
|
|
//
|
|
result =
|
|
itemStrength > 0 &&
|
|
requiredStrength > 0 &&
|
|
itemStrength > requiredStrength;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Sort |
|
|
//+------------------------------------------------------------------+
|
|
|
|
/**
|
|
* Allowed Sort Param ...
|
|
**/
|
|
enum ENUM_X_SORT_BY
|
|
{
|
|
X_SORT_BY_NONE = 0, // None
|
|
X_SORT_BY_DATE = 1, // by Date
|
|
X_SORT_BY_VALUE = 2, // by Date
|
|
};
|
|
|
|
/**
|
|
* Check Specified Sort By Validation ...
|
|
*
|
|
* @param value: ENUM_X_SORT_BY, value to Validate ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsXValid(ENUM_X_SORT_BY value)
|
|
{
|
|
return value != X_SORT_BY_NONE;
|
|
}
|
|
|
|
/**
|
|
* Select Specified Index of a Collection by Sort Params ...
|
|
*
|
|
* @param source: Collection for Search ...
|
|
* @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ...
|
|
* @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
template <typename T>
|
|
int SelectItemForSorting(
|
|
T &source[],
|
|
ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE,
|
|
ENUM_X_DIRECTION sortDir = X_DIRECTION_BULLISH //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
// Validate ...
|
|
if (!HasChild(source) ||
|
|
!IsXValid(sortBy) ||
|
|
!HasDirection(sortDir))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Sort By Date ...
|
|
if (sortBy == X_SORT_BY_DATE)
|
|
{
|
|
//
|
|
// Select Based on Sorting Direction ...
|
|
|
|
//
|
|
// form Oldest to Youngest ...
|
|
if (sortDir == X_DIRECTION_BULLISH)
|
|
{
|
|
result = GetOldest(source);
|
|
}
|
|
//
|
|
// form Youngest to Oldest ...
|
|
else if (sortDir == X_DIRECTION_BEARISH)
|
|
{
|
|
result = GetYoungest(source);
|
|
}
|
|
//
|
|
// Not Valid ...
|
|
else
|
|
{
|
|
result = -1;
|
|
}
|
|
}
|
|
//
|
|
// Sort By Value ...
|
|
else if (sortBy == X_SORT_BY_VALUE)
|
|
{
|
|
//
|
|
// form Lowst to Highest ...
|
|
if (sortDir == X_DIRECTION_BULLISH)
|
|
{
|
|
result = GetLowest(source);
|
|
}
|
|
//
|
|
// form Highest to Lowest ...
|
|
else if (sortDir == X_DIRECTION_BEARISH)
|
|
{
|
|
result = GetHighest(source);
|
|
}
|
|
//
|
|
// Not Valid ...
|
|
else
|
|
{
|
|
result = -1;
|
|
}
|
|
}
|
|
//
|
|
// Not Valid ...
|
|
else
|
|
{
|
|
result = -1;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Select Specified Index of a Collection by Sort Params ...
|
|
*
|
|
* @param source: Collection for Search ...
|
|
* @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ...
|
|
* @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int SelectBarForSorting(
|
|
XOHCL &source[],
|
|
ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE,
|
|
ENUM_X_DIRECTION sortDir = X_DIRECTION_BULLISH,
|
|
ENUM_X_PRICE priceType = X_PRICE_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
// Validate ...
|
|
if (!HasChild(source) ||
|
|
!IsXValid(sortBy) ||
|
|
!HasDirection(sortDir))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Sort By Date ...
|
|
if (sortBy == X_SORT_BY_DATE)
|
|
{
|
|
//
|
|
// Select Based on Sorting Direction ...
|
|
|
|
//
|
|
// form Oldest to Youngest ...
|
|
if (sortDir == X_DIRECTION_BULLISH)
|
|
{
|
|
result = GetOldest(source);
|
|
}
|
|
//
|
|
// form Youngest to Oldest ...
|
|
else if (sortDir == X_DIRECTION_BEARISH)
|
|
{
|
|
result = GetYoungest(source);
|
|
}
|
|
//
|
|
// Not Valid ...
|
|
else
|
|
{
|
|
result = -1;
|
|
}
|
|
}
|
|
//
|
|
// Sort By Value ...
|
|
else if (sortBy == X_SORT_BY_VALUE)
|
|
{
|
|
//
|
|
// form Lowst to Highest ...
|
|
if (sortDir == X_DIRECTION_BULLISH)
|
|
{
|
|
result = GetLowest(source, priceType);
|
|
}
|
|
//
|
|
// form Highest to Lowest ...
|
|
else if (sortDir == X_DIRECTION_BEARISH)
|
|
{
|
|
result = GetHighest(source, priceType);
|
|
}
|
|
//
|
|
// Not Valid ...
|
|
else
|
|
{
|
|
result = -1;
|
|
}
|
|
}
|
|
//
|
|
// Not Valid ...
|
|
else
|
|
{
|
|
result = -1;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Apply Sort on Specified Collection ...
|
|
*
|
|
* @param source: Collection Reference to Sort ...
|
|
* @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ...
|
|
* @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ...
|
|
* @param maxAllowed: int, Max Allowed Collection Size ...
|
|
*/
|
|
template <typename T>
|
|
void Sort(
|
|
T &source[],
|
|
ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE,
|
|
ENUM_X_DIRECTION sortDir = X_DIRECTION_BEARISH,
|
|
int maxAllowed = 0 //
|
|
)
|
|
{
|
|
//
|
|
int idx = -1;
|
|
bool has = false;
|
|
|
|
//
|
|
// Validate ...
|
|
has =
|
|
IsXValid(sortBy) &&
|
|
HasChild(source) &&
|
|
HasDirection(sortDir);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Copy source for Manipulating ...
|
|
T tmps[];
|
|
Copy(
|
|
source,
|
|
tmps //
|
|
);
|
|
|
|
//
|
|
// Clean Source Collection for Adding Sorted Items ...
|
|
Clean(source);
|
|
|
|
//
|
|
// Loop Through Temp Collection Has Child ...
|
|
while (HasChild(tmps))
|
|
{
|
|
//
|
|
// Select Based on Sorting Parameter ...
|
|
idx = SelectItemForSorting(
|
|
tmps,
|
|
sortBy,
|
|
sortDir //
|
|
);
|
|
|
|
//
|
|
// Validate Detected Index ...
|
|
has = IsValidIndex(idx);
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Add Detected Indexed Item to Source ...
|
|
AddRef(
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
|
|
//
|
|
// Remove Item From Temp Collection ...
|
|
ArrayRemove(
|
|
tmps,
|
|
idx,
|
|
1 //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Collection if Max Items Reached ...
|
|
if (maxAllowed > 0)
|
|
{
|
|
//
|
|
CleanupArray(
|
|
source,
|
|
maxAllowed //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(tmps);
|
|
}
|
|
|
|
/**
|
|
* Apply Sort on Specified Collection ...
|
|
*
|
|
* @param source: Collection Reference to Sort ...
|
|
* @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ...
|
|
* @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ...
|
|
* @param priceType: ENUM_X_PRICE, Price Selecting Method ...
|
|
* @param maxAllowed: int, Max Allowed Collection Size ...
|
|
*/
|
|
void SortBar(
|
|
XOHCL &source[],
|
|
ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE,
|
|
ENUM_X_DIRECTION sortDir = X_DIRECTION_BULLISH,
|
|
ENUM_X_PRICE priceType = X_PRICE_NONE,
|
|
int maxAllowed = 0 //
|
|
)
|
|
{
|
|
//
|
|
int idx = -1;
|
|
bool has = false;
|
|
|
|
//
|
|
// Validate ...
|
|
has =
|
|
IsXValid(sortBy) &&
|
|
HasChild(source) &&
|
|
HasDirection(sortDir);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Copy source for Manipulating ...
|
|
XOHCL tmps[];
|
|
Copy(
|
|
source,
|
|
tmps //
|
|
);
|
|
|
|
//
|
|
// Clean Source Collection for Adding Sorted Items ...
|
|
Clean(source);
|
|
|
|
//
|
|
// Loop Through Temp Collection Has Child ...
|
|
while (HasChild(tmps))
|
|
{
|
|
//
|
|
// Select Based on Sorting Parameter ...
|
|
idx = SelectBarForSorting(
|
|
tmps,
|
|
sortBy,
|
|
sortDir,
|
|
priceType //
|
|
);
|
|
|
|
//
|
|
// Validate Detected Index ...
|
|
has = IsValidIndex(idx);
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Add Detected Indexed Item to Source ...
|
|
AddRef(
|
|
tmps[idx],
|
|
source //
|
|
);
|
|
|
|
//
|
|
// Remove Item From Temp Collection ...
|
|
ArrayRemove(
|
|
tmps,
|
|
idx,
|
|
1 //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Collection if Max Items Reached ...
|
|
if (maxAllowed > 0)
|
|
{
|
|
//
|
|
CleanupArray(
|
|
source,
|
|
maxAllowed //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(tmps);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Extraction |
|
|
//+------------------------------------------------------------------+
|
|
|
|
/**
|
|
* Extract Specific Types of Pivots From a Collection ...
|
|
*
|
|
* @param dest: reference Collection to Hold result ...
|
|
* @param source: Collection to Find Type Specific items ...
|
|
* @param _type: Specified item Type ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractPivots(
|
|
XPivot &dest[],
|
|
XPivot &source[],
|
|
ENUM_X_PIVOT_TYPE _type //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(dest);
|
|
|
|
//
|
|
// Validate ...
|
|
int count = ArraySize(source);
|
|
bool has =
|
|
IsXValid(_type) &&
|
|
IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Check Type Passing ...
|
|
has = _type == source[i].type;
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
AddIfNotExists(
|
|
source[i],
|
|
dest //
|
|
);
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract Same Time Pivots ...
|
|
*
|
|
* @param item: XPivot, reference to Specified Pivot for Detect Same Times ...
|
|
* @param dest: XPivot, collection reference to holds Same Times Pivots ...
|
|
* @param source: XPivot, collection reference to Provide Data Source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractSameTimePivots(
|
|
XPivot &item,
|
|
XPivot &dest[],
|
|
XPivot &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
XClean(dest);
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = HasChild(source) &&
|
|
item.IsValid();
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
int count = ArraySize(source);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = item.time == source[i].time;
|
|
if (has)
|
|
{
|
|
AddIfNotExists(source[i], dest);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Add item as a Child ...
|
|
AddIfNotExists(item, dest);
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract Pivots Data for Linear Regression Calculations ...
|
|
*
|
|
* @param xData: refrence Collection to Holds X-Axis Data ...
|
|
* @param yData: refrence Collection to Holds Y-Axis Data ...
|
|
* @param source: pivots Collection for Extraction ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractPivotsData(
|
|
double &xData[],
|
|
double &yData[],
|
|
XPivot &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(xData);
|
|
SpecifiedClean(yData);
|
|
|
|
//
|
|
// Validate ...
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool has = false;
|
|
double iX = EMPTY_VALUE;
|
|
double iY = EMPTY_VALUE;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Get Pivot Bar ...
|
|
has = source[i].GetBar(iBar);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
iX = iBar.Index();
|
|
iY = source[i].value;
|
|
|
|
//
|
|
Add(
|
|
iX,
|
|
xData //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
iY,
|
|
yData //
|
|
);
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
result = MathMin(ArraySize(xData), ArraySize(yData));
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Support and Resistance |
|
|
//+------------------------------------------------------------------+
|
|
/**
|
|
* Extract Support Levels of Pivots Collection ...
|
|
*
|
|
* @param _minor: refrence to Holds Minor Level ...
|
|
* @param _major: refrence to Holds Major Level ...
|
|
* @param source: Collection of Pivots ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ExtractSupport(
|
|
double &_minor,
|
|
double &_major,
|
|
XPivot &source[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
_minor = EMPTY_VALUE;
|
|
_major = EMPTY_VALUE;
|
|
|
|
//
|
|
// Validate ...
|
|
int count = ArraySize(source);
|
|
result = IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool has = false;
|
|
double tmp = EMPTY_VALUE;
|
|
double iValue = EMPTY_VALUE;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Check Type ...
|
|
has = source[i].IsVale();
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Reading Value ...
|
|
iValue = source[i].value;
|
|
|
|
//
|
|
// Check Can Change Major ...
|
|
has = !NotEmpty(_major) ||
|
|
_major > iValue;
|
|
if (has)
|
|
{
|
|
//
|
|
tmp = _major;
|
|
_major = iValue;
|
|
}
|
|
//
|
|
// Check Can Change Minor ...
|
|
else
|
|
{
|
|
//
|
|
// Change Minor ...
|
|
has = !NotEmpty(tmp) ||
|
|
tmp > iValue;
|
|
if (has)
|
|
{
|
|
tmp = iValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Last Update of Minore Minor ...
|
|
has = NotEmpty(tmp);
|
|
if (has)
|
|
{
|
|
_minor = tmp;
|
|
}
|
|
|
|
//
|
|
result = NotEmpty(_major) ||
|
|
NotEmpty(_minor);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract Resistance Levels of Pivots Collection ...
|
|
*
|
|
* @param _minor: refrence to Holds Minor Level ...
|
|
* @param _major: refrence to Holds Major Level ...
|
|
* @param source: Collection of Pivots ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ExtractResistances(
|
|
double &_minor,
|
|
double &_major,
|
|
XPivot &source[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
_minor = EMPTY_VALUE;
|
|
_major = EMPTY_VALUE;
|
|
|
|
//
|
|
// Validate ...
|
|
int count = ArraySize(source);
|
|
result = IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool has = false;
|
|
double tmp = EMPTY_VALUE;
|
|
double iValue = EMPTY_VALUE;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Check Type ...
|
|
has = source[i].IsPeak();
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Reading Value ...
|
|
iValue = source[i].value;
|
|
|
|
//
|
|
// Check Can Change Major ...
|
|
has = !NotEmpty(_major) ||
|
|
_major < iValue;
|
|
if (has)
|
|
{
|
|
//
|
|
tmp = _major;
|
|
_major = iValue;
|
|
}
|
|
//
|
|
// Check Can Change Minor ...
|
|
else
|
|
{
|
|
//
|
|
// Change Minor ...
|
|
has = !NotEmpty(tmp) ||
|
|
tmp < iValue;
|
|
if (has)
|
|
{
|
|
tmp = iValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Last Update of Minore Minor ...
|
|
has = NotEmpty(tmp);
|
|
if (has)
|
|
{
|
|
_minor = tmp;
|
|
}
|
|
|
|
//
|
|
result = NotEmpty(_major) ||
|
|
NotEmpty(_minor);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Find Index |
|
|
//+------------------------------------------------------------------+
|
|
/**
|
|
* Find Specified Item index in a Collection ...
|
|
*
|
|
* @param index: int, reference to Hold Index if Exists ...
|
|
* @param item: Specified item to Detect ...
|
|
* @param source: Collection to Search for item ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool FindIndex(
|
|
int &index,
|
|
XBoxZone &item,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
result = item.IsValid() &&
|
|
IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
bool isSame = item.IsSameAs(source[i]);
|
|
if (isSame)
|
|
{
|
|
//
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Find Specified Item index in a Collection ...
|
|
*
|
|
* @param index: int, reference to Hold Index if Exists ...
|
|
* @param item: Specified item to Detect ...
|
|
* @param source: Collection to Search for item ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool FindIndex(
|
|
int &index,
|
|
XPivot &item,
|
|
XPivot &source[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
result = item.IsValid() &&
|
|
IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
bool isSame = item.IsSameAs(source[i]);
|
|
if (isSame)
|
|
{
|
|
//
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Find Specified Item index in a Collection ...
|
|
*
|
|
* @param index: int, reference to Hold Index if Exists ...
|
|
* @param item: Specified item to Detect ...
|
|
* @param source: Collection to Search for item ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool FindIndex(
|
|
int &index,
|
|
XDirectionShift &item,
|
|
XDirectionShift &source[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
result = item.IsValid() &&
|
|
IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
bool isSame = item.IsSameAs(source[i]);
|
|
if (isSame)
|
|
{
|
|
//
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Remove |
|
|
//+------------------------------------------------------------------+
|
|
/**
|
|
* Remove Specified Item from a Collection ...
|
|
*
|
|
* @param item: Specified Item ...
|
|
* @param source: Specified Collection for Remove item from it ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Remove(
|
|
XPivot &item,
|
|
XPivot &source[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
item.IsValid() &&
|
|
HasChild(source);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
result = FindIndex(
|
|
idx,
|
|
item,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArrayRemove(
|
|
source,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Remove Specified Item from a Collection ...
|
|
*
|
|
* @param item: Specified Item ...
|
|
* @param source: Specified Collection for Remove item from it ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Remove(
|
|
XBoxZone &item,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
item.IsValid() &&
|
|
HasChild(source);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
result = FindIndex(
|
|
idx,
|
|
item,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArrayRemove(
|
|
source,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Remove Specified Item from a Collection ...
|
|
*
|
|
* @param item: Specified Item ...
|
|
* @param source: Specified Collection for Remove item from it ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Remove(
|
|
XDirectionShift &item,
|
|
XDirectionShift &source[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
item.IsValid() &&
|
|
HasChild(source);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
result = FindIndex(
|
|
idx,
|
|
item,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArrayRemove(
|
|
source,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Remove Specified items from a Collection ...
|
|
*
|
|
* @param items: Specified Items to Remove ...
|
|
* @param sources: Sepcified Collection for Removing items from it ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int Removes(
|
|
XBoxZone &items[],
|
|
XBoxZone &sources[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
bool has = HasChild(items) &&
|
|
HasChild(sources);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
has = false;
|
|
int count = ArraySize(items);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Detect Item Index in Collection ...
|
|
has = FindIndex(
|
|
idx,
|
|
items[i],
|
|
sources //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Remove Detected Index from Collection ...
|
|
has = ArrayRemove(
|
|
sources,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
//
|
|
// Count Removed Items ...
|
|
result++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Remove Specified items from a Collection ...
|
|
*
|
|
* @param items: Specified Items to Remove ...
|
|
* @param sources: Sepcified Collection for Removing items from it ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int Removes(
|
|
XPivot &items[],
|
|
XPivot &sources[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
bool has = HasChild(items) &&
|
|
HasChild(sources);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
has = false;
|
|
int count = ArraySize(items);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Detect Item Index in Collection ...
|
|
has = FindIndex(
|
|
idx,
|
|
items[i],
|
|
sources //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Remove Detected Index from Collection ...
|
|
has = ArrayRemove(
|
|
sources,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
//
|
|
// Count Removed Items ...
|
|
result++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Remove Specified items from a Collection ...
|
|
*
|
|
* @param items: Specified Items to Remove ...
|
|
* @param sources: Sepcified Collection for Removing items from it ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int Removes(
|
|
XDirectionShift &items[],
|
|
XDirectionShift &sources[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
bool has = HasChild(items) &&
|
|
HasChild(sources);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
has = false;
|
|
int count = ArraySize(items);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Detect Item Index in Collection ...
|
|
has = FindIndex(
|
|
idx,
|
|
items[i],
|
|
sources //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Remove Detected Index from Collection ...
|
|
has = ArrayRemove(
|
|
sources,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
//
|
|
// Count Removed Items ...
|
|
result++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Add If Not Exists |
|
|
//+------------------------------------------------------------------+
|
|
/**
|
|
* Add Specified Item to Specified Collection, if not Exists ...
|
|
*
|
|
* @param item: Item to Add ...
|
|
* @param sources: Collection to Add item ...
|
|
* @param maxAllowed: int, Max Allowed Collection Size ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool AddIfNotExists(
|
|
XBoxZone &item,
|
|
XBoxZone &sources[],
|
|
int maxAllowed = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
result = item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Item Exists or not ...
|
|
int idx = -1;
|
|
bool isExists = FindIndex(
|
|
idx,
|
|
item,
|
|
sources //
|
|
);
|
|
result = !isExists;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
item,
|
|
sources //
|
|
);
|
|
|
|
//
|
|
// Handle Cleanup Collection
|
|
// if Max Reached ...
|
|
if (result &&
|
|
maxAllowed > 0)
|
|
{
|
|
//
|
|
CleanupArray(
|
|
sources,
|
|
maxAllowed //
|
|
);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Add Specified Item to Specified Collection, if not Exists ...
|
|
*
|
|
* @param item: Item to Add ...
|
|
* @param sources: Collection to Add item ...
|
|
* @param maxAllowed: int, Max Allowed Collection Size ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool AddIfNotExists(
|
|
XPivot &item,
|
|
XPivot &sources[],
|
|
int maxAllowed = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
result = item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Item Exists or not ...
|
|
int idx = -1;
|
|
bool isExists = FindIndex(
|
|
idx,
|
|
item,
|
|
sources //
|
|
);
|
|
result = !isExists;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
item,
|
|
sources //
|
|
);
|
|
|
|
//
|
|
// Handle Cleanup Collection
|
|
// if Max Reached ...
|
|
if (result &&
|
|
maxAllowed > 0)
|
|
{
|
|
//
|
|
CleanupArray(
|
|
sources,
|
|
maxAllowed //
|
|
);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Add Specified Item to Specified Collection, if not Exists ...
|
|
*
|
|
* @param item: Item to Add ...
|
|
* @param sources: Collection to Add item ...
|
|
* @param maxAllowed: int, Max Allowed Collection Size ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool AddIfNotExists(
|
|
XDirectionShift &item,
|
|
XDirectionShift &sources[],
|
|
int maxAllowed = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
result = item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Item Exists or not ...
|
|
int idx = -1;
|
|
bool isExists = FindIndex(
|
|
idx,
|
|
item,
|
|
sources //
|
|
);
|
|
result = !isExists;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
item,
|
|
sources //
|
|
);
|
|
|
|
//
|
|
// Handle Cleanup Collection
|
|
// if Max Reached ...
|
|
if (result &&
|
|
maxAllowed > 0)
|
|
{
|
|
//
|
|
CleanupArray(
|
|
sources,
|
|
maxAllowed //
|
|
);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int FillNotExists(
|
|
T &dest[],
|
|
T &source[],
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
|
|
int maxAllowed = 0 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
XClean(dest);
|
|
|
|
//
|
|
// Normalize ...
|
|
maxAllowed = NormalizeInt(maxAllowed, 0);
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = HasChild(source);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has =
|
|
source[i].IsValid() &&
|
|
(!HasDirection(forDir) || forDir == source[i].dir);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
has = AddIfNotExists(source[i], dest);
|
|
if (has)
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle Cleanup Collection
|
|
// if Max Reached ...
|
|
if (maxAllowed > 0)
|
|
{
|
|
//
|
|
CleanupArray(
|
|
dest,
|
|
maxAllowed //
|
|
);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Extract |
|
|
//+------------------------------------------------------------------+
|
|
|
|
/**
|
|
* Extract Specified Directional Items ...
|
|
*
|
|
* @param dest: reference collection to holds extracted items ...
|
|
* @param source: reference collection to provides data source ...
|
|
* @param forDir: Specified which direction to Extract items ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
template <typename T>
|
|
int ExtractByDirection(
|
|
T &dest[],
|
|
T &source[],
|
|
ENUM_X_DIRECTION forDir //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
XClean(dest);
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = HasChild(source) &&
|
|
HasDirection(forDir);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = source[i].dir == forDir;
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
source[i],
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Other Extensions |
|
|
//+------------------------------------------------------------------+
|
|
|
|
/**
|
|
* Validate Boxes ...
|
|
* @param box: XBoxZone instance reference for Validate ...
|
|
* @param barIndex: int, Bar Index ...
|
|
* @param barsLength: int, Bars Length for Validation ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxValid(
|
|
XBoxZone &box,
|
|
int barIndex = 0,
|
|
int barsLength = 3 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize Bar Index ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
barsLength = NormalizeInt(barsLength, 1);
|
|
|
|
//
|
|
// Ceck Input Box is Valid ...
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Input Box is Breaked or not ...
|
|
// Breaktion Found using Counting Over/Under Close Bars ...
|
|
bool isBullish = box.IsBullish();
|
|
double appliedPrice = box.GetInDirectionalPrice();
|
|
result = NotEmptyZero(appliedPrice);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int toIDX = box.ToIndex();
|
|
|
|
//
|
|
XOHCL iBar;
|
|
int edgeBreakes = 0;
|
|
for (int i = barIndex; i <= toIDX; i++)
|
|
{
|
|
//
|
|
// Initialize Indexed Bar ...
|
|
result = iBar.Init(
|
|
box.symbol,
|
|
box.period,
|
|
i //
|
|
);
|
|
|
|
//
|
|
// Checking Price ...
|
|
result =
|
|
//
|
|
// Checking Bar Validation ...
|
|
result &&
|
|
//
|
|
// Checking Price Breaked or not ...
|
|
(isBullish
|
|
? iBar.close < box.lower
|
|
: iBar.close > box.upper);
|
|
if (result)
|
|
{
|
|
edgeBreakes++;
|
|
}
|
|
else
|
|
{
|
|
edgeBreakes = 0;
|
|
}
|
|
|
|
//
|
|
result = edgeBreakes >= barsLength;
|
|
if (result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
// return true;
|
|
|
|
//
|
|
result =
|
|
edgeBreakes < barsLength;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void SortBoxes(
|
|
XBoxZone &items[],
|
|
int maxAllowed = 0 //
|
|
)
|
|
{
|
|
//
|
|
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 //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (maxAllowed > 0)
|
|
{
|
|
//
|
|
CleanupArray(
|
|
items,
|
|
maxAllowed //
|
|
);
|
|
}
|
|
|
|
//
|
|
Clean(tmp);
|
|
}
|
|
|
|
/**
|
|
* Check a BaxHas Valid Place for Specified Bar ...
|
|
*
|
|
* @param bar: XOHCL instance reference, Specified Bar ...
|
|
* #param box: XBoxZone instance reference, Specified Box ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxPlaceValidForBar(
|
|
XOHCL &bar,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
box.IsBullish()
|
|
? bar.low > box.upper
|
|
: bar.high < box.upper;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void ValidateBoxes(
|
|
XBoxZone &boxes[],
|
|
int barIndex = 0,
|
|
int barsLength = 3,
|
|
bool forceSorting = false,
|
|
int maxAllowed = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool has = false;
|
|
|
|
//
|
|
// Normalize Args ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
barsLength = NormalizeInt(barsLength, 3);
|
|
|
|
//
|
|
// Validate Args ...
|
|
has = HasChild(boxes);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Copy Boxes to tmp ...
|
|
XBoxZone tmp[];
|
|
Copy(
|
|
boxes,
|
|
tmp //
|
|
);
|
|
Clean(boxes);
|
|
|
|
//
|
|
// Looping Through Exists Boxes ...
|
|
while (HasChild(tmp))
|
|
{
|
|
//
|
|
// Select Indexed Box ...
|
|
XBoxZone iBox = tmp[0];
|
|
|
|
//
|
|
// Remove Indexed Box ...
|
|
ArrayRemove(
|
|
tmp,
|
|
0,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Check Box Validating ...
|
|
has = IsBoxValid(
|
|
iBox,
|
|
barIndex,
|
|
barsLength //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
boxes //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Sorting ...
|
|
if (forceSorting)
|
|
{
|
|
//
|
|
// Check Has Result or not ...
|
|
has = HasChild(boxes);
|
|
if (has)
|
|
{
|
|
//
|
|
// Sorting ...
|
|
SortBoxes(
|
|
boxes,
|
|
maxAllowed //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
}
|
|
|
|
void UpdateToTime(
|
|
XBoxZone &zones[],
|
|
datetime toTime = NULL //
|
|
)
|
|
{
|
|
//
|
|
// Normalize ...
|
|
toTime = NormalizeTime(toTime);
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = HasChild(zones);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(zones);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
zones[i].to = toTime;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove Breaked Zones from a Collection ...
|
|
*
|
|
* @param source: XBoxZone, reference to Specified Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int RemoveBreakedZones(
|
|
XBoxZone &source[],
|
|
bool forceBreak = false //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = HasChild(source);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone iZone;
|
|
XBoxZone tmps[];
|
|
Copy(
|
|
source,
|
|
tmps //
|
|
);
|
|
XClean(source);
|
|
XOHCL tmpBars[];
|
|
int breakerBars = 0;
|
|
while (HasChild(tmps))
|
|
{
|
|
//
|
|
iZone.Clean();
|
|
iZone = tmps[0];
|
|
ArrayRemove(tmps, 0, 1);
|
|
has = IsXValid(iZone.breakAt);
|
|
if (has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (forceBreak)
|
|
{
|
|
//
|
|
breakerBars = GetBreakerBars(iZone, tmpBars);
|
|
has = IsValidSize(breakerBars);
|
|
}
|
|
if (has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iZone,
|
|
source //
|
|
);
|
|
}
|
|
|
|
//
|
|
result = ArraySize(source);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Remove Filled Zones ...
|
|
*
|
|
* @param source: XBoxZone, collection reference to Provide Data Source ...
|
|
* @param zoneRangeFilledFactor: double, Filling Factor ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int RemoveFilledZones(
|
|
XBoxZone &source[],
|
|
double zoneRangeFilledFactor = 0.8 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = HasChild(source);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone iTMP;
|
|
XBoxZone tmp[];
|
|
Copy(source, tmp);
|
|
XClean(source);
|
|
while (HasChild(tmp))
|
|
{
|
|
//
|
|
iTMP.Clean();
|
|
iTMP = tmp[0];
|
|
ArrayRemove(tmp, 0, 1);
|
|
|
|
//
|
|
has = IsFilled(iTMP, zoneRangeFilledFactor);
|
|
if (!has)
|
|
{
|
|
AddIfNotExists(iTMP, source);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(source);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
// #region Zone Converters ...
|
|
/**
|
|
* Converts a Bar to Pivot ...
|
|
*
|
|
* @param bar: XOHCL, reference to Specified Bar ...
|
|
* @param pivot: XPivot, reference to holds result ...
|
|
* @param forDir: ENUM_X_DIRECTION, specified Pivot Direction ...
|
|
* @param prefix: string, Specified Pivot Prefix (used for Object Type) ...
|
|
* @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ...
|
|
* @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToPivot(
|
|
XOHCL &bar,
|
|
XPivot &pivot,
|
|
ENUM_X_DIRECTION forDir,
|
|
string prefix = NULL,
|
|
ENUM_X_PRICE peakPriceType = X_PRICE_HIGH,
|
|
ENUM_X_PRICE valePriceType = X_PRICE_LOW //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
pivot.Clean();
|
|
|
|
//
|
|
// Normalize ...
|
|
if (!IsXValid(peakPriceType))
|
|
{
|
|
peakPriceType = X_PRICE_HIGH;
|
|
}
|
|
if (!IsXValid(valePriceType))
|
|
{
|
|
valePriceType = X_PRICE_LOW;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
HasDirection(forDir) &&
|
|
IsXValid(peakPriceType) &&
|
|
IsXValid(valePriceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Direction ...
|
|
bool isBullish = IsSpecifiedBullish(forDir);
|
|
|
|
//
|
|
// Prepare Value of Pivot ...
|
|
double iValue =
|
|
isBullish
|
|
? bar.GetPrice(valePriceType)
|
|
: bar.GetPrice(peakPriceType);
|
|
|
|
//
|
|
// Prepare Pivot Type ...
|
|
ENUM_X_PIVOT_TYPE iType =
|
|
isBullish
|
|
? X_PIVOT_TYPE_VALE
|
|
: X_PIVOT_TYPE_PEAK;
|
|
|
|
//
|
|
// Initialize Pivot ...
|
|
result = pivot.Init(
|
|
iValue,
|
|
bar.time,
|
|
bar.symbol,
|
|
forDir,
|
|
bar.period,
|
|
iType //
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
// Set Prefix if Pivot initialized successfully ...
|
|
pivot.prefix = prefix;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = pivot.IsValid();
|
|
if (!result)
|
|
{
|
|
pivot.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts a Bar to Pattern Pivot ...
|
|
*
|
|
* @param bar: XOHCL, reference to Specified Bar ...
|
|
* @param pivot: XPivot, reference to holds result ...
|
|
* @param patternDir: ENUM_X_DIRECTION, specified Pivot Direction ...
|
|
* @param pattern: ENUM_X_BAR_PATTERN, Specified Pattern Type ...
|
|
* @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ...
|
|
* @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToPivot(
|
|
XOHCL &bar,
|
|
XPivot &pivot,
|
|
ENUM_X_DIRECTION patternDir,
|
|
ENUM_X_BAR_PATTERN pattern,
|
|
ENUM_X_PRICE peakPriceType = X_PRICE_HIGH,
|
|
ENUM_X_PRICE valePriceType = X_PRICE_LOW //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
pivot.Clean();
|
|
|
|
//
|
|
// Normalize ...
|
|
if (!IsXValid(peakPriceType))
|
|
{
|
|
peakPriceType = X_PRICE_HIGH;
|
|
}
|
|
if (!IsXValid(valePriceType))
|
|
{
|
|
valePriceType = X_PRICE_LOW;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
IsXValid(pattern) &&
|
|
IsXValid(peakPriceType) &&
|
|
IsXValid(valePriceType) &&
|
|
HasDirection(patternDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
datetime iTime = bar.time;
|
|
string iSymbol = bar.symbol;
|
|
string iPrefix = ToXString(pattern);
|
|
ENUM_TIMEFRAMES iPeriod = bar.period;
|
|
double iValue = IsXBullish(patternDir)
|
|
? bar.GetPrice(X_PRICE_LOW)
|
|
: IsXBearish(patternDir)
|
|
? bar.GetPrice(X_PRICE_HIGH)
|
|
: EMPTY_VALUE;
|
|
ENUM_X_PIVOT_TYPE iType = IsXBullish(patternDir)
|
|
? X_PIVOT_TYPE_VALE
|
|
: IsXBearish(patternDir)
|
|
? X_PIVOT_TYPE_PEAK
|
|
: X_PIVOT_TYPE_NONE;
|
|
|
|
//
|
|
result = pivot.Init(
|
|
iValue,
|
|
iTime,
|
|
iSymbol,
|
|
patternDir,
|
|
iPeriod,
|
|
iType //
|
|
);
|
|
if (result)
|
|
{
|
|
pivot.prefix = iPrefix;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
if (!result)
|
|
{
|
|
pivot.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts POI Bar to Box ...
|
|
*
|
|
* @param bar: XOHCL, reference to Specified Pattern ...
|
|
* @param box: XBoxZone, reference to holds result ...
|
|
* @param forDir: ENUM_X_DIRECTION, Specified Pattern Direction ...
|
|
* @param prefix: string, Specified Pattern Type ...
|
|
* @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ...
|
|
* @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ...
|
|
* @param setFromByBreakerBar: bool, Set Box From Time to Breaker Bar ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XOHCL &bar,
|
|
XBoxZone &box,
|
|
ENUM_X_DIRECTION forDir,
|
|
string prefix = NULL,
|
|
ENUM_X_PRICE peakPriceType = X_PRICE_HIGH,
|
|
ENUM_X_PRICE valePriceType = X_PRICE_LOW,
|
|
bool setFromByBreakerBar = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
box.Clean();
|
|
|
|
//
|
|
// Normalize ...
|
|
if (!IsXValid(peakPriceType))
|
|
{
|
|
peakPriceType = X_PRICE_HIGH;
|
|
}
|
|
if (!IsXValid(valePriceType))
|
|
{
|
|
valePriceType = X_PRICE_LOW;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
HasDirection(forDir) &&
|
|
IsXValid(peakPriceType) &&
|
|
IsXValid(valePriceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check if is Valid Pattern ...
|
|
ENUM_X_BAR_PATTERN iPattern = ToBarPattern(prefix);
|
|
result = IsXValid(iPattern);
|
|
if (result)
|
|
{
|
|
//
|
|
// Conver to Box as Pattern ...
|
|
result = ToBox(
|
|
bar,
|
|
box,
|
|
forDir,
|
|
iPattern,
|
|
peakPriceType,
|
|
valePriceType,
|
|
setFromByBreakerBar //
|
|
);
|
|
}
|
|
//
|
|
// There is not any Valid Pattern Provided ...
|
|
else
|
|
{
|
|
//
|
|
bool isBullish = IsXBullish(forDir);
|
|
double peakPrice = bar.GetPrice(peakPriceType);
|
|
double valePrice = bar.GetPrice(valePriceType);
|
|
|
|
//
|
|
string iType = prefix;
|
|
datetime iAt = bar.time;
|
|
datetime iTo = bar.time;
|
|
double iUpper = peakPrice;
|
|
double iLower = valePrice;
|
|
string iSymbol = bar.symbol;
|
|
datetime iFrom = bar.BeforeOn();
|
|
ENUM_TIMEFRAMES iPeriod = bar.period;
|
|
|
|
//
|
|
// Assign Values to Box ...
|
|
box.at = iAt;
|
|
box.to = iTo;
|
|
box.from = iFrom;
|
|
box.type = iType;
|
|
box.dir = forDir;
|
|
box.upper = iUpper;
|
|
box.lower = iLower;
|
|
box.symbol = iSymbol;
|
|
box.period = iPeriod;
|
|
}
|
|
|
|
//
|
|
// Validate result ...
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts Pattern Bar to Box ...
|
|
*
|
|
* @param bar: XOHCL, reference to Specified Pattern ...
|
|
* @param box: XBoxZone, reference to holds result ...
|
|
* @param forDir: ENUM_X_DIRECTION, Specified Pattern Direction ...
|
|
* @param prefix: string, Specified Pattern Type ...
|
|
* @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ...
|
|
* @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ...
|
|
* @param setFromByBreakerBar: bool, Set Box From Time to Breaker Bar ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XOHCL &bar,
|
|
XBoxZone &box,
|
|
ENUM_X_DIRECTION patternDir,
|
|
ENUM_X_BAR_PATTERN pattern,
|
|
ENUM_X_PRICE peakPriceType = X_PRICE_HIGH,
|
|
ENUM_X_PRICE valePriceType = X_PRICE_LOW,
|
|
bool setFromByBreakerBar = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
box.Clean();
|
|
|
|
//
|
|
// Normalize ...
|
|
if (!IsXValid(peakPriceType))
|
|
{
|
|
peakPriceType = X_PRICE_HIGH;
|
|
}
|
|
if (!IsXValid(valePriceType))
|
|
{
|
|
valePriceType = X_PRICE_LOW;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
IsXValid(pattern) &&
|
|
IsXValid(peakPriceType) &&
|
|
IsXValid(valePriceType) &&
|
|
HasDirection(patternDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Define Requirements ...
|
|
XOHCL tmpBar;
|
|
XBoxZone tmpBox;
|
|
bool has = false;
|
|
datetime iAt = bar.time;
|
|
datetime iTo = bar.time;
|
|
double iUpper = EMPTY_VALUE;
|
|
double iLower = EMPTY_VALUE;
|
|
string iSymbol = bar.symbol;
|
|
datetime iFrom = bar.BeforeOn();
|
|
string iType = ToXString(pattern);
|
|
ENUM_TIMEFRAMES iPeriod = bar.period;
|
|
|
|
//
|
|
bool isBullish = IsXBullish(patternDir);
|
|
double peakPrice = bar.GetPrice(peakPriceType);
|
|
double valePrice = bar.GetPrice(valePriceType);
|
|
|
|
//
|
|
// Calculate Requirements Based on Pattern Type and Direction ...
|
|
switch (pattern)
|
|
{
|
|
//
|
|
case X_BAR_PATTERN_HIGH: {
|
|
//
|
|
if (setFromByBreakerBar)
|
|
{
|
|
//
|
|
tmpBar.Clean();
|
|
has = GetBreakerBar(
|
|
bar,
|
|
tmpBar,
|
|
peakPriceType,
|
|
peakPriceType,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
if (has)
|
|
{
|
|
iFrom = tmpBar.time;
|
|
}
|
|
}
|
|
|
|
//
|
|
iUpper = peakPrice;
|
|
iLower = bar.GetUp();
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_LOW: {
|
|
//
|
|
if (setFromByBreakerBar)
|
|
{
|
|
//
|
|
tmpBar.Clean();
|
|
has = GetBreakerBar(
|
|
bar,
|
|
tmpBar,
|
|
valePriceType,
|
|
valePriceType,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
if (has)
|
|
{
|
|
iFrom = tmpBar.time;
|
|
}
|
|
}
|
|
|
|
//
|
|
iUpper = bar.GetDown();
|
|
iLower = valePrice;
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_MOMENTUM: {
|
|
//
|
|
if (setFromByBreakerBar)
|
|
{
|
|
//
|
|
tmpBar.Clean();
|
|
ENUM_X_PRICE iPType = isBullish
|
|
? valePriceType
|
|
: peakPriceType;
|
|
has = GetBreakerBar(
|
|
bar,
|
|
tmpBar,
|
|
iPType,
|
|
iPType,
|
|
patternDir //
|
|
);
|
|
if (has)
|
|
{
|
|
iFrom = tmpBar.time;
|
|
}
|
|
}
|
|
|
|
//
|
|
iUpper = peakPrice;
|
|
iLower = valePrice;
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_ENGULFED: {
|
|
//
|
|
if (setFromByBreakerBar)
|
|
{
|
|
//
|
|
tmpBar.Clean();
|
|
ENUM_X_PRICE iPType = isBullish
|
|
? valePriceType
|
|
: peakPriceType;
|
|
has = GetBreakerBar(
|
|
bar,
|
|
tmpBar,
|
|
iPType,
|
|
iPType,
|
|
patternDir //
|
|
);
|
|
if (has)
|
|
{
|
|
iFrom = tmpBar.time;
|
|
}
|
|
}
|
|
|
|
//
|
|
iUpper = peakPrice;
|
|
iLower = valePrice;
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_TRUE_GAPED: {
|
|
//
|
|
tmpBar.Clean();
|
|
has = bar.GetPreviousBar(tmpBar);
|
|
if (has)
|
|
{
|
|
//
|
|
iFrom = tmpBar.time;
|
|
|
|
//
|
|
iUpper =
|
|
isBullish
|
|
? valePrice
|
|
: tmpBar.GetPrice(valePriceType);
|
|
iLower =
|
|
isBullish
|
|
? tmpBar.GetPrice(peakPriceType)
|
|
: peakPrice;
|
|
}
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_PINNED: {
|
|
//
|
|
if (setFromByBreakerBar)
|
|
{
|
|
//
|
|
tmpBar.Clean();
|
|
ENUM_X_PRICE iPType = isBullish
|
|
? valePriceType
|
|
: peakPriceType;
|
|
has = GetBreakerBar(
|
|
bar,
|
|
tmpBar,
|
|
iPType,
|
|
iPType,
|
|
patternDir //
|
|
);
|
|
if (has)
|
|
{
|
|
iFrom = tmpBar.time;
|
|
}
|
|
}
|
|
|
|
//
|
|
iUpper =
|
|
isBullish
|
|
? bar.GetDown()
|
|
: peakPrice;
|
|
iLower =
|
|
isBullish
|
|
? valePrice
|
|
: bar.GetUp();
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_STAR: {
|
|
//
|
|
tmpBar.Clean();
|
|
ENUM_X_PRICE iPType = isBullish
|
|
? valePriceType
|
|
: peakPriceType;
|
|
has = GetBreakerBar(
|
|
bar,
|
|
tmpBar,
|
|
iPType,
|
|
iPType,
|
|
patternDir //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
if (setFromByBreakerBar)
|
|
{
|
|
iFrom = tmpBar.time;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
int mLength = tmpBar.Index() - bar.Index();
|
|
iLower = bar.FindLowest(idx, mLength, valePriceType);
|
|
iUpper = bar.FindHighest(idx, mLength, peakPriceType);
|
|
}
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_PIERCING: {
|
|
//
|
|
if (setFromByBreakerBar)
|
|
{
|
|
//
|
|
tmpBar.Clean();
|
|
ENUM_X_PRICE iPType = isBullish
|
|
? valePriceType
|
|
: peakPriceType;
|
|
has = GetBreakerBar(
|
|
bar,
|
|
tmpBar,
|
|
iPType,
|
|
iPType,
|
|
patternDir //
|
|
);
|
|
if (has)
|
|
{
|
|
iFrom = tmpBar.time;
|
|
}
|
|
}
|
|
|
|
//
|
|
iUpper = peakPrice;
|
|
iLower = valePrice;
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_RISING: {
|
|
//
|
|
if (setFromByBreakerBar)
|
|
{
|
|
//
|
|
tmpBar.Clean();
|
|
ENUM_X_PRICE iPType = isBullish
|
|
? valePriceType
|
|
: peakPriceType;
|
|
has = GetBreakerBar(
|
|
bar,
|
|
tmpBar,
|
|
iPType,
|
|
iPType,
|
|
patternDir //
|
|
);
|
|
if (has)
|
|
{
|
|
iFrom = tmpBar.time;
|
|
}
|
|
}
|
|
|
|
//
|
|
iUpper = peakPrice;
|
|
iLower = valePrice;
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_FLAG: {
|
|
//
|
|
if (setFromByBreakerBar)
|
|
{
|
|
//
|
|
tmpBar.Clean();
|
|
ENUM_X_PRICE iPType = isBullish
|
|
? valePriceType
|
|
: peakPriceType;
|
|
has = GetBreakerBar(
|
|
bar,
|
|
tmpBar,
|
|
iPType,
|
|
iPType,
|
|
patternDir //
|
|
);
|
|
if (has)
|
|
{
|
|
iFrom = tmpBar.time;
|
|
}
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
int mLength = 3;
|
|
iUpper = bar.FindHighest(idx, mLength, peakPriceType);
|
|
iLower = bar.FindLowest(idx, mLength, valePriceType);
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_SIGNALKEY: {
|
|
//
|
|
if (setFromByBreakerBar)
|
|
{
|
|
//
|
|
tmpBar.Clean();
|
|
ENUM_X_PRICE iPType = isBullish
|
|
? valePriceType
|
|
: peakPriceType;
|
|
has = GetBreakerBar(
|
|
bar,
|
|
tmpBar,
|
|
iPType,
|
|
iPType,
|
|
patternDir //
|
|
);
|
|
if (has)
|
|
{
|
|
iFrom = tmpBar.time;
|
|
}
|
|
}
|
|
|
|
//
|
|
has = bar.GetPreviousBar(tmpBar);
|
|
if (has)
|
|
{
|
|
//
|
|
iUpper = MathMax(peakPrice, tmpBar.GetPrice(peakPriceType));
|
|
iLower = MathMin(valePrice, tmpBar.GetPrice(valePriceType));
|
|
}
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_OB: {
|
|
//
|
|
tmpBox.Clean();
|
|
has = ToOBBox(
|
|
bar,
|
|
tmpBox,
|
|
patternDir //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
iFrom = tmpBox.from;
|
|
iUpper = tmpBox.upper;
|
|
iLower = tmpBox.lower;
|
|
}
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_FVG: {
|
|
//
|
|
tmpBox.Clean();
|
|
has = ToFVGBox(
|
|
bar,
|
|
tmpBox,
|
|
patternDir //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
iFrom = tmpBox.from;
|
|
iUpper = tmpBox.upper;
|
|
iLower = tmpBox.lower;
|
|
}
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_SUPPORT: {
|
|
//
|
|
if (setFromByBreakerBar)
|
|
{
|
|
//
|
|
tmpBar.Clean();
|
|
ENUM_X_PRICE iPType = isBullish
|
|
? valePriceType
|
|
: peakPriceType;
|
|
has = GetBreakerBar(
|
|
bar,
|
|
tmpBar,
|
|
iPType,
|
|
iPType,
|
|
patternDir //
|
|
);
|
|
if (has)
|
|
{
|
|
iFrom = tmpBar.time;
|
|
}
|
|
}
|
|
|
|
//
|
|
iUpper =
|
|
isBullish
|
|
? peakPrice
|
|
: valePrice;
|
|
iLower =
|
|
isBullish
|
|
? peakPrice
|
|
: valePrice;
|
|
}
|
|
break;
|
|
|
|
//
|
|
case X_BAR_PATTERN_RESISTANCE: {
|
|
//
|
|
if (setFromByBreakerBar)
|
|
{
|
|
//
|
|
tmpBar.Clean();
|
|
ENUM_X_PRICE iPType = isBullish
|
|
? valePriceType
|
|
: peakPriceType;
|
|
has = GetBreakerBar(
|
|
bar,
|
|
tmpBar,
|
|
iPType,
|
|
iPType,
|
|
patternDir //
|
|
);
|
|
if (has)
|
|
{
|
|
iFrom = tmpBar.time;
|
|
}
|
|
}
|
|
|
|
//
|
|
iUpper =
|
|
isBullish
|
|
? peakPrice
|
|
: valePrice;
|
|
iLower =
|
|
isBullish
|
|
? peakPrice
|
|
: valePrice;
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Assign Values to Box ...
|
|
box.at = iAt;
|
|
box.to = iTo;
|
|
box.from = iFrom;
|
|
box.type = iType;
|
|
box.upper = iUpper;
|
|
box.lower = iLower;
|
|
box.symbol = iSymbol;
|
|
box.period = iPeriod;
|
|
box.dir = patternDir;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
if (!result)
|
|
{
|
|
box.Clean();
|
|
}
|
|
tmpBar.Clean();
|
|
tmpBox.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts Order Flow to Zone ...
|
|
*
|
|
* @param zone: XBoxZone, reference to holds result ...
|
|
* @param orderFlow: XBoxZone, collection reference to provides order flow ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &zone,
|
|
XBoxZone &orderFlow[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
zone.Clean();
|
|
|
|
//
|
|
// Validate ...
|
|
result = HasChild(orderFlow);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
zone = orderFlow[0];
|
|
int idx = GetHighest(orderFlow);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
zone.upper = orderFlow[idx].upper;
|
|
}
|
|
idx = GetLowest(orderFlow);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
zone.lower = orderFlow[idx].lower;
|
|
}
|
|
|
|
//
|
|
zone.type = "XOrderFlowP";
|
|
|
|
//
|
|
result = zone.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts a Bar to OB Box ...
|
|
*
|
|
* @param bar: XOHCL, Specified Bar ...
|
|
* @param box: XBoxZone, destination Box ...
|
|
* @param forDir: ENUM_X_DIRECTION, Specified Direction ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToOBBox(
|
|
XOHCL &bar,
|
|
XBoxZone &box,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
box.Clean();
|
|
|
|
//
|
|
// Normalize ...
|
|
if (!HasDirection(forDir))
|
|
{
|
|
forDir = bar.GetDirection();
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
HasDirection(forDir) &&
|
|
bar.GetDirection() == forDir;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detect OB Start Bar ...
|
|
XOHCL obStartBar;
|
|
result = GetDirectionalBar(
|
|
bar,
|
|
obStartBar,
|
|
Opposit(forDir) //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
obStartBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.dir = forDir;
|
|
box.to = bar.time;
|
|
box.at = bar.time;
|
|
box.symbol = bar.symbol;
|
|
box.period = bar.period;
|
|
box.from = obStartBar.time;
|
|
box.type = ToXString(X_BAR_PATTERN_OB);
|
|
box.lower = MathMin(obStartBar.low, bar.low);
|
|
box.upper = MathMax(obStartBar.high, bar.high);
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
if (!result)
|
|
{
|
|
box.Clean();
|
|
}
|
|
obStartBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts a Bar to FVG Box ...
|
|
*
|
|
* @param bar: XOHCL, Specified Bar ...
|
|
* @param box: XBoxZone, destination Box ...
|
|
* @param forDir: ENUM_X_DIRECTION, Specified Direction ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToFVGBox(
|
|
XOHCL &bar,
|
|
XBoxZone &box,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
box.Clean();
|
|
|
|
//
|
|
// Normalize ...
|
|
if (!HasDirection(forDir))
|
|
{
|
|
forDir = bar.GetDirection();
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
HasDirection(forDir) &&
|
|
bar.GetDirection() == forDir;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detect FVG Start Bar ...
|
|
XOHCL fvgStartBar;
|
|
result = bar.BarAt(
|
|
bar.Index() + 2,
|
|
fvgStartBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
fvgStartBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsXBullish(forDir);
|
|
|
|
//
|
|
box.dir = forDir;
|
|
box.to = bar.time;
|
|
box.at = bar.time;
|
|
box.upper =
|
|
isBullish
|
|
? bar.low
|
|
: bar.high;
|
|
box.symbol = bar.symbol;
|
|
box.period = bar.period;
|
|
box.lower =
|
|
isBullish
|
|
? fvgStartBar.high
|
|
: fvgStartBar.low;
|
|
box.from = fvgStartBar.time;
|
|
box.type = ToXString(X_BAR_PATTERN_FVG);
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
if (!result)
|
|
{
|
|
box.Clean();
|
|
}
|
|
fvgStartBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts a Bar to Support Box ...
|
|
*
|
|
* @param bar: XOHCL, Specified Bar ...
|
|
* @param box: XBoxZone, destination Box ...
|
|
* @param toTime: datetime, Specified Box to Time ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToSupportBox(
|
|
XOHCL &bar,
|
|
XBoxZone &box,
|
|
datetime toTime = NULL,
|
|
int validationLength = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
box.Clean();
|
|
|
|
//
|
|
// Normalize ...
|
|
toTime = NormalizeTime(toTime);
|
|
validationLength = NormalizeInt(validationLength, 0);
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL breaker;
|
|
result = GetBreakerBar(
|
|
bar,
|
|
breaker,
|
|
X_PRICE_LOW,
|
|
X_PRICE_DOWN,
|
|
X_DIRECTION_BEARISH,
|
|
500 //
|
|
);
|
|
if (!result)
|
|
{
|
|
breaker.Clean();
|
|
}
|
|
|
|
//
|
|
box.to = toTime;
|
|
box.at = bar.time;
|
|
box.from =
|
|
breaker.IsValid()
|
|
? breaker.time
|
|
: validationLength <= 0
|
|
? bar.time
|
|
: GetBarTime(
|
|
bar.symbol,
|
|
bar.period,
|
|
bar.Index() + validationLength //
|
|
);
|
|
box.lower = bar.low;
|
|
box.symbol = bar.symbol;
|
|
box.period = bar.period;
|
|
box.upper = bar.GetDown();
|
|
box.dir = X_DIRECTION_BULLISH;
|
|
box.type = ToXString(X_BAR_PATTERN_SUPPORT);
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
box.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts a Bar to Resistance Box ...
|
|
*
|
|
* @param bar: XOHCL, Specified Bar ...
|
|
* @param box: XBoxZone, destination Box ...
|
|
* @param toTime: datetime, Specified Box to Time ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToResistanceBox(
|
|
XOHCL &bar,
|
|
XBoxZone &box,
|
|
datetime toTime = NULL,
|
|
int validationLength = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
box.Clean();
|
|
|
|
//
|
|
// Normalize ...
|
|
toTime = NormalizeTime(toTime);
|
|
validationLength = NormalizeInt(validationLength, 0);
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL breaker;
|
|
result = GetBreakerBar(
|
|
bar,
|
|
breaker,
|
|
X_PRICE_HIGH,
|
|
X_PRICE_UP,
|
|
X_DIRECTION_BULLISH,
|
|
500 //
|
|
);
|
|
if (!result)
|
|
{
|
|
breaker.Clean();
|
|
}
|
|
|
|
//
|
|
box.to = toTime;
|
|
box.at = bar.time;
|
|
box.from =
|
|
breaker.IsValid()
|
|
? breaker.time
|
|
: validationLength <= 0
|
|
? bar.time
|
|
: GetBarTime(
|
|
bar.symbol,
|
|
bar.period,
|
|
bar.Index() + validationLength //
|
|
);
|
|
box.upper = bar.high;
|
|
box.symbol = bar.symbol;
|
|
box.period = bar.period;
|
|
box.lower = bar.GetUp();
|
|
box.dir = X_DIRECTION_BEARISH;
|
|
box.type = ToXString(X_BAR_PATTERN_RESISTANCE);
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
box.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
// #endregion
|
|
|
|
// #region Zone Checkers ...
|
|
/**
|
|
* Check a Zone is Filled or Not ...
|
|
*
|
|
* @param zone: XBoxZone, reference to Specified Zone ...
|
|
* @param zoneRangeFilledFactor: double, Filling Factor ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsFilled(
|
|
XBoxZone &zone,
|
|
double zoneRangeFilledFactor = 0.8 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result = zone.IsValid() &&
|
|
zoneRangeFilledFactor > 0 &&
|
|
zoneRangeFilledFactor < 1;
|
|
if (!result)
|
|
{
|
|
//
|
|
result = true;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL iBar;
|
|
int toIDX = zone.ToIndex();
|
|
int fromIDX = zone.FromIndex();
|
|
double zoneRangeFactor = zone.GetRange() / 100;
|
|
double useValue = zone.lower + (zoneRangeFactor * zoneRangeFilledFactor);
|
|
for (int i = toIDX; i < fromIDX; i++)
|
|
{
|
|
//
|
|
// Initialize Indexed Bar ...
|
|
iBar.Clean();
|
|
result = iBar.Init(zone.symbol, zone.period, i);
|
|
result =
|
|
result &&
|
|
(zone.IsBullish()
|
|
? iBar.GetPrice(X_PRICE_LOW) <= useValue
|
|
: iBar.GetPrice(X_PRICE_HIGH) >= useValue);
|
|
if (result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Zone is Breaked by Specified Bar or not ...
|
|
*
|
|
* @param bar: Specified Bar ...
|
|
* @param zone: Specified Zone ...
|
|
* @param forceBarEdge: bool, flag to Check Breaktion by high ot low ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBreaked(
|
|
XOHCL &bar,
|
|
XBoxZone &zone,
|
|
bool forceBarEdge = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
zone.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Break ...
|
|
result =
|
|
zone.IsBullish()
|
|
? bar.close < zone.lower
|
|
: bar.close > zone.upper;
|
|
|
|
//
|
|
// Apply Force Bar Edge ...
|
|
if (forceBarEdge)
|
|
{
|
|
//
|
|
result =
|
|
result &&
|
|
zone.IsBullish()
|
|
? bar.low > zone.upper
|
|
: bar.high < zone.lower;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Zone is Tested by Specified Bar or not ...
|
|
*
|
|
* @param bar: Specified Bar ...
|
|
* @param zone: Specified Zone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsTested(
|
|
XOHCL &bar,
|
|
XBoxZone &zone //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
zone.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Test ...
|
|
result =
|
|
zone.IsBullish()
|
|
? bar.low < zone.upper && bar.low > zone.lower
|
|
: bar.high > zone.lower &&
|
|
bar.high < zone.upper;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Zone is Rejected by Specified Bar or not ...
|
|
*
|
|
* @param bar: Specified Bar ...
|
|
* @param zone: Specified Zone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsRejected(
|
|
XOHCL &bar,
|
|
XBoxZone &zone //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
zone.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Test ...
|
|
result =
|
|
IsTested(bar, zone) &&
|
|
(zone.IsBullish()
|
|
? bar.GetDown() >= zone.upper
|
|
: bar.GetUp() <= zone.lower);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar is Inside Specified Zone or not ...
|
|
*
|
|
* @param bar: Specified Bar ...
|
|
* @param zone: Specified Zone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsInside(
|
|
XOHCL &bar,
|
|
XBoxZone &zone //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
zone.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Inside ...
|
|
result =
|
|
zone.IsBullish()
|
|
? bar.low < zone.upper &&
|
|
bar.low > zone.lower
|
|
: bar.high > zone.lower &&
|
|
bar.high < zone.upper;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar is Acted On Specified Zone or not ...
|
|
*
|
|
* @param bar: Specified Bar ...
|
|
* @param zone: Specified Zone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsActed(
|
|
XOHCL &bar,
|
|
XBoxZone &zone //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
zone.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get Previous Bar ...
|
|
XOHCL pBar;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Previous Bar must one of Following States:
|
|
// - Tested;
|
|
// - Inside;
|
|
// - Breaked;
|
|
bool isTested = IsTested(pBar, zone);
|
|
bool isInside = IsInside(pBar, zone);
|
|
bool isBreaked = IsBreaked(pBar, zone);
|
|
result = isTested ||
|
|
isInside ||
|
|
isBreaked;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Current Bar Must Close Over / Under Zone ...
|
|
result =
|
|
zone.IsBullish()
|
|
? bar.close > zone.upper
|
|
: zone.IsBearish()
|
|
? bar.close < zone.lower
|
|
: false;
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
pBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Zone is Breaked or not ...
|
|
*
|
|
* @param zone: XBoxZone, reference to Specified Zone ...
|
|
* @param priceType: ENUM_X_PRICE, Specified Price Type for Zone Break Detection ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBreaked(
|
|
XBoxZone &zone,
|
|
ENUM_X_PRICE priceType = X_PRICE_CLOSE //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result = zone.IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
//
|
|
result = true;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL iBar;
|
|
double iPrice;
|
|
bool isBullish;
|
|
int start = zone.ToIndex();
|
|
int end = zone.FromIndex();
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
//
|
|
// Initialize Indexed Bar ...
|
|
iBar.Clean();
|
|
result = iBar.Init(zone.symbol, zone.period, i);
|
|
if (!result)
|
|
{
|
|
//
|
|
result = true;
|
|
break;
|
|
}
|
|
|
|
//
|
|
isBullish = zone.IsBullish();
|
|
iPrice = iBar.GetPrice(priceType);
|
|
result = isBullish
|
|
? iPrice < zone.lower
|
|
: iPrice > zone.upper;
|
|
if (result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar is Acted On Specified Zone or not ...
|
|
*
|
|
* @param bar: Specified Bar ...
|
|
* @param zone: Specified Zone ...
|
|
* @param validationLength: Specified Length for Breaks ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValidBreaked(
|
|
XOHCL &bar,
|
|
XBoxZone &zone,
|
|
int validationLength = 3 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
validationLength = NormalizeInt(validationLength, 1);
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
zone.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL iBar;
|
|
int count = 0;
|
|
int start = bar.Index();
|
|
int end = start + validationLength;
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
//
|
|
// Initialize Indexed Bar ...
|
|
result = bar.BarAt(i, iBar);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = IsBreaked(iBar, zone);
|
|
if (result)
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidSize(count) &&
|
|
count >= validationLength;
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar is Fake Breaked Specified Zone or not ...
|
|
*
|
|
* @param bar: Specified Bar ...
|
|
* @param zone: Specified Zone ...
|
|
* @param validationLength: Specified Length for Breaks ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsFakeBreaked(
|
|
XOHCL &bar,
|
|
XBoxZone &zone,
|
|
int validationLength = 3 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
validationLength = NormalizeInt(validationLength, 1);
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
zone.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Bar Must Acting Zone ...
|
|
result = zone.IsBullish()
|
|
? bar.close > zone.upper
|
|
: zone.IsBearish()
|
|
? bar.close < zone.lower
|
|
: false;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detect Breaker Bars ...
|
|
XOHCL breakerBars[];
|
|
int breakerBarsCount = GetBreakerBars(
|
|
zone,
|
|
breakerBars //
|
|
);
|
|
result = IsValidSize(breakerBarsCount);
|
|
if (!result)
|
|
{
|
|
//
|
|
XClean(breakerBars);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get Youngest Breaker Bars ...
|
|
int idx = GetYoungest(breakerBars);
|
|
result = IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
//
|
|
XClean(breakerBars);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = breakerBars[idx].Index() - bar.Index() <= validationLength;
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
XClean(breakerBars);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified ZOne is Affected by Specified Bar or not ...
|
|
*
|
|
* @param bar: XOHCL, reference to Specified Bar ...
|
|
* @param zone: XBoxZone, reference to Specified Zone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsZoneAffected(
|
|
XOHCL &bar,
|
|
XBoxZone &zone //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
zone.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isActed = IsActed(bar, zone);
|
|
bool isTested = IsTested(bar, zone);
|
|
bool isFakeBreaked = IsFakeBreaked(bar, zone);
|
|
|
|
//
|
|
result = isActed ||
|
|
isTested ||
|
|
isFakeBreaked;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
// #endregion
|
|
|
|
// #region Zones Hasers ...
|
|
/**
|
|
* Check a Bar is Inside a Zone or not ...
|
|
*
|
|
* @param index: int, reference to holds detected index ...
|
|
* @param bar: reference to Specified Bar ...
|
|
* @param source: reference collection to provide source ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasInside(
|
|
int &index,
|
|
XOHCL &bar,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
XBoxZone selected[];
|
|
int count = ExtractInsides(bar, selected, source);
|
|
bool result = IsValidSize(count);
|
|
if (result)
|
|
{
|
|
//
|
|
index = GetYoungest(selected);
|
|
if (IsValidIndex(index))
|
|
{
|
|
result = FindIndex(index, selected[index], source);
|
|
}
|
|
}
|
|
|
|
//
|
|
XClean(selected);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Bar is Reject a Zone or not ...
|
|
*
|
|
* @param index: int, reference to holds detected index ...
|
|
* @param bar: reference to Specified Bar ...
|
|
* @param source: reference collection to provide source ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasRejected(
|
|
int &index,
|
|
XOHCL &bar,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
XBoxZone selected[];
|
|
int count = ExtractRejecteds(bar, selected, source);
|
|
bool result = IsValidSize(count);
|
|
if (result)
|
|
{
|
|
//
|
|
index = GetYoungest(selected);
|
|
if (IsValidIndex(index))
|
|
{
|
|
result = FindIndex(index, selected[index], source);
|
|
}
|
|
}
|
|
|
|
//
|
|
XClean(selected);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Bar is Break a Zone or not ...
|
|
*
|
|
* @param index: int, reference to holds detected index ...
|
|
* @param bar: reference to Specified Bar ...
|
|
* @param source: reference collection to provide source ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasBreaked(
|
|
int &index,
|
|
XOHCL &bar,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
XBoxZone selected[];
|
|
int count = ExtractBreakeds(bar, selected, source);
|
|
bool result = IsValidSize(count);
|
|
if (result)
|
|
{
|
|
//
|
|
index = GetYoungest(selected);
|
|
if (IsValidIndex(index))
|
|
{
|
|
result = FindIndex(index, selected[index], source);
|
|
}
|
|
}
|
|
|
|
//
|
|
XClean(selected);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Bar is Act a Zone or not ...
|
|
*
|
|
* @param index: int, reference to holds detected index ...
|
|
* @param bar: reference to Specified Bar ...
|
|
* @param source: reference collection to provide source ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasActed(
|
|
int &index,
|
|
XOHCL &bar,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
XBoxZone selected[];
|
|
int count = ExtractActeds(bar, selected, source);
|
|
bool result = IsValidSize(count);
|
|
if (result)
|
|
{
|
|
//
|
|
index = GetYoungest(selected);
|
|
if (IsValidIndex(index))
|
|
{
|
|
result = FindIndex(index, selected[index], source);
|
|
}
|
|
}
|
|
|
|
//
|
|
XClean(selected);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
// #endregion
|
|
|
|
// #region Zone Extractors ...
|
|
/**
|
|
* Extract Affected Zones for Specified Bar ...
|
|
*
|
|
* @param bar: XOHCL, reference to Specified Bar ...
|
|
* @param source: XBoxZone, reference collection to Provide Data Source ...
|
|
* @param dest: XBoxZone, reference collection to holds result ...
|
|
* @param forDir: ENUM_X_DIRECTION, Specified Zones Direction to Lookup ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractAffectedZones(
|
|
XOHCL &bar,
|
|
XBoxZone &source[],
|
|
XBoxZone &dest[],
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
XClean(dest);
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = bar.IsValid() &&
|
|
HasChild(source);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isActed;
|
|
bool isTested;
|
|
bool isInside;
|
|
bool isFakeBreaked;
|
|
for (int i = 0; i < ArraySize(source); i++)
|
|
{
|
|
//
|
|
// Validate Direction ...
|
|
has =
|
|
!HasDirection(forDir) ||
|
|
forDir == source[i].dir;
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Affected ...
|
|
isActed = IsActed(bar, source[i]);
|
|
isTested = IsTested(bar, source[i]);
|
|
isInside = IsInside(bar, source[i]);
|
|
isFakeBreaked = IsFakeBreaked(bar, source[i]);
|
|
|
|
//
|
|
has =
|
|
isActed ||
|
|
isTested ||
|
|
isInside ||
|
|
isFakeBreaked;
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
source[i],
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract all Items which Specified Bar is inside them ...
|
|
*
|
|
* @param bar: reference to Specified Bar ...
|
|
* @param dest: reference to result ...
|
|
* @param source: reference collection to provide source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractInsides(
|
|
XOHCL &bar,
|
|
XBoxZone &dest[],
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(dest);
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = bar.IsValid() &&
|
|
HasChild(source);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = IsInside(
|
|
bar,
|
|
source[i] //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
source[i],
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract all Items which Specified Bar is Acted them ...
|
|
*
|
|
* @param bar: reference to Specified Bar ...
|
|
* @param dest: reference to result ...
|
|
* @param source: reference collection to provide source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractActeds(
|
|
XOHCL &bar,
|
|
XBoxZone &dest[],
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
XClean(dest);
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = bar.IsValid() &&
|
|
HasChild(source);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = IsActed(
|
|
bar,
|
|
source[i] //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
source[i],
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract all Items which Specified Bar is Breaked them ...
|
|
*
|
|
* @param bar: reference to Specified Bar ...
|
|
* @param dest: reference to result ...
|
|
* @param source: reference collection to provide source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractBreakeds(
|
|
XOHCL &bar,
|
|
XBoxZone &dest[],
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(dest);
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = bar.IsValid() &&
|
|
HasChild(source);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = IsBreaked(
|
|
bar,
|
|
source[i] //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
source[i],
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract all Items which Specified Bar is Rejected them ...
|
|
*
|
|
* @param bar: reference to Specified Bar ...
|
|
* @param dest: reference to result ...
|
|
* @param source: reference collection to provide source ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractRejecteds(
|
|
XOHCL &bar,
|
|
XBoxZone &dest[],
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(dest);
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = bar.IsValid() &&
|
|
HasChild(source);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = IsRejected(
|
|
bar,
|
|
source[i] //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
source[i],
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Collect all Bars which Breakes Specified Zone ...
|
|
*
|
|
* @param zone: reference to Specified Zone ...
|
|
* @param dest: reference Collection to hold result ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetBreakerBars(
|
|
XBoxZone &zone,
|
|
XOHCL &dest[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = zone.IsValid();
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(dest);
|
|
|
|
//
|
|
// Do Action ...
|
|
XOHCL iBar;
|
|
int start = zone.ToIndex();
|
|
int end = zone.FromIndex();
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
//
|
|
// Initialize indexed Bar ...
|
|
has = iBar.Init(
|
|
zone.symbol,
|
|
zone.period,
|
|
i //
|
|
);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
has = IsBreaked(
|
|
iBar,
|
|
zone,
|
|
false // Breakes by Close ...
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
dest //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Collect all Bars which Inside Specified Zone ...
|
|
*
|
|
* @param zone: reference to Specified Zone ...
|
|
* @param dest: reference Collection to hold result ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetInsideBars(
|
|
XBoxZone &zone,
|
|
XOHCL &dest[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = zone.IsValid();
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(dest);
|
|
|
|
//
|
|
// Do Action ...
|
|
XOHCL iBar;
|
|
int start = zone.ToIndex();
|
|
int end = zone.FromIndex();
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
//
|
|
// Initialize indexed Bar ...
|
|
has = iBar.Init(
|
|
zone.symbol,
|
|
zone.period,
|
|
i //
|
|
);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
has = IsInside(
|
|
iBar,
|
|
zone //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
dest //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Collect all Bars which Tested Specified Zone ...
|
|
*
|
|
* @param zone: reference to Specified Zone ...
|
|
* @param dest: reference Collection to hold result ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetTesterBars(
|
|
XBoxZone &zone,
|
|
XOHCL &dest[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = zone.IsValid();
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(dest);
|
|
|
|
//
|
|
// Do Action ...
|
|
XOHCL iBar;
|
|
int start = zone.ToIndex();
|
|
int end = zone.FromIndex();
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
//
|
|
// Initialize indexed Bar ...
|
|
has = iBar.Init(
|
|
zone.symbol,
|
|
zone.period,
|
|
i //
|
|
);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
has = IsTested(
|
|
iBar,
|
|
zone //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
dest //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Validate Zones Range ...
|
|
*
|
|
* @param source: XBoxZone, collection reference to Validate ...
|
|
* @param minAllowedRange: double, min allowed range to Validate ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ValidateZonesRange(
|
|
XBoxZone &source[],
|
|
double minAllowedRange //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = HasChild(source) &&
|
|
minAllowedRange > 0;
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone iTMP;
|
|
XBoxZone tmps[];
|
|
Copy(source, tmps);
|
|
XClean(source);
|
|
while (HasChild(tmps))
|
|
{
|
|
//
|
|
iTMP.Clean();
|
|
iTMP = tmps[0];
|
|
ArrayRemove(tmps, 0, 1);
|
|
|
|
//
|
|
// Check Range Validation ...
|
|
has = iTMP.GetRange() > minAllowedRange;
|
|
if (has)
|
|
{
|
|
AddIfNotExists(iTMP, source);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(source);
|
|
|
|
//
|
|
// Cleanup ...
|
|
XClean(tmps);
|
|
iTMP.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Remove Breaked Zones ...
|
|
*
|
|
* @param source: XBoxZone, collection reference to Remove Breaked Zones ...
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type of Break Detection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int RemoveBreakedZones(
|
|
XBoxZone &source[],
|
|
ENUM_X_PRICE priceType = X_PRICE_CLOSE //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Validate ...
|
|
if (!HasChild(source) || !IsXValid(priceType))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone tmp[];
|
|
Copy(source, tmp);
|
|
XClean(source);
|
|
XBoxZone iTMP;
|
|
bool isBreaked = false;
|
|
while (HasChild(tmp))
|
|
{
|
|
//
|
|
iTMP.Clean();
|
|
iTMP = tmp[0];
|
|
ArrayRemove(tmp, 0, 1);
|
|
|
|
//
|
|
isBreaked = IsBreaked(iTMP, priceType);
|
|
if (!isBreaked)
|
|
{
|
|
//
|
|
AddIfNotExists(iTMP, source);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(source);
|
|
|
|
//
|
|
// Cleanup ...
|
|
XClean(tmp);
|
|
iTMP.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
// #endregion
|
|
//+------------------------------------------------------------------+
|
|
|
|
// #region Bar Extensions ...
|
|
/**
|
|
* Check Specified Bar is Breaked or not ...
|
|
*
|
|
* @param bar: XOHCL, Specified Bar for Checking Proce ...
|
|
* @param breakerBar: XOHCL, Hold's Breaker Bar if Exists ...
|
|
* @param barIndex: int, Start Checking Bar till Bar's Index ...
|
|
* @param breakDir: ENUM_X_DIRECTION, Checking Direction Type, if Bullish Break Price must bigger, otherwise must lower ...
|
|
* @param barPriceType: ENUM_X_PRICE, Price type to Check Break ...
|
|
* @param breakPriceType: ENUM_X_PRICE, Price Type to Break Bar's Price ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBarBreaked(
|
|
XOHCL &bar,
|
|
XOHCL &breakerBar,
|
|
int barIndex = 0,
|
|
ENUM_X_DIRECTION breakDir = X_DIRECTION_NONE,
|
|
ENUM_X_PRICE barPriceType = X_PRICE_CLOSE,
|
|
ENUM_X_PRICE breakPriceType = X_PRICE_CLOSE //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
breakerBar.Clean();
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result =
|
|
bar.IsValid() &&
|
|
HasDirection(breakDir) &&
|
|
IsXValid(barPriceType) &&
|
|
IsXValid(breakPriceType) &&
|
|
barIndex < bar.Index();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop for Validating ...
|
|
XOHCL tmpBar;
|
|
bool has = false;
|
|
double tmpPrice = EMPTY_VALUE;
|
|
double barPrice = bar.GetPrice(barPriceType);
|
|
for (int i = barIndex; i < bar.Index(); i++)
|
|
{
|
|
//
|
|
has = tmpBar.Init(bar.symbol, bar.period, i);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
tmpPrice = tmpBar.GetPrice(breakPriceType);
|
|
has = NotEmptyZero(tmpPrice);
|
|
if (!has)
|
|
{
|
|
//
|
|
tmpBar.Clean();
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
has =
|
|
IsXBullish(breakDir)
|
|
? tmpPrice > barPrice
|
|
: tmpPrice < barPrice;
|
|
if (has)
|
|
{
|
|
//
|
|
breakerBar = tmpBar;
|
|
tmpBar.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
tmpBar.Clean();
|
|
}
|
|
|
|
//
|
|
result = breakerBar.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
// #endregion
|
|
|
|
// |