4465 lines
86 KiB
Plaintext
4465 lines
86 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Seriallize Library
|
|
// ---------------------------------------
|
|
// Name: XPOILib
|
|
// Description: All models related to POIs ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright `023, SaherElm IT Center"
|
|
#property link "https://www.saherelm.ir"
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
#include "../Libraries/x-saherelm.x-poi.lib.mq5"
|
|
|
|
//
|
|
// Extensions ...
|
|
|
|
/**
|
|
* Combine a Collection of States into dest ...
|
|
*
|
|
* @param dest: XPOIState instance ...
|
|
* @param source: XPOIState Collection ...
|
|
*/
|
|
void CombineStates(
|
|
XPOIState &dest,
|
|
XPOIState &source[] //
|
|
)
|
|
{
|
|
//
|
|
dest.Clean();
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XPOIState iState = source[i];
|
|
|
|
//
|
|
if (dest.ticksZone == NULL)
|
|
{
|
|
dest.ticksZone = iState.ticksZone;
|
|
}
|
|
|
|
//
|
|
Copy(
|
|
iState.swingHighs,
|
|
dest.swingHighs,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
iState.swingLows,
|
|
dest.swingLows,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
iState.bullishMomentumBars,
|
|
dest.bullishMomentumBars,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
iState.bearishMomentumBars,
|
|
dest.bearishMomentumBars,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
iState.bullishRejectionBars,
|
|
dest.bullishRejectionBars,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
iState.bearishRejectionBars,
|
|
dest.bearishRejectionBars,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
iState.supportZones,
|
|
dest.supportZones,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
iState.resistanceZones,
|
|
dest.resistanceZones,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
iState.supplyZones,
|
|
dest.supplyZones,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
iState.demandZones,
|
|
dest.demandZones,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
iState.bullishOrderBlocks,
|
|
dest.bullishOrderBlocks,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
iState.bearishOrderBlocks,
|
|
dest.bearishOrderBlocks,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
iState.bullishFairValueGaps,
|
|
dest.bullishFairValueGaps,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
iState.bearishFairValueGaps,
|
|
dest.bearishFairValueGaps,
|
|
false //
|
|
);
|
|
|
|
//
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
bool ToZone(
|
|
T *&source[],
|
|
XCZone *&dest[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(dest);
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
result = IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
T *item = source[i];
|
|
|
|
//
|
|
if (item != NULL)
|
|
{
|
|
//
|
|
Add(
|
|
(XCZone *)item,
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
int destCount = ArraySize(dest);
|
|
result = IsValidSize(destCount);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool ToBox(
|
|
T *&source[],
|
|
XBoxZone &dest[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(dest);
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
result = IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
T *item = source[i];
|
|
|
|
//
|
|
if (item != NULL)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
bool hasBox = ToBox(
|
|
iBox,
|
|
item //
|
|
);
|
|
|
|
//
|
|
if (hasBox)
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
int destCount = ArraySize(dest);
|
|
result = IsValidSize(destCount);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetOldest(
|
|
T *&sourec[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetOldest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetYoungest(
|
|
T *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetYoungest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetLowest(
|
|
T *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetLowest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetHighest(
|
|
T *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetHighest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsSame(
|
|
T *source,
|
|
T *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = sourceBox.IsSame(destBox);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename F>
|
|
bool IsSameDiff(
|
|
T *source,
|
|
F *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = sourceBox.IsSame(destBox);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsBelow(
|
|
T *source,
|
|
T *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxBelow(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename F>
|
|
bool IsBelowDiff(
|
|
T *source,
|
|
F *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxBelow(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsAbove(
|
|
T *source,
|
|
T *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxAbove(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename F>
|
|
bool IsAboveDiff(
|
|
T *source,
|
|
F *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxAbove(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsInside(
|
|
T *source,
|
|
T *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxInside(
|
|
sourceBox,
|
|
destBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename F>
|
|
bool IsInsideDiff(
|
|
T *source,
|
|
F *dest,
|
|
bool forceSideOut = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxInside(
|
|
sourceBox,
|
|
destBox,
|
|
forceSideOut //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool FindIndex(
|
|
int &index,
|
|
T *item,
|
|
T *&items[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
XBoxZone itemBox;
|
|
result = ToBox(
|
|
itemBox,
|
|
item //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone itemsBox[];
|
|
result = ToBox(
|
|
items,
|
|
itemsBox //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = FindBoxIndex(
|
|
index,
|
|
itemBox,
|
|
itemsBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsInside(
|
|
double value,
|
|
T *source //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsInsideBox(
|
|
value,
|
|
sourceBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsAbove(
|
|
double value,
|
|
T *source //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsAboveBox(
|
|
value,
|
|
sourceBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsBelow(
|
|
double value,
|
|
T *source //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBelowBox(
|
|
value,
|
|
sourceBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Find Specified Box Index inside a Collection of Boxes ...
|
|
*
|
|
* @param box: XBoxZone instance Reference ...
|
|
* @param boxes: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
bool FindBoxIndex(
|
|
int &index,
|
|
XBoxZone &box,
|
|
XBoxZone &boxes[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
int count = ArraySize(boxes);
|
|
result = box.IsValid() &&
|
|
IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = boxes[i];
|
|
|
|
//
|
|
bool isSame = box.IsSame(iBox);
|
|
if (isSame)
|
|
{
|
|
//
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Source Box is Below Dest ...
|
|
*
|
|
* @param source: XBoxZone instance Reference ...
|
|
* @param dest: XBoxZone instance Reference ...
|
|
* @param ignoreInside: bool ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxBelow(
|
|
XBoxZone &source,
|
|
XBoxZone &dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSame(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!ignoreInside)
|
|
{
|
|
result = source.upper < dest.lower;
|
|
}
|
|
else
|
|
{
|
|
result = (source.upper < dest.lower ||
|
|
source.upper >= dest.upper) &&
|
|
source.lower < dest.lower;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Source Box is Above Dest ...
|
|
*
|
|
* @param source: XBoxZone instance Reference ...
|
|
* @param dest: XBoxZone instance Reference ...
|
|
* @param ignoreInside: bool ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxAbove(
|
|
XBoxZone &source,
|
|
XBoxZone &dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSame(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!ignoreInside)
|
|
{
|
|
result = source.lower > dest.upper;
|
|
}
|
|
else
|
|
{
|
|
result = (source.lower > dest.upper ||
|
|
source.lower <= dest.upper) &&
|
|
source.upper > dest.upper;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Source Box is Inside Dest ...
|
|
*
|
|
* @param source: XBoxZone instance Reference ...
|
|
* @param dest: XBoxZone instance Reference ...
|
|
* @param forceSideOut: bool, force check Box has One Side Out ...
|
|
* @param ignoreSideOut: bool, Accept if source Box one Side is out of Dest Box ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxInside(
|
|
XBoxZone &source,
|
|
XBoxZone &dest,
|
|
bool forceSideOut = false, //
|
|
bool ignoreSideOut = true //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSame(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(dest.dir);
|
|
|
|
//
|
|
if (!forceSideOut)
|
|
{
|
|
//
|
|
if (ignoreSideOut)
|
|
{
|
|
//
|
|
result = source.lower >= dest.lower &&
|
|
source.upper <= dest.upper;
|
|
}
|
|
else
|
|
{
|
|
result = source.lower >= dest.lower ||
|
|
source.upper <= dest.upper;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
bool hasSideIn =
|
|
isBullish
|
|
? source.lower >= dest.lower
|
|
: source.upper <= dest.upper;
|
|
bool hasSideOut =
|
|
isBullish
|
|
? source.upper >= dest.upper
|
|
: source.lower <= dest.lower;
|
|
result =
|
|
hasSideIn &&
|
|
hasSideOut;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Value is Inside Specified Box ...
|
|
*
|
|
* @param value: double ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsInsideBox(
|
|
double value,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value > 0 &&
|
|
box.IsValid() &&
|
|
value <= box.upper &&
|
|
value >= box.lower;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Value is Above Specified Box ...
|
|
*
|
|
* @param value: double ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsAboveBox(
|
|
double value,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value > 0 &&
|
|
box.IsValid() &&
|
|
value > box.upper;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Value is Below Specified Box ...
|
|
*
|
|
* @param value: double ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBelowBox(
|
|
double value,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value > 0 &&
|
|
box.IsValid() &&
|
|
value < box.lower;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Box is Used or not ...
|
|
*
|
|
* @param box: XBoxZone instance Reference ...
|
|
* @param fromIndex: int ...
|
|
* @param toIndex: int
|
|
* @param forPeriod: Specified Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxUsed(
|
|
XBoxZone &box,
|
|
int fromIndex,
|
|
int toIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (toIndex < 0)
|
|
{
|
|
toIndex = 0;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
box.IsValid() &&
|
|
fromIndex > 0 &&
|
|
fromIndex > toIndex
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = box.period;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION forDir = box.dir;
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
for (int i = fromIndex; i >= toIndex; i--)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
box.symbol,
|
|
forPeriod,
|
|
i //
|
|
);
|
|
|
|
//
|
|
bool isTouched =
|
|
isBullish
|
|
? iBar.high > box.lower
|
|
: iBar.low < box.upper;
|
|
if (!isTouched)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
result = false;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts a Consolidation Zone ...
|
|
*
|
|
* @param zone: XConsolidationZone instance Reference ...
|
|
* @param dest: XCZone pointer Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToZone(
|
|
XConsolidationZone &zone,
|
|
XCZone *&dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dest = NULL;
|
|
|
|
//
|
|
result = zone.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
dest = new XCZone();
|
|
dest.Upper(zone.upper);
|
|
dest.Lower(zone.lower);
|
|
result = dest.IsValidBoundary();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCOrderBlock *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = item.IsBullish()
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCFVG *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = item.IsBullish()
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCSupportZone *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCResistanceZone *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCSupplyZone *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCDemandZone *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XConsolidationZone &item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.upper = item.upper;
|
|
box.lower = item.lower;
|
|
box.dir = item.breakDir;
|
|
box.from = item.initTime;
|
|
box.symbol = item.symbol;
|
|
box.period = item.period;
|
|
box.to = item.breakerBar.time;
|
|
box.type = "X_CONSOLIDATION_ZONE";
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Oldest Zone ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldest(
|
|
XCZone *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XCZone *oldest = NULL;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCZone *iZone = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
oldest == NULL ||
|
|
(oldest != NULL &&
|
|
oldest.From() > iZone.From());
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
oldest = iZone;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Zone ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungest(
|
|
XCZone *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XCZone *youngest = NULL;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCZone *iZone = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
youngest == NULL ||
|
|
(youngest != NULL &&
|
|
youngest.From() < iZone.From());
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
youngest = iZone;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Oldest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from > iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from < iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Highest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.upper < iBox.upper;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Lowest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.lower > iBox.lower;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
template <typename T>
|
|
void SortZones(
|
|
T *&source[],
|
|
ENUM_X_DIRECTION forDir,
|
|
bool ignoreInside = true //
|
|
)
|
|
{
|
|
//
|
|
int idx = -1;
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
has = HasDirection(forDir);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
count = ArraySize(source);
|
|
has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
T *tmpItems[];
|
|
T *last = NULL;
|
|
bool hasLast = false;
|
|
while (HasChild(source))
|
|
{
|
|
//
|
|
if (!hasLast)
|
|
{
|
|
//
|
|
idx = GetYoungest(source);
|
|
hasLast = IsValidIndex(idx);
|
|
if (hasLast)
|
|
{
|
|
//
|
|
last = source[idx];
|
|
ArrayRemove(
|
|
source,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
last,
|
|
source //
|
|
);
|
|
}
|
|
|
|
//
|
|
count = ArraySize(source);
|
|
has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
//
|
|
ZeroMemory(last);
|
|
break;
|
|
}
|
|
}
|
|
if (!hasLast)
|
|
{
|
|
//
|
|
ZeroMemory(last);
|
|
break;
|
|
}
|
|
|
|
//
|
|
T *item = NULL;
|
|
idx = GetYoungest(source);
|
|
has = IsValidIndex(idx);
|
|
if (!has)
|
|
{
|
|
//
|
|
ZeroMemory(last);
|
|
ZeroMemory(item);
|
|
break;
|
|
}
|
|
item = source[idx];
|
|
ArrayRemove(
|
|
source,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
bool isAbove = IsAbove(
|
|
item,
|
|
last,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
bool isBelow = IsBelow(
|
|
item,
|
|
last,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
has =
|
|
isBullish
|
|
? isAbove
|
|
: isBelow;
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
item,
|
|
tmpItems //
|
|
);
|
|
|
|
//
|
|
last = item;
|
|
hasLast = item != NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(source);
|
|
Copy(
|
|
tmpItems,
|
|
source //
|
|
);
|
|
|
|
//
|
|
Clean(tmpItems);
|
|
}
|
|
|
|
//
|
|
template <typename T>
|
|
int FilterZones(
|
|
//
|
|
T *&source[],
|
|
//
|
|
ENUM_X_DIRECTION forDir,
|
|
ENUM_TIMEFRAMES forPeriod = NULL,
|
|
datetime after = NULL,
|
|
//
|
|
// Start ...
|
|
ENUM_XZONE_STATE startState = XZONE_STATE_PASSED,
|
|
bool forceStartedBodyOut = false,
|
|
//
|
|
// Activation ...
|
|
ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED,
|
|
bool forceActivatedBodyIn = false,
|
|
//
|
|
// Breaktion ...
|
|
ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED,
|
|
bool forceBreakedBodyOut = false,
|
|
//
|
|
// Works ...
|
|
ENUM_XZONE_STATE workState = XZONE_STATE_FAILED,
|
|
bool forceWorkedBodyOut = false,
|
|
//
|
|
bool applySort = false,
|
|
//
|
|
bool ignoreInside = true
|
|
//
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
int idx = -1;
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
has = HasDirection(forDir);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
count = ArraySize(source);
|
|
has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
T *tmpZones[];
|
|
XOHCL passedBar;
|
|
bool isPassed = false;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
T *iZone = source[i];
|
|
|
|
//
|
|
// Apply after Filter ...
|
|
isPassed =
|
|
!IsValid(after)
|
|
? true
|
|
: iZone.From() >= after;
|
|
if (!isPassed)
|
|
{
|
|
//
|
|
ZeroMemory(iZone);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Started State ...
|
|
if (startState == XZONE_STATE_PASSED ||
|
|
startState == XZONE_STATE_FAILED)
|
|
{
|
|
//
|
|
bool isBodyOut = false;
|
|
bool isStarted = iZone.IsStarted(
|
|
forDir,
|
|
passedBar,
|
|
isBodyOut,
|
|
forPeriod //
|
|
);
|
|
|
|
//
|
|
bool isPassed =
|
|
startState == XZONE_STATE_FAILED
|
|
? !isStarted
|
|
: !forceStartedBodyOut
|
|
? isStarted
|
|
: isStarted &&
|
|
isBodyOut;
|
|
|
|
//
|
|
passedBar.Clean();
|
|
if (!isPassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Activation State ...
|
|
if (activeState == XZONE_STATE_PASSED ||
|
|
activeState == XZONE_STATE_FAILED)
|
|
{
|
|
//
|
|
bool isBodyIn = false;
|
|
bool isActivated = iZone.IsActivated(
|
|
forDir,
|
|
passedBar,
|
|
isBodyIn,
|
|
forceStartedBodyOut,
|
|
forPeriod //
|
|
);
|
|
|
|
//
|
|
bool isPassed =
|
|
activeState == XZONE_STATE_FAILED
|
|
? !isActivated
|
|
: !forceActivatedBodyIn
|
|
? isActivated
|
|
: isActivated &&
|
|
isBodyIn;
|
|
|
|
//
|
|
passedBar.Clean();
|
|
if (!isPassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Break State ...
|
|
if (breakState == XZONE_STATE_PASSED ||
|
|
breakState == XZONE_STATE_FAILED)
|
|
{
|
|
//
|
|
bool isBodyOut = false;
|
|
bool isBreaked = iZone.IsBreaked(
|
|
forDir,
|
|
passedBar,
|
|
isBodyOut,
|
|
forceStartedBodyOut,
|
|
forPeriod //
|
|
);
|
|
|
|
//
|
|
bool isPassed =
|
|
breakState == XZONE_STATE_FAILED
|
|
? !isBreaked
|
|
: !forceBreakedBodyOut
|
|
? isBreaked
|
|
: isBreaked &&
|
|
isBodyOut;
|
|
|
|
//
|
|
passedBar.Clean();
|
|
if (!isPassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Work State ...
|
|
if (workState == XZONE_STATE_PASSED ||
|
|
workState == XZONE_STATE_FAILED)
|
|
{
|
|
//
|
|
bool ignoreActivation = activeState != XZONE_STATE_PASSED;
|
|
|
|
//
|
|
bool isBodyOut = false;
|
|
bool isWorked = iZone.IsWorked(
|
|
forDir,
|
|
passedBar,
|
|
isBodyOut,
|
|
ignoreActivation,
|
|
forceStartedBodyOut,
|
|
forceActivatedBodyIn,
|
|
forPeriod //
|
|
);
|
|
|
|
//
|
|
bool isPassed =
|
|
workState == XZONE_STATE_FAILED
|
|
? !isWorked
|
|
: !forceWorkedBodyOut
|
|
? isWorked
|
|
: isWorked &&
|
|
isBodyOut;
|
|
|
|
//
|
|
passedBar.Clean();
|
|
if (!isPassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Filtered Zone Doesn't Exists ...
|
|
has = FindIndex(
|
|
idx,
|
|
iZone,
|
|
tmpZones //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
ZeroMemory(iZone);
|
|
passedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
iZone,
|
|
tmpZones //
|
|
);
|
|
}
|
|
|
|
//
|
|
Clean(source);
|
|
|
|
//
|
|
has = HasChild(tmpZones);
|
|
if (!has)
|
|
{
|
|
//
|
|
Clean(tmpZones);
|
|
passedBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Apply Sorting ...
|
|
if (applySort)
|
|
{
|
|
//
|
|
T *last = NULL;
|
|
bool hasLast = false;
|
|
while (HasChild(tmpZones))
|
|
{
|
|
//
|
|
idx = GetYoungest(tmpZones);
|
|
hasLast = IsValidIndex(idx);
|
|
if (hasLast)
|
|
{
|
|
//
|
|
last = tmpZones[idx];
|
|
ArrayRemove(
|
|
tmpZones,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
last,
|
|
source //
|
|
);
|
|
}
|
|
|
|
//
|
|
has = HasChild(tmpZones);
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
T *zone = NULL;
|
|
bool hasZone = false;
|
|
idx = GetYoungest(tmpZones);
|
|
hasZone = IsValidIndex(idx);
|
|
if (hasZone)
|
|
{
|
|
//
|
|
zone = tmpZones[idx];
|
|
ArrayRemove(
|
|
tmpZones,
|
|
idx,
|
|
1 //
|
|
);
|
|
}
|
|
if (!hasZone)
|
|
{
|
|
//
|
|
ZeroMemory(zone);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isAbove = IsAbove(
|
|
zone,
|
|
last,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
bool isBelow = IsBelow(
|
|
zone,
|
|
last,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
isPassed =
|
|
isBullish
|
|
? isAbove
|
|
: isBelow;
|
|
if (!isPassed)
|
|
{
|
|
//
|
|
ZeroMemory(zone);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
zone,
|
|
source //
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Copy(
|
|
tmpZones,
|
|
source //
|
|
);
|
|
}
|
|
|
|
//
|
|
result = ArraySize(source);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
/**
|
|
* Extract XOBFVG Collection of Market ...
|
|
*
|
|
* @param htfState: Higher Time Frame POI State (Used For Detecting Order Blocks) ...
|
|
* @param mtfState: Medium Time Frame POI State (Used For Detecting Fair Value Gaps) ...
|
|
* @param stfState: Short Time Frame POI State (Used For Detecting Other POI(s)) ...
|
|
* @param dest: Result Collection ...
|
|
* @param forDir: Market Direction for Detecting POI(s) ...
|
|
* @param forPeriod: Time Frame which Used for Zones actions (NULL for Default) ...
|
|
* @param startState: Zones Start State ...
|
|
* @param forceStartedBodyOut: Zones Started Bar's Body State ...
|
|
* @param activeState: Zones Activation State ...
|
|
* @param forceActivatedBodyIn: Zones Activated Bar's Body State ...
|
|
* @param breakState: Zones Breaked State ...
|
|
* @param forceBreakedBodyOut: Zone Breaker Bar's Body State ...
|
|
* @param workState: Zones Worked State ...
|
|
* @param forceWorkedBodyOut: Zones Worked Bar's Body State ...
|
|
* @param applySort: Specify Applying Sorting on Collections ...
|
|
* @param applyFromFilter: Filter Sorted Zones based on Occured Date ...
|
|
* @param applyPlaceFilter: Filter Sorted Zones based on Occured Place ...
|
|
* @param ignoreInside: Ignore Inside Sides of POI(s) Zones in Related to Order Block ...
|
|
* @param applyFromFilterForPOIs: Apply From Filter for Other POI(s) ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractOBFVGZones(
|
|
XPOIState &htfState,
|
|
XPOIState &mtfState,
|
|
XPOIState &stfState,
|
|
XOBFVG &dest[],
|
|
//
|
|
ENUM_X_DIRECTION forDir,
|
|
ENUM_TIMEFRAMES forPeriod = NULL,
|
|
//
|
|
// Start ...
|
|
ENUM_XZONE_STATE startState = XZONE_STATE_PASSED,
|
|
bool forceStartedBodyOut = false,
|
|
//
|
|
// Activation ...
|
|
ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED,
|
|
bool forceActivatedBodyIn = false,
|
|
//
|
|
// Breaktion ...
|
|
ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED,
|
|
bool forceBreakedBodyOut = false,
|
|
//
|
|
// Works ...
|
|
ENUM_XZONE_STATE workState = XZONE_STATE_FAILED,
|
|
bool forceWorkedBodyOut = false,
|
|
//
|
|
bool applySort = true,
|
|
bool applyFromFilter = true,
|
|
bool applyPlaceFilter = true,
|
|
//
|
|
bool ignoreInside = true,
|
|
//
|
|
bool detectInsideOBPOIs = true,
|
|
bool detectInsideFVGPOIs = true,
|
|
bool applyFromFilterForPOIs = true
|
|
//
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(dest);
|
|
|
|
//
|
|
bool isValid =
|
|
//
|
|
htfState.HasChild() &&
|
|
mtfState.HasChild() &&
|
|
stfState.HasChild() &&
|
|
HasDirection(forDir)
|
|
//
|
|
;
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Implement Logic ...
|
|
|
|
//
|
|
int idx = -1;
|
|
int count = 0;
|
|
bool has = false;
|
|
XCFVG *tmpFVGs[];
|
|
XOBFVG tmpOBFVGs[];
|
|
XCOrderBlock *tmpOBs[];
|
|
XCOrderBlock *tmpWorkingOBs[];
|
|
datetime cTime = TimeCurrent();
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
has = htfState.HasBullishOrderBlocks();
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
htfState.bullishOrderBlocks,
|
|
tmpOBs //
|
|
);
|
|
|
|
//
|
|
has = mtfState.HasBullishFairValueGaps();
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
mtfState.bullishFairValueGaps,
|
|
tmpFVGs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
has = htfState.HasBearishOrderBlocks();
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
htfState.bearishOrderBlocks,
|
|
tmpOBs //
|
|
);
|
|
|
|
//
|
|
has = mtfState.HasBearishFairValueGaps();
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
mtfState.bearishFairValueGaps,
|
|
tmpFVGs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
count = ArraySize(tmpOBs);
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iOB = tmpOBs[i];
|
|
|
|
//
|
|
// Check Started State ...
|
|
if (startState == XZONE_STATE_PASSED ||
|
|
startState == XZONE_STATE_FAILED)
|
|
{
|
|
//
|
|
XOHCL passedBar;
|
|
bool isBodyOut = false;
|
|
bool isStarted = iOB.IsStarted(
|
|
forDir,
|
|
passedBar,
|
|
isBodyOut,
|
|
forPeriod //
|
|
);
|
|
|
|
//
|
|
bool isPassed =
|
|
startState == XZONE_STATE_FAILED
|
|
? !isStarted
|
|
: !forceStartedBodyOut
|
|
? isStarted
|
|
: isStarted &&
|
|
isBodyOut;
|
|
|
|
//
|
|
passedBar.Clean();
|
|
if (!isPassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Activation State ...
|
|
if (activeState == XZONE_STATE_PASSED ||
|
|
activeState == XZONE_STATE_FAILED)
|
|
{
|
|
//
|
|
XOHCL passedBar;
|
|
bool isBodyIn = false;
|
|
bool isActivated = iOB.IsActivated(
|
|
forDir,
|
|
passedBar,
|
|
isBodyIn,
|
|
forceStartedBodyOut,
|
|
forPeriod //
|
|
);
|
|
|
|
//
|
|
bool isPassed =
|
|
activeState == XZONE_STATE_FAILED
|
|
? !isActivated
|
|
: !forceActivatedBodyIn
|
|
? isActivated
|
|
: isActivated &&
|
|
isBodyIn;
|
|
|
|
//
|
|
passedBar.Clean();
|
|
if (!isPassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Break State ...
|
|
if (breakState == XZONE_STATE_PASSED ||
|
|
breakState == XZONE_STATE_FAILED)
|
|
{
|
|
//
|
|
XOHCL passedBar;
|
|
bool isBodyOut = false;
|
|
bool isBreaked = iOB.IsBreaked(
|
|
forDir,
|
|
passedBar,
|
|
isBodyOut,
|
|
forceStartedBodyOut,
|
|
forPeriod //
|
|
);
|
|
|
|
//
|
|
bool isPassed =
|
|
breakState == XZONE_STATE_FAILED
|
|
? !isBreaked
|
|
: !forceBreakedBodyOut
|
|
? isBreaked
|
|
: isBreaked &&
|
|
isBodyOut;
|
|
|
|
//
|
|
passedBar.Clean();
|
|
if (!isPassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Work State ...
|
|
if (workState == XZONE_STATE_PASSED ||
|
|
workState == XZONE_STATE_FAILED)
|
|
{
|
|
//
|
|
bool ignoreActivation = activeState != XZONE_STATE_PASSED;
|
|
|
|
//
|
|
XOHCL passedBar;
|
|
bool isBodyOut = false;
|
|
bool isWorked = iOB.IsWorked(
|
|
forDir,
|
|
passedBar,
|
|
isBodyOut,
|
|
ignoreActivation,
|
|
forceStartedBodyOut,
|
|
forceActivatedBodyIn,
|
|
forPeriod //
|
|
);
|
|
|
|
//
|
|
bool isPassed =
|
|
workState == XZONE_STATE_FAILED
|
|
? !isWorked
|
|
: !forceWorkedBodyOut
|
|
? isWorked
|
|
: isWorked &&
|
|
isBodyOut;
|
|
|
|
//
|
|
passedBar.Clean();
|
|
if (!isPassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
has = FindIndex(
|
|
idx,
|
|
iOB,
|
|
tmpWorkingOBs //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
ZeroMemory(iOB);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
iOB,
|
|
tmpWorkingOBs //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Clean ...
|
|
Clean(tmpOBs);
|
|
has = HasChild(tmpWorkingOBs);
|
|
if (has)
|
|
{
|
|
//
|
|
Clean(tmpOBs);
|
|
Copy(
|
|
tmpWorkingOBs,
|
|
tmpOBs //
|
|
);
|
|
|
|
//
|
|
Clean(tmpWorkingOBs);
|
|
}
|
|
|
|
//
|
|
// Sorting ...
|
|
if (applySort)
|
|
{
|
|
//
|
|
Clean(tmpWorkingOBs);
|
|
has = HasChild(tmpOBs);
|
|
count = ArraySize(tmpOBs);
|
|
|
|
//
|
|
// Sorting Applied Only when there is more than one item ...
|
|
if (has && count > 1)
|
|
{
|
|
//
|
|
bool hasLast = false;
|
|
XCOrderBlock *last = NULL;
|
|
while (HasChild(tmpOBs))
|
|
{
|
|
//
|
|
// Extract First Last Item ...
|
|
if (!hasLast)
|
|
{
|
|
//
|
|
idx =
|
|
isBullish
|
|
? GetLowest(tmpOBs)
|
|
: GetHighest(tmpOBs);
|
|
hasLast = IsValidIndex(idx);
|
|
if (hasLast)
|
|
{
|
|
//
|
|
last = tmpOBs[idx];
|
|
ArrayRemove(
|
|
tmpOBs,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
last,
|
|
tmpWorkingOBs //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
has = false;
|
|
XCOrderBlock *iOB = NULL;
|
|
idx =
|
|
isBullish
|
|
? GetLowest(tmpOBs)
|
|
: GetHighest(tmpOBs);
|
|
has = IsValidIndex(idx);
|
|
if (has)
|
|
{
|
|
//
|
|
iOB = tmpOBs[idx];
|
|
ArrayRemove(
|
|
tmpOBs,
|
|
idx,
|
|
1 //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Apply From Filter ...
|
|
if (applyFromFilter)
|
|
{
|
|
//
|
|
bool isFromPassed =
|
|
hasLast &&
|
|
last.From() < iOB.From();
|
|
if (!isFromPassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Apply Place Filter ...
|
|
if (applyPlaceFilter)
|
|
{
|
|
//
|
|
bool isAbove =
|
|
hasLast &&
|
|
IsAbove(
|
|
iOB,
|
|
last,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
bool isBelow =
|
|
hasLast &&
|
|
IsBelow(
|
|
iOB,
|
|
last,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
bool isPlacePassed =
|
|
isBullish
|
|
? isAbove
|
|
: isBelow;
|
|
if (!isPlacePassed)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
last = iOB;
|
|
Add(
|
|
iOB,
|
|
tmpWorkingOBs //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (hasLast &&
|
|
!HasChild(tmpWorkingOBs))
|
|
{
|
|
//
|
|
Add(
|
|
last,
|
|
tmpWorkingOBs //
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Copy(
|
|
tmpOBs,
|
|
tmpWorkingOBs //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (HasChild(tmpWorkingOBs))
|
|
{
|
|
//
|
|
Copy(
|
|
tmpWorkingOBs,
|
|
tmpOBs //
|
|
);
|
|
}
|
|
//
|
|
}
|
|
|
|
//
|
|
count = ArraySize(tmpOBs);
|
|
has = IsValidSize(count);
|
|
|
|
//
|
|
// Converts to XOBFVG ...
|
|
if (has)
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XOBFVG iOBFVG;
|
|
|
|
//
|
|
iOBFVG.ob = tmpOBs[i];
|
|
|
|
//
|
|
AddRef(
|
|
iOBFVG,
|
|
tmpOBFVGs //
|
|
);
|
|
|
|
//
|
|
iOBFVG.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(dest);
|
|
Clean(tmpOBs);
|
|
Clean(tmpWorkingOBs);
|
|
|
|
//
|
|
// Here we Going to Complete XOBFVGs ...
|
|
has = HasChild(tmpOBFVGs);
|
|
if (has && HasChild(tmpFVGs))
|
|
{
|
|
//
|
|
count = ArraySize(tmpOBFVGs);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XOBFVG iOBFVG = tmpOBFVGs[i];
|
|
|
|
//
|
|
// Detecting FVG ...
|
|
XCFVG *tmpWorkingFVGs[];
|
|
for (int j = 0; j < ArraySize(tmpFVGs); j++)
|
|
{
|
|
//
|
|
XCFVG *jFVG = tmpFVGs[j];
|
|
|
|
//
|
|
// Check Start Date ...
|
|
bool isFromPassed = jFVG.From() > iOBFVG.ob.From();
|
|
if (!isFromPassed)
|
|
{
|
|
//
|
|
ZeroMemory(jFVG);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Place ...
|
|
|
|
//
|
|
bool isAbove = IsAboveDiff(
|
|
jFVG,
|
|
iOBFVG.ob,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
bool isBelow = IsBelowDiff(
|
|
jFVG,
|
|
iOBFVG.ob,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
bool isInside = IsInsideDiff(
|
|
jFVG,
|
|
iOBFVG.ob,
|
|
false //
|
|
);
|
|
|
|
//
|
|
bool isPlacePassed =
|
|
isInside ||
|
|
(isBullish
|
|
? isAbove
|
|
: isBelow);
|
|
if (!isPlacePassed)
|
|
{
|
|
//
|
|
ZeroMemory(jFVG);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
jFVG,
|
|
tmpWorkingFVGs //
|
|
);
|
|
}
|
|
|
|
//
|
|
int fvgsCount = ArraySize(tmpWorkingFVGs);
|
|
has = IsValidSize(fvgsCount);
|
|
if (has)
|
|
{
|
|
//
|
|
idx =
|
|
isBullish
|
|
? GetLowest(tmpWorkingFVGs)
|
|
: GetHighest(tmpWorkingFVGs);
|
|
|
|
//
|
|
if (IsValidIndex(idx))
|
|
{
|
|
//
|
|
XCFVG *selectedFVG = tmpWorkingFVGs[idx];
|
|
|
|
//
|
|
iOBFVG.fvg = selectedFVG;
|
|
|
|
//
|
|
bool isExists = FindIndex(
|
|
idx,
|
|
selectedFVG,
|
|
tmpFVGs //
|
|
);
|
|
if (isExists)
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
tmpFVGs,
|
|
idx,
|
|
1 //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
Clean(tmpWorkingFVGs);
|
|
|
|
//
|
|
bool isFVGPassed = iOBFVG.HasFVG();
|
|
if (!isFVGPassed)
|
|
{
|
|
//
|
|
iOBFVG.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Validate Model ...
|
|
bool isValid = iOBFVG.IsValid();
|
|
if (!isValid)
|
|
{
|
|
//
|
|
iOBFVG.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
iOBFVG.UpdateTo(cTime);
|
|
|
|
//
|
|
AddRef(
|
|
iOBFVG,
|
|
dest //
|
|
);
|
|
|
|
//
|
|
iOBFVG.Clean();
|
|
}
|
|
|
|
//
|
|
Clean(tmpOBFVGs);
|
|
}
|
|
|
|
//
|
|
// Detecting Other POI(s) ...
|
|
has = HasChild(dest);
|
|
bool canDetectPOIs =
|
|
detectInsideOBPOIs ||
|
|
detectInsideFVGPOIs;
|
|
if (has &&
|
|
canDetectPOIs)
|
|
{
|
|
//
|
|
count = ArraySize(dest);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Supply Zones ...
|
|
has = stfState.HasSupplyZones();
|
|
if (has)
|
|
{
|
|
//
|
|
for (int j = 0; j < stfState.CountSupplyZones(); j++)
|
|
{
|
|
//
|
|
bool isInsideOB = IsInsideDiff(
|
|
stfState.supplyZones[j],
|
|
dest[i].ob //
|
|
);
|
|
|
|
//
|
|
bool isInsideFVG = IsInsideDiff(
|
|
stfState.supplyZones[j],
|
|
dest[i].fvg //
|
|
);
|
|
|
|
//
|
|
bool isInside = isInsideOB ||
|
|
isInsideFVG;
|
|
if (isInside)
|
|
{
|
|
//
|
|
bool isPassed =
|
|
detectInsideOBPOIs
|
|
? isInsideOB
|
|
: detectInsideFVGPOIs
|
|
? isInsideFVG
|
|
: false;
|
|
if (isPassed)
|
|
{
|
|
//
|
|
isPassed =
|
|
!applyFromFilterForPOIs
|
|
? isPassed
|
|
: isInsideOB
|
|
? stfState.supplyZones[j].From() > dest[i].ob.From()
|
|
: isInsideFVG
|
|
? stfState.supplyZones[j].From() > dest[i].fvg.From()
|
|
: false;
|
|
}
|
|
|
|
//
|
|
if (isPassed)
|
|
{
|
|
//
|
|
Add(
|
|
stfState.supplyZones[j],
|
|
dest[i].supplyZones //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand Zones ...
|
|
has = stfState.HasDemandZones();
|
|
if (has)
|
|
{
|
|
//
|
|
for (int j = 0; j < stfState.CountDemandZones(); j++)
|
|
{
|
|
//
|
|
bool isInsideOB = IsInsideDiff(
|
|
stfState.demandZones[j],
|
|
dest[i].ob //
|
|
);
|
|
|
|
//
|
|
bool isInsideFVG = IsInsideDiff(
|
|
stfState.demandZones[j],
|
|
dest[i].fvg //
|
|
);
|
|
|
|
//
|
|
bool isInside = isInsideOB ||
|
|
isInsideFVG;
|
|
if (isInside)
|
|
{
|
|
//
|
|
bool isPassed =
|
|
detectInsideOBPOIs
|
|
? isInsideOB
|
|
: detectInsideFVGPOIs
|
|
? isInsideFVG
|
|
: false;
|
|
if (isPassed)
|
|
{
|
|
//
|
|
isPassed =
|
|
!applyFromFilterForPOIs
|
|
? isPassed
|
|
: isInsideOB
|
|
? stfState.demandZones[j].From() > dest[i].ob.From()
|
|
: isInsideFVG
|
|
? stfState.demandZones[j].From() > dest[i].fvg.From()
|
|
: false;
|
|
}
|
|
|
|
//
|
|
if (isPassed)
|
|
{
|
|
//
|
|
Add(
|
|
stfState.demandZones[j],
|
|
dest[i].demandZones //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support Zones ...
|
|
has = stfState.HasSupportZones();
|
|
if (has)
|
|
{
|
|
//
|
|
for (int j = 0; j < stfState.CountSupportZones(); j++)
|
|
{
|
|
//
|
|
bool isInsideOB = IsInsideDiff(
|
|
stfState.supportZones[j],
|
|
dest[i].ob //
|
|
);
|
|
|
|
//
|
|
bool isInsideFVG = IsInsideDiff(
|
|
stfState.supportZones[j],
|
|
dest[i].fvg //
|
|
);
|
|
|
|
//
|
|
bool isInside = isInsideOB ||
|
|
isInsideFVG;
|
|
if (isInside)
|
|
{
|
|
//
|
|
bool isPassed =
|
|
detectInsideOBPOIs
|
|
? isInsideOB
|
|
: detectInsideFVGPOIs
|
|
? isInsideFVG
|
|
: false;
|
|
if (isPassed)
|
|
{
|
|
//
|
|
isPassed =
|
|
!applyFromFilterForPOIs
|
|
? isPassed
|
|
: isInsideOB
|
|
? stfState.supportZones[j].From() > dest[i].ob.From()
|
|
: isInsideFVG
|
|
? stfState.supportZones[j].From() > dest[i].fvg.From()
|
|
: false;
|
|
}
|
|
|
|
//
|
|
if (isPassed)
|
|
{
|
|
//
|
|
Add(
|
|
stfState.supportZones[j],
|
|
dest[i].supportZones //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistance Zones ...
|
|
has = stfState.HasResistanceZones();
|
|
if (has)
|
|
{
|
|
//
|
|
for (int j = 0; j < stfState.CountResistanceZones(); j++)
|
|
{
|
|
//
|
|
bool isInsideOB = IsInsideDiff(
|
|
stfState.resistanceZones[j],
|
|
dest[i].ob //
|
|
);
|
|
|
|
//
|
|
bool isInsideFVG = IsInsideDiff(
|
|
stfState.resistanceZones[j],
|
|
dest[i].fvg //
|
|
);
|
|
|
|
//
|
|
bool isInside = isInsideOB ||
|
|
isInsideFVG;
|
|
if (isInside)
|
|
{
|
|
//
|
|
bool isPassed =
|
|
detectInsideOBPOIs
|
|
? isInsideOB
|
|
: detectInsideFVGPOIs
|
|
? isInsideFVG
|
|
: false;
|
|
if (isPassed)
|
|
{
|
|
//
|
|
isPassed =
|
|
!applyFromFilterForPOIs
|
|
? isPassed
|
|
: isInsideOB
|
|
? stfState.resistanceZones[j].From() > dest[i].ob.From()
|
|
: isInsideFVG
|
|
? stfState.resistanceZones[j].From() > dest[i].fvg.From()
|
|
: false;
|
|
}
|
|
|
|
//
|
|
if (isPassed)
|
|
{
|
|
//
|
|
Add(
|
|
stfState.resistanceZones[j],
|
|
dest[i].resistanceZones //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(tmpOBs);
|
|
Clean(tmpFVGs);
|
|
Clean(tmpOBFVGs);
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Find Highest Order Block of XOBFVG Collection ...
|
|
*
|
|
* @param source: XOBFVG Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighest(
|
|
XOBFVG &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
bool has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOBFVG item;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XOBFVG iOBFVG = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!item.IsValid()
|
|
? true
|
|
: item.ob.Upper() < iOBFVG.ob.Upper();
|
|
if (canSet)
|
|
{
|
|
//
|
|
item = iOBFVG;
|
|
result = i;
|
|
}
|
|
|
|
//
|
|
iOBFVG.Clean();
|
|
}
|
|
|
|
//
|
|
item.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Find Lowest Order Block of XOBFVG Collection ...
|
|
*
|
|
* @param source: XOBFVG Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowest(
|
|
XOBFVG &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
bool has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOBFVG item;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XOBFVG iOBFVG = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!item.IsValid()
|
|
? true
|
|
: item.ob.Lower() > iOBFVG.ob.Lower();
|
|
if (canSet)
|
|
{
|
|
//
|
|
item = iOBFVG;
|
|
result = i;
|
|
}
|
|
|
|
//
|
|
iOBFVG.Clean();
|
|
}
|
|
|
|
//
|
|
item.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Find Youngest Order Block of XOBFVG Collection ...
|
|
*
|
|
* @param source: XOBFVG Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungest(
|
|
XOBFVG &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
bool has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOBFVG item;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XOBFVG iOBFVG = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!item.IsValid()
|
|
? true
|
|
: item.ob.From() < iOBFVG.ob.From();
|
|
if (canSet)
|
|
{
|
|
//
|
|
item = iOBFVG;
|
|
result = i;
|
|
}
|
|
|
|
//
|
|
iOBFVG.Clean();
|
|
}
|
|
|
|
//
|
|
item.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Find Oldest Order Block of XOBFVG Collection ...
|
|
*
|
|
* @param source: XOBFVG Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldest(
|
|
XOBFVG &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
bool has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOBFVG item;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XOBFVG iOBFVG = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!item.IsValid()
|
|
? true
|
|
: item.ob.From() > iOBFVG.ob.From();
|
|
if (canSet)
|
|
{
|
|
//
|
|
item = iOBFVG;
|
|
result = i;
|
|
}
|
|
|
|
//
|
|
iOBFVG.Clean();
|
|
}
|
|
|
|
//
|
|
item.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Sort XOBFVG Collection based on OB Place ...
|
|
*
|
|
* @param source: XOBFVG instance Collection ...
|
|
* @param forDir: ENUM_X_DIRECTION member ...
|
|
* @param ignoreInside: Specified Ignoring price inside in Sorting ...
|
|
*/
|
|
void Sort(
|
|
XOBFVG &source[],
|
|
ENUM_X_DIRECTION forDir,
|
|
bool ignoreInside = true //
|
|
)
|
|
{
|
|
//
|
|
int idx = -1;
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
has = HasDirection(forDir);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
count = ArraySize(source);
|
|
has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XOBFVG last;
|
|
XOBFVG tmpItems[];
|
|
bool hasLast = false;
|
|
while (HasChild(source))
|
|
{
|
|
//
|
|
if (!hasLast)
|
|
{
|
|
//
|
|
idx = GetYoungest(source);
|
|
hasLast = IsValidIndex(idx);
|
|
if (hasLast)
|
|
{
|
|
//
|
|
last = source[idx];
|
|
ArrayRemove(
|
|
source,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
AddRef(
|
|
last,
|
|
source //
|
|
);
|
|
}
|
|
|
|
//
|
|
count = ArraySize(source);
|
|
has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
//
|
|
last.Clean();
|
|
break;
|
|
}
|
|
}
|
|
if (!hasLast)
|
|
{
|
|
//
|
|
ZeroMemory(last);
|
|
break;
|
|
}
|
|
|
|
//
|
|
XOBFVG item;
|
|
idx = GetYoungest(source);
|
|
has = IsValidIndex(idx);
|
|
if (!has)
|
|
{
|
|
//
|
|
item.Clean();
|
|
last.Clean();
|
|
break;
|
|
}
|
|
item = source[idx];
|
|
ArrayRemove(
|
|
source,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
bool isAbove = IsAbove(
|
|
item.ob,
|
|
last.ob,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
bool isBelow = IsBelow(
|
|
item.ob,
|
|
last.ob,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
has =
|
|
isBullish
|
|
? isAbove
|
|
: isBelow;
|
|
if (has)
|
|
{
|
|
//
|
|
AddRef(
|
|
item,
|
|
tmpItems //
|
|
);
|
|
|
|
//
|
|
last = item;
|
|
hasLast = item.IsValid();
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(source);
|
|
Copy(
|
|
tmpItems,
|
|
source //
|
|
);
|
|
|
|
//
|
|
Clean(tmpItems);
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
/**
|
|
* Check Trading Conditions based on Specified Box ...
|
|
*
|
|
* @param box: XBoxZone instance Reference, specified Box for Checking Conditions ...
|
|
* @param appliedBox: XBoxZone instance Reference, hold's Selected Box inside Parent which trading conditions happens on it ...
|
|
* @param swingBar: XOHCL instance Reference, holds Swing Bar if Exists ...
|
|
* @param breakerBar: XOHCL instance Reference, holds Breaker Bar if Exists ...
|
|
* @param rejectionBar: XOHCL instance Reference, holds Rejection Bar if Exists ...
|
|
* @param momentumBar: XOHCL instance Reference, holds Momentum Bar if Exists ...
|
|
* @param state: XPOIState instance Reference, provides requirement zone's for check Conditions ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param forPeriod: ENUM_TIMEFRAMES member, Specified Conditions Checking Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool CheckBoxForTradeConditions(
|
|
XBoxZone &box,
|
|
XBoxZone &appliedBox,
|
|
XOHCL &swingBar,
|
|
XOHCL &breakerBar,
|
|
XOHCL &rejectionBar,
|
|
XOHCL &momentumBar,
|
|
XPOIState &state,
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
swingBar.Clean();
|
|
appliedBox.Clean();
|
|
breakerBar.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
result = box.IsValid() &&
|
|
state.IsValid() &&
|
|
state.HasChild();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = box.period;
|
|
}
|
|
|
|
//
|
|
string symbol = box.symbol;
|
|
datetime cTime = iTime(
|
|
symbol,
|
|
forPeriod,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
ENUM_X_DIRECTION forDir = box.dir;
|
|
result = HasDirection(forDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
int supportsCount = 0;
|
|
bool hasSupports = false;
|
|
XCSupportZone *supports[];
|
|
|
|
//
|
|
int resistancesCount = 0;
|
|
bool hasResistances = false;
|
|
XCResistanceZone *resistances[];
|
|
|
|
//
|
|
XBoxZone supResBoxes[];
|
|
int supresBoxesCount = 0;
|
|
bool hasSupResBoxes = false;
|
|
|
|
//
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
has = state.HasSupportZones();
|
|
if (has)
|
|
{
|
|
//
|
|
count = state.CountSupportZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSupportZone *iZone = state.supportZones[i];
|
|
|
|
//
|
|
iZone.To(cTime);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
bool hasBox = ToBox(
|
|
iBox,
|
|
iZone //
|
|
);
|
|
if (!hasBox)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check From ...
|
|
bool isInside = IsBoxInside(
|
|
iBox,
|
|
box //
|
|
);
|
|
if (!isInside)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
iZone,
|
|
supports //
|
|
);
|
|
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
supResBoxes //
|
|
);
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
supportsCount = ArraySize(supports);
|
|
hasSupports = IsValidSize(supportsCount);
|
|
|
|
//
|
|
supresBoxesCount = ArraySize(supResBoxes);
|
|
hasSupResBoxes = IsValidSize(supresBoxesCount);
|
|
}
|
|
|
|
//
|
|
has = state.HasResistanceZones();
|
|
if (has)
|
|
{
|
|
//
|
|
count = state.CountResistanceZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCResistanceZone *iZone = state.resistanceZones[i];
|
|
|
|
//
|
|
iZone.To(cTime);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
bool hasBox = ToBox(
|
|
iBox,
|
|
iZone //
|
|
);
|
|
if (!hasBox)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check From ...
|
|
bool isInside = IsBoxInside(
|
|
iBox,
|
|
box //
|
|
);
|
|
if (!isInside)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
iZone,
|
|
resistances //
|
|
);
|
|
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
supResBoxes //
|
|
);
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
resistancesCount = ArraySize(resistances);
|
|
hasResistances = IsValidSize(resistancesCount);
|
|
|
|
//
|
|
supresBoxesCount = ArraySize(supResBoxes);
|
|
hasSupResBoxes = IsValidSize(supresBoxesCount);
|
|
}
|
|
|
|
//
|
|
result = hasSupResBoxes;
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean(supports);
|
|
Clean(resistances);
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detect Bars ...
|
|
|
|
//
|
|
XOHCL zBar;
|
|
result = zBar.Init(
|
|
symbol,
|
|
forPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
Clean(supports);
|
|
Clean(resistances);
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = zBar.GetPreviousBar(cBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
Clean(supports);
|
|
Clean(resistances);
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
result = cBar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
Clean(supports);
|
|
Clean(resistances);
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL ppBar;
|
|
result = pBar.GetPreviousBar(ppBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
ppBar.Clean();
|
|
Clean(supports);
|
|
Clean(resistances);
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//
|
|
// Check Conditions ...
|
|
|
|
//
|
|
// Detect Start Senario ...
|
|
|
|
//
|
|
double fiboPressureLevel = GetFiboLevelValue(X_FIBO_LEVEL_382);
|
|
|
|
//
|
|
double fiboUpDown = GetFibonacciLevel(
|
|
pBar.high,
|
|
pBar.low,
|
|
X_FIBO_LEVEL_382,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
double fiboDownUp = GetFibonacciLevel(
|
|
pBar.high,
|
|
pBar.low,
|
|
X_FIBO_LEVEL_382,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
|
|
//
|
|
bool hasFiboToUpPressure =
|
|
fiboDownUp > 0 &&
|
|
fiboDownUp <= pBar.GetDown();
|
|
bool hasFiboToDownPressure =
|
|
fiboUpDown > 0 &&
|
|
fiboUpDown >= pBar.GetUp();
|
|
|
|
//
|
|
int selectedBoxIDX = -1;
|
|
for (int j = 0; j < supresBoxesCount; j++)
|
|
{
|
|
//
|
|
double appliedPrice =
|
|
isBullish
|
|
? supResBoxes[j].lower
|
|
: supResBoxes[j].upper;
|
|
|
|
//
|
|
// Check Swing Low ...
|
|
bool isSwingLow =
|
|
//
|
|
pBar.low < ppBar.low &&
|
|
pBar.low < cBar.low &&
|
|
zBar.open > pBar.low &&
|
|
//
|
|
appliedPrice > pBar.low &&
|
|
appliedPrice < pBar.GetDown()
|
|
//
|
|
;
|
|
bool isPressuredSwingLow =
|
|
isSwingLow &&
|
|
hasFiboToUpPressure;
|
|
bool isPressuredStrongSwingLow =
|
|
pBar.IsBullish() &&
|
|
isPressuredSwingLow;
|
|
|
|
//
|
|
bool isSwingHigh =
|
|
//
|
|
pBar.high > ppBar.high &&
|
|
pBar.high > cBar.high &&
|
|
zBar.open < pBar.high &&
|
|
//
|
|
appliedPrice < pBar.high &&
|
|
appliedPrice > pBar.GetUp()
|
|
//
|
|
;
|
|
bool isPressuredSwingHigh =
|
|
isSwingHigh &&
|
|
hasFiboToDownPressure;
|
|
bool isPressuredStrongSwingHigh =
|
|
pBar.IsBearish() &&
|
|
isPressuredSwingHigh;
|
|
|
|
//
|
|
bool hasValidSwing =
|
|
isBullish
|
|
? isSwingLow
|
|
: isSwingHigh;
|
|
bool hasValidPressuredSwing =
|
|
isBullish
|
|
? isPressuredSwingLow
|
|
: isPressuredSwingHigh;
|
|
bool hasValidPressuredStrongSwing =
|
|
isBullish
|
|
? isPressuredStrongSwingLow
|
|
: isPressuredStrongSwingHigh;
|
|
if (hasValidSwing)
|
|
{
|
|
swingBar = pBar;
|
|
}
|
|
if (hasValidPressuredSwing)
|
|
{
|
|
swingBar = pBar;
|
|
}
|
|
if (hasValidPressuredStrongSwing)
|
|
{
|
|
swingBar = pBar;
|
|
}
|
|
|
|
//
|
|
bool isCBarBreaked = IsBarBreak(
|
|
appliedPrice,
|
|
forDir,
|
|
cBar //
|
|
);
|
|
if (isCBarBreaked)
|
|
{
|
|
breakerBar = cBar;
|
|
}
|
|
bool isPBarBreaked = IsBarBreak(
|
|
appliedPrice,
|
|
forDir,
|
|
pBar //
|
|
);
|
|
if (!isCBarBreaked && isPBarBreaked)
|
|
{
|
|
breakerBar = pBar;
|
|
}
|
|
else
|
|
{
|
|
isPBarBreaked = false;
|
|
}
|
|
bool isPPBarBreaked = IsBarBreak(
|
|
appliedPrice,
|
|
forDir,
|
|
ppBar //
|
|
);
|
|
if (!isCBarBreaked &&
|
|
!isPBarBreaked &&
|
|
isPPBarBreaked)
|
|
{
|
|
breakerBar = ppBar;
|
|
}
|
|
else
|
|
{
|
|
isPPBarBreaked = false;
|
|
}
|
|
bool isBoxBreaked = isCBarBreaked ||
|
|
isPBarBreaked ||
|
|
isPPBarBreaked;
|
|
|
|
//
|
|
bool isCBarRejected = IsBarReject(
|
|
appliedPrice,
|
|
forDir,
|
|
cBar //
|
|
);
|
|
if (isCBarRejected)
|
|
{
|
|
rejectionBar = cBar;
|
|
}
|
|
bool isPBarRejected = IsBarReject(
|
|
appliedPrice,
|
|
forDir,
|
|
pBar //
|
|
);
|
|
if (!isCBarRejected && isPBarRejected)
|
|
{
|
|
rejectionBar = pBar;
|
|
}
|
|
else
|
|
{
|
|
isPBarRejected = false;
|
|
}
|
|
bool isPPBarRejected = IsBarReject(
|
|
appliedPrice,
|
|
forDir,
|
|
ppBar //
|
|
);
|
|
if (!isCBarRejected &&
|
|
!isPBarRejected &&
|
|
isPPBarRejected)
|
|
{
|
|
rejectionBar = ppBar;
|
|
}
|
|
else
|
|
{
|
|
isPPBarRejected = false;
|
|
}
|
|
bool isBoxRejected = isCBarRejected ||
|
|
isPBarRejected ||
|
|
isPPBarRejected;
|
|
|
|
//
|
|
bool hasRejectionBar = false;
|
|
if (isBullish)
|
|
{
|
|
//
|
|
count = state.CountBullishRejectionBars();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCRejectionBar *iZone = state.bullishRejectionBars[i];
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isFilled = iZone.FillBar(iBar);
|
|
if (!isFilled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iBarIndex = iBar.Index();
|
|
|
|
//
|
|
hasRejectionBar =
|
|
//
|
|
(iBarIndex == cBar.Index() ||
|
|
iBarIndex == pBar.Index())
|
|
//
|
|
;
|
|
if (hasRejectionBar)
|
|
{
|
|
//
|
|
if (!rejectionBar.IsValid())
|
|
{
|
|
rejectionBar = iBar;
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
count = state.CountBearishRejectionBars();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCRejectionBar *iZone = state.bearishRejectionBars[i];
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isFilled = iZone.FillBar(iBar);
|
|
if (!isFilled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iBarIndex = iBar.Index();
|
|
|
|
//
|
|
hasRejectionBar =
|
|
//
|
|
(iBarIndex == cBar.Index() ||
|
|
iBarIndex == pBar.Index())
|
|
//
|
|
;
|
|
if (hasRejectionBar)
|
|
{
|
|
//
|
|
if (!rejectionBar.IsValid())
|
|
{
|
|
rejectionBar = iBar;
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
bool hasMomentumBar = false;
|
|
if (isBullish)
|
|
{
|
|
//
|
|
count = state.CountBullishMomentumBars();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCMomentumBar *iZone = state.bullishMomentumBars[i];
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isFilled = iZone.FillBar(iBar);
|
|
if (!isFilled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iBarIndex = iBar.Index();
|
|
|
|
//
|
|
hasMomentumBar =
|
|
//
|
|
(iBarIndex == cBar.Index() ||
|
|
iBarIndex == pBar.Index())
|
|
//
|
|
;
|
|
if (hasMomentumBar)
|
|
{
|
|
//
|
|
if (!momentumBar.IsValid())
|
|
{
|
|
momentumBar = iBar;
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
count = state.CountBearishMomentumBars();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCMomentumBar *iZone = state.bearishMomentumBars[i];
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isFilled = iZone.FillBar(iBar);
|
|
if (!isFilled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iBarIndex = iBar.Index();
|
|
|
|
//
|
|
hasMomentumBar =
|
|
//
|
|
(iBarIndex == cBar.Index() ||
|
|
iBarIndex == pBar.Index())
|
|
//
|
|
;
|
|
if (hasMomentumBar)
|
|
{
|
|
//
|
|
if (!momentumBar.IsValid())
|
|
{
|
|
momentumBar = iBar;
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
bool hasSwing = false;
|
|
if (isBullish)
|
|
{
|
|
//
|
|
count = state.CountSwingLows();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSwing *iSwing = state.swingLows[i];
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isFilled = iSwing.FillBar(iBar);
|
|
if (!isFilled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iBarIndex = iBar.Index();
|
|
|
|
//
|
|
hasSwing =
|
|
//
|
|
(iBarIndex == cBar.Index() ||
|
|
iBarIndex == pBar.Index())
|
|
//
|
|
;
|
|
if (hasSwing)
|
|
{
|
|
//
|
|
if (!swingBar.IsValid())
|
|
{
|
|
swingBar = iBar;
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
count = state.CountSwingHighs();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSwing *iSwing = state.swingHighs[i];
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isFilled = iSwing.FillBar(iBar);
|
|
if (!isFilled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iBarIndex = iBar.Index();
|
|
|
|
//
|
|
hasSwing =
|
|
//
|
|
(iBarIndex == cBar.Index() ||
|
|
iBarIndex == pBar.Index())
|
|
//
|
|
;
|
|
if (hasSwing)
|
|
{
|
|
//
|
|
if (!swingBar.IsValid())
|
|
{
|
|
swingBar = iBar;
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
bool hasRequiredValidations =
|
|
//
|
|
(hasRejectionBar ||
|
|
hasMomentumBar)
|
|
//
|
|
||
|
|
//
|
|
(hasRejectionBar ||
|
|
hasSwing)
|
|
//
|
|
||
|
|
//
|
|
(hasMomentumBar ||
|
|
hasSwing)
|
|
//
|
|
;
|
|
|
|
//
|
|
result =
|
|
//
|
|
(isBoxBreaked &&
|
|
(hasRequiredValidations ||
|
|
hasValidPressuredSwing))
|
|
//
|
|
||
|
|
//
|
|
(isBoxRejected &&
|
|
(hasRequiredValidations ||
|
|
hasValidPressuredSwing))
|
|
//
|
|
;
|
|
if (result)
|
|
{
|
|
//
|
|
selectedBoxIDX = j;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
(isBullish
|
|
? zBar.open > box.upper
|
|
: zBar.open < box.lower) &&
|
|
IsValidIndex(selectedBoxIDX);
|
|
if (result)
|
|
{
|
|
appliedBox = supResBoxes[selectedBoxIDX];
|
|
}
|
|
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
ppBar.Clean();
|
|
Clean(supports);
|
|
Clean(resistances);
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
return result;
|
|
}
|