Files
MQL5Data/Libraries/x-saherelm.xobfvg.lib.mq5
T
2025-02-22 05:16:43 +03:30

1899 lines
42 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Seriallize Library
// ---------------------------------------
// Name: XOBFVGLib
// 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"
#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5"
//
struct XOBFVGPivot
{
//
// Props ...
double value;
datetime at;
//
// Constructor ...
XOBFVGPivot()
{
Clean();
}
//
// Tools ...
//
void Clean()
{
//
value = 0;
at = NULL;
//
ZeroMemory(this);
}
//
bool IsValid()
{
//
bool result = false;
//
result =
value > 0 &&
IsValid(at);
//
return result;
}
};
//
struct XOBFVG
{
//
// Props ...
XCFVG *fvg;
XCOrderBlock *ob;
//
XCSupplyZone *supplyZones[];
XCDemandZone *demandZones[];
//
XCSupportZone *supportZones[];
XCResistanceZone *resistanceZones[];
//
// Constructor ...
XOBFVG()
{
Clean();
}
//
// Tools ...
//
void Clean()
{
//
ZeroMemory(ob);
ZeroMemory(fvg);
//
Clean(supplyZones);
Clean(demandZones);
Clean(supportZones);
Clean(resistanceZones);
//
ZeroMemory(this);
}
//
bool IsValid()
{
return HasOB() &&
HasFVG();
}
//
bool HasOB()
{
return ob != NULL &&
ob.IsValid();
}
//
bool HasFVG()
{
return fvg != NULL &&
fvg.IsValid();
}
//
bool HasSupplyZones()
{
return HasChild(supplyZones);
}
//
int CountSupplyZones()
{
return ArraySize(supplyZones);
}
//
bool HasDemandZones()
{
return HasChild(demandZones);
}
//
int CountDemandZones()
{
return ArraySize(demandZones);
}
//
bool HasSupportZones()
{
return HasChild(supportZones);
}
//
int CountSupportZones()
{
return ArraySize(supportZones);
}
//
bool HasResistanceZones()
{
return HasChild(resistanceZones);
}
//
int CountResistanceZones()
{
return ArraySize(resistanceZones);
}
//
ENUM_X_DIRECTION GetDirection()
{
//
ENUM_X_DIRECTION result = X_DIRECTION_NONE;
//
bool isValid = IsValid();
if (!isValid)
{
return result;
}
//
result = ob.GetDirection();
//
return result;
}
//
bool IsBullish()
{
return IsBullish(GetDirection());
}
//
bool IsBearish()
{
return IsBearish(GetDirection());
}
//
int GetSwings(
XOBFVGPivot &pivots[] //
)
{
//
int result = 0;
//
Clean(pivots);
//
if (!IsValid())
{
return result;
}
//
ENUM_X_DIRECTION forDir = GetDirection();
bool isBullish = IsBullish(forDir);
//
XOHCL passedBar;
XOBFVGPivot iPivot;
bool isPassed = false;
double appliedPrice = 0;
bool isBodyState = false;
//
// Start ...
isPassed = ob.IsStarted(
forDir,
passedBar,
isBodyState //
);
if (isPassed)
{
//
appliedPrice =
isBullish
? passedBar.low
: passedBar.high;
//
iPivot.Clean();
iPivot.value = appliedPrice;
iPivot.at = passedBar.time;
//
AddRef(
iPivot,
pivots //
);
//
iPivot.Clean();
}
//
// Activation ...
isPassed = ob.IsActivated(
forDir,
passedBar,
isBodyState //
);
if (isPassed)
{
//
appliedPrice =
isBullish
? passedBar.low
: passedBar.high;
//
iPivot.Clean();
iPivot.value = appliedPrice;
iPivot.at = passedBar.time;
//
AddRef(
iPivot,
pivots //
);
//
iPivot.Clean();
}
//
// Worked ...
isPassed = ob.IsWorked(
forDir,
passedBar,
isBodyState //
);
if (isPassed)
{
//
appliedPrice =
isBullish
? passedBar.low
: passedBar.high;
//
iPivot.Clean();
iPivot.value = appliedPrice;
iPivot.at = passedBar.time;
//
AddRef(
iPivot,
pivots //
);
//
iPivot.Clean();
}
//
passedBar.Clean();
//
result = ArraySize(pivots);
//
return result;
}
//
void UpdateZones(
XPOIState &state //
)
{
//
Clean(supplyZones);
Clean(demandZones);
Clean(supportZones);
Clean(resistanceZones);
//
bool isValid =
IsValid() &&
state.HasChild();
if (!isValid)
{
return;
}
//
int count = 0;
bool has = false;
bool isPassed = false;
//
// Supply Zones ...
has = state.HasSupplyZones();
if (has)
{
//
count = state.CountSupplyZones();
for (int i = 0; i < count; i++)
{
//
XCSupplyZone *iZone = state.supplyZones[i];
//
isPassed = iZone.From() > ob.From();
if (!isPassed)
{
//
ZeroMemory(iZone);
continue;
}
//
isPassed = IsInsideDiff(
iZone,
ob //
);
if (!isPassed)
{
//
ZeroMemory(iZone);
continue;
}
//
Add(
iZone,
supplyZones //
);
}
}
//
// Demand Zones ...
has = state.HasDemandZones();
if (has)
{
//
count = state.CountDemandZones();
for (int i = 0; i < count; i++)
{
//
XCDemandZone *iZone = state.demandZones[i];
//
isPassed = iZone.From() > ob.From();
if (!isPassed)
{
//
ZeroMemory(iZone);
continue;
}
//
isPassed = IsInsideDiff(
iZone,
ob //
);
if (!isPassed)
{
//
ZeroMemory(iZone);
continue;
}
//
Add(
iZone,
demandZones //
);
}
}
//
// Support Zones ...
has = state.HasSupportZones();
if (has)
{
//
count = state.CountSupportZones();
for (int i = 0; i < count; i++)
{
//
XCSupportZone *iZone = state.supportZones[i];
//
isPassed = iZone.From() > ob.From();
if (!isPassed)
{
//
ZeroMemory(iZone);
continue;
}
//
isPassed = IsInsideDiff(
iZone,
ob //
);
if (!isPassed)
{
//
ZeroMemory(iZone);
continue;
}
//
Add(
iZone,
supportZones //
);
}
}
//
// Resistance Zones ...
has = state.HasResistanceZones();
if (has)
{
//
count = state.CountResistanceZones();
for (int i = 0; i < count; i++)
{
//
XCResistanceZone *iZone = state.resistanceZones[i];
//
isPassed = iZone.From() > ob.From();
if (!isPassed)
{
//
ZeroMemory(iZone);
continue;
}
//
isPassed = IsInsideDiff(
iZone,
ob //
);
if (!isPassed)
{
//
ZeroMemory(iZone);
continue;
}
//
Add(
iZone,
resistanceZones //
);
}
}
}
//
void UpdateTo(datetime value = NULL)
{
//
value = NormalizeTime(value);
//
int count = 0;
bool has = false;
//
has = HasOB();
if (has)
{
ob.To(value);
}
//
has = HasFVG();
if (has)
{
fvg.To(value);
}
//
// Supply Zones ...
has = HasSupplyZones();
if (has)
{
//
count = CountSupplyZones();
for (int i = 0; i < count; i++)
{
supplyZones[i].To(value);
}
}
//
// Demand Zones ...
has = HasDemandZones();
if (has)
{
//
count = CountDemandZones();
for (int i = 0; i < count; i++)
{
demandZones[i].To(value);
}
}
//
// Support Zones ...
has = HasSupportZones();
if (has)
{
//
count = CountSupportZones();
for (int i = 0; i < count; i++)
{
supportZones[i].To(value);
}
}
//
// Resistance Zones ...
has = HasResistanceZones();
if (has)
{
//
count = CountResistanceZones();
for (int i = 0; i < count; i++)
{
resistanceZones[i].To(value);
}
}
}
};
//
//
//
/**
* 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 = GetOldest(source);
hasLast = IsValidIndex(idx);
if (hasLast)
{
//
last = source[idx];
ArrayRemove(
source,
idx,
1 //
);
//
AddRef(
last,
tmpItems //
);
}
//
count = ArraySize(source);
has = IsValidSize(count);
if (!has)
{
//
last.Clean();
break;
}
}
if (!hasLast)
{
//
last.Clean();
break;
}
//
XOBFVG item;
idx = GetOldest(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);
}
//