Files
MQL5Data/Documents/BKP/1/poilib.bkp.mq5
T
2025-02-04 03:33:59 +03:30

7951 lines
158 KiB
Plaintext

/**
* Calculate Target for Specified Direction ...
*
* @param bar: XOHCL instance Reference ...
* @param state: XPOIState instance Reference ...
* @param forDir: ENUM_S_DIRECTION member ...
*
* @return ( double )
*/
double CalculateTarget(
XOHCL &bar,
XPOIState &state,
ENUM_X_DIRECTION forDir //
)
{
//
double result = 0;
//
if (!state.IsValid() ||
!state.HasChild() ||
!HasDirection(forDir))
{
return result;
}
//
XCFVG *iFVG = NULL;
XCOrderBlock *iOB = NULL;
XCSupplyZone *iSupply = NULL;
XCDemandZone *iDemand = NULL;
XCSupportZone *iSupport = NULL;
XCResistanceZone *iResistance = NULL;
//
bool hasOB = false;
bool hasFVG = false;
bool hasSupply = false;
bool hasDemand = false;
bool hasSupport = false;
bool hasResistance = false;
//
int count = 0;
//
if (IsBearish(forDir))
{
//
// FVG ...
count = state.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iZone = state.bullishFairValueGaps[i];
//
bool isValid = IsPriceAboveZone(
bar,
iZone //
);
if (isValid)
{
//
iFVG = iZone;
hasFVG = true;
break;
}
}
}
//
// OB ...
count = state.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCOrderBlock *iZone = state.bullishOrderBlocks[i];
//
bool isValid = IsPriceAboveZone(
bar,
iZone //
);
if (isValid)
{
//
iOB = iZone;
hasOB = true;
break;
}
}
}
//
// SUPPORT ...
count = state.CountSupportZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCSupportZone *iZone = state.supportZones[i];
//
bool isValid = IsPriceAboveZone(
bar,
iZone //
);
if (isValid)
{
//
iSupport = iZone;
hasSupport = true;
break;
}
}
}
//
// DEMAND ...
count = state.CountDemandZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCDemandZone *iZone = state.demandZones[i];
//
bool isValid = IsPriceAboveZone(
bar,
iZone //
);
if (isValid)
{
//
iDemand = iZone;
hasDemand = true;
break;
}
}
}
//
// Summary ...
result =
hasFVG
? iFVG.Upper()
: hasOB
? iOB.Upper()
: hasSupport
? iSupport.Upper()
: hasDemand
? iDemand.Upper()
: 0;
if (hasFVG)
{
result = MathMax(result, iFVG.Upper());
}
if (hasOB)
{
result = MathMax(result, iOB.Upper());
}
if (hasSupport)
{
result = MathMax(result, iSupport.Upper());
}
if (hasDemand)
{
result = MathMax(result, iDemand.Upper());
}
}
//
if (IsBullish(forDir))
{
//
// FVG ...
count = state.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iZone = state.bearishFairValueGaps[i];
//
bool isValid = IsPriceBelowZone(
bar,
iZone //
);
if (isValid)
{
//
iFVG = iZone;
hasFVG = true;
break;
}
}
}
//
// OB ...
count = state.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCOrderBlock *iZone = state.bearishOrderBlocks[i];
//
bool isValid = IsPriceBelowZone(
bar,
iZone //
);
if (isValid)
{
//
iOB = iZone;
hasOB = true;
break;
}
}
}
//
// RESISTANCE ...
count = state.CountResistanceZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCResistanceZone *iZone = state.resistanceZones[i];
//
bool isValid = IsPriceBelowZone(
bar,
iZone //
);
if (isValid)
{
//
iResistance = iZone;
hasResistance = true;
break;
}
}
}
//
// SUPPLY ...
count = state.CountSupplyZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCSupplyZone *iZone = state.supplyZones[i];
//
bool isValid = IsPriceBelowZone(
bar,
iZone //
);
if (isValid)
{
//
iSupply = iZone;
hasSupply = true;
break;
}
}
}
//
// Summary ...
result =
hasFVG
? iFVG.Lower()
: hasOB
? iOB.Lower()
: hasSupport
? iSupport.Lower()
: hasDemand
? iDemand.Lower()
: 0;
if (hasFVG)
{
result = MathMin(result, iFVG.Lower());
}
if (hasOB)
{
result = MathMin(result, iOB.Lower());
}
if (hasSupport)
{
result = MathMin(result, iSupport.Lower());
}
if (hasDemand)
{
result = MathMin(result, iDemand.Lower());
}
}
//
return result;
}
/**
* Detect Valid Order Blocks ...
*
* @param forDir: ENUM_X_DIRECTION member ...
* @param source: XPOIState instance Reference ...
*
* @return ( int )
*/
int DetectValidOrderBlocks(
ENUM_X_DIRECTION forDir,
XPOIState &source,
XCOrderBlock *&orderBlocks[] //
)
{
//
int result = 0;
//
Clean(orderBlocks);
//
bool isValid =
//
source.IsValid() &&
source.HasChild() &&
HasDirection(forDir)
//
;
if (!isValid)
{
return result;
}
//
datetime cTime = TimeCurrent();
//
XOHCL cBar;
bool isInited = cBar.Init(
source.symbol,
source.period,
1 //
);
if (!isInited)
{
return result;
}
//
int count = 0;
//
// Bullish ...
count = source.CountBullishOrderBlocks();
isValid = IsValidSize(count) &&
IsBullish(forDir);
if (isValid)
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iOB = source.bullishOrderBlocks[i];
//
// Update Order Block Time ...
iOB.To(cTime);
//
// Check Order Block Validation ...
isValid = IsValid(
forDir,
cBar.symbol,
cBar.period,
iOB.Upper(),
iOB.Lower(),
iOB.From(),
iOB.To() //
);
if (isValid)
{
//
Add(
iOB,
orderBlocks //
);
}
}
}
//
// Bearish ...
count = source.CountBearishOrderBlocks();
isValid = IsValidSize(count) &&
IsBearish(forDir);
if (isValid)
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iOB = source.bearishOrderBlocks[i];
//
// Update Order Block Time ...
iOB.To(cTime);
//
// Check Order Block Validation ...
isValid = IsValid(
forDir,
cBar.symbol,
cBar.period,
iOB.Upper(),
iOB.Lower(),
iOB.From(),
iOB.To() //
);
if (isValid)
{
//
Add(
iOB,
orderBlocks //
);
}
}
}
//
result = ArraySize(orderBlocks);
//
return result;
}
/**
* Detect Valid Fair Value Gaps ...
*
* @param forDir: ENUM_X_DIRECTION member ...
* @param source: XPOIState instance Reference ...
*
* @return ( int )
*/
int DetectValidFairValueGaps(
ENUM_X_DIRECTION forDir,
XPOIState &source,
XCFVG *&fairValueGaps[] //
)
{
//
int result = 0;
//
Clean(fairValueGaps);
//
bool isValid =
//
source.IsValid() &&
source.HasChild() &&
HasDirection(forDir)
//
;
if (!isValid)
{
return result;
}
//
datetime cTime = TimeCurrent();
//
XOHCL cBar;
bool isInited = cBar.Init(
source.symbol,
source.period,
1 //
);
if (!isInited)
{
return result;
}
//
int count = 0;
//
// Bullish ...
count = source.CountBullishFairValueGaps();
isValid = IsValidSize(count) &&
IsBullish(forDir);
if (isValid)
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iFVG = source.bullishFairValueGaps[i];
//
// Update FVG Time ...
iFVG.To(cTime);
//
// Check FVG Validation ...
isValid = IsValid(
forDir,
cBar.symbol,
cBar.period,
iFVG.Upper(),
iFVG.Lower(),
iFVG.From(),
iFVG.To() //
);
if (isValid)
{
//
Add(
iFVG,
fairValueGaps //
);
}
}
}
//
// Bearish ...
count = source.CountBearishFairValueGaps();
isValid = IsValidSize(count) &&
IsBearish(forDir);
if (isValid)
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iFVG = source.bearishFairValueGaps[i];
//
// Update Order Block Time ...
iFVG.To(cTime);
//
// Check Order Block Validation ...
isValid = IsValid(
forDir,
cBar.symbol,
cBar.period,
iFVG.Upper(),
iFVG.Lower(),
iFVG.From(),
iFVG.To() //
);
if (isValid)
{
//
Add(
iFVG,
fairValueGaps //
);
}
}
}
//
result = ArraySize(fairValueGaps);
//
return result;
}
/**
* Detect Valid Support Zones ...
*
* @param source: XPOIState instance ...
*
* @return ( int )
*/
int DetectValidSupportZones(
XPOIState &source,
XCOrderBlock *&bullishOrderBlocks[],
XCFVG *&bullishFairValueGaps[],
XCSupportZone *&supportZones[] //
)
{
//
int result = 0;
//
Clean(supportZones);
//
int obsCount = ArraySize(bullishOrderBlocks);
int fvgsCount = ArraySize(bullishFairValueGaps);
//
bool isValid =
//
source.IsValid() &&
source.HasChild() &&
IsValidSize(obsCount + fvgsCount)
//
;
if (!isValid)
{
return result;
}
//
int count = source.CountSupportZones();
for (int i = 0; i < count; i++)
{
//
XCSupportZone *iZone = source.supportZones[i];
//
bool isAdded = false;
//
for (int j = 0; j < obsCount; j++)
{
//
XCOrderBlock *iOB = bullishOrderBlocks[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iOB.Upper(),
iOB.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iOB.Upper(),
iOB.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
supportZones //
);
//
isAdded = true;
break;
}
}
//
if (isAdded)
{
continue;
}
//
for (int j = 0; j < fvgsCount; j++)
{
//
XCFVG *iFVG = bullishFairValueGaps[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iFVG.Upper(),
iFVG.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iFVG.Upper(),
iFVG.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
supportZones //
);
//
isAdded = true;
break;
}
}
}
//
result = ArraySize(supportZones);
//
return result;
}
/**
* Detect Valid Resistance Zones ...
*
* @param source: XPOIState instance ...
*
* @return ( int )
*/
int DetectValidResistanceZones(
XPOIState &source,
XCOrderBlock *&bearishOrderBlocks[],
XCFVG *&bearishFairValueGaps[],
XCResistanceZone *&resistanceZones[] //
)
{
//
int result = 0;
//
Clean(resistanceZones);
//
int obsCount = ArraySize(bearishOrderBlocks);
int fvgsCount = ArraySize(bearishFairValueGaps);
//
bool isValid =
//
source.IsValid() &&
source.HasChild() &&
IsValidSize(obsCount + fvgsCount)
//
;
if (!isValid)
{
return result;
}
//
int count = source.CountResistanceZones();
for (int i = 0; i < count; i++)
{
//
XCResistanceZone *iZone = source.resistanceZones[i];
//
bool isAdded = false;
//
for (int j = 0; j < obsCount; j++)
{
//
XCOrderBlock *iOB = bearishOrderBlocks[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iOB.Upper(),
iOB.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iOB.Upper(),
iOB.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
resistanceZones //
);
//
isAdded = true;
break;
}
}
//
if (isAdded)
{
continue;
}
//
for (int j = 0; j < fvgsCount; j++)
{
//
XCFVG *iFVG = bearishFairValueGaps[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iFVG.Upper(),
iFVG.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iFVG.Upper(),
iFVG.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
resistanceZones //
);
//
isAdded = true;
break;
}
}
}
//
result = ArraySize(resistanceZones);
//
return result;
}
/**
* Detect Valid Support Zones ...
*
* @param source: XPOIState instance ...
*
* @return ( int )
*/
int DetectValidDemandZones(
XPOIState &source,
XCOrderBlock *&bullishOrderBlocks[],
XCFVG *&bullishFairValueGaps[],
XCDemandZone *&demandZones[] //
)
{
//
int result = 0;
//
Clean(demandZones);
//
int obsCount = ArraySize(bullishOrderBlocks);
int fvgsCount = ArraySize(bullishFairValueGaps);
//
bool isValid =
//
source.IsValid() &&
source.HasChild() &&
IsValidSize(obsCount + fvgsCount)
//
;
if (!isValid)
{
return result;
}
//
int count = source.CountDemandZones();
for (int i = 0; i < count; i++)
{
//
XCDemandZone *iZone = source.demandZones[i];
//
bool isAdded = false;
//
for (int j = 0; j < obsCount; j++)
{
//
XCOrderBlock *iOB = bullishOrderBlocks[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iOB.Upper(),
iOB.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iOB.Upper(),
iOB.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
demandZones //
);
//
isAdded = true;
break;
}
}
//
if (isAdded)
{
continue;
}
//
for (int j = 0; j < fvgsCount; j++)
{
//
XCFVG *iFVG = bullishFairValueGaps[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iFVG.Upper(),
iFVG.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iFVG.Upper(),
iFVG.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
demandZones //
);
//
isAdded = true;
break;
}
}
}
//
result = ArraySize(demandZones);
//
return result;
}
/**
* Detect Valid Resistance Zones ...
*
* @param source: XPOIState instance ...
*
* @return ( int )
*/
int DetectValidSupplyZones(
XPOIState &source,
XCOrderBlock *&bearishOrderBlocks[],
XCFVG *&bearishFairValueGaps[],
XCSupplyZone *&supplyZones[] //
)
{
//
int result = 0;
//
Clean(supplyZones);
//
int obsCount = ArraySize(bearishOrderBlocks);
int fvgsCount = ArraySize(bearishFairValueGaps);
//
bool isValid =
//
source.IsValid() &&
source.HasChild() &&
IsValidSize(obsCount + fvgsCount)
//
;
if (!isValid)
{
return result;
}
//
int count = source.CountSupplyZones();
for (int i = 0; i < count; i++)
{
//
XCSupplyZone *iZone = source.supplyZones[i];
//
bool isAdded = false;
//
for (int j = 0; j < obsCount; j++)
{
//
XCOrderBlock *iOB = bearishOrderBlocks[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iOB.Upper(),
iOB.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iOB.Upper(),
iOB.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
supplyZones //
);
//
isAdded = true;
break;
}
}
//
if (isAdded)
{
continue;
}
//
for (int j = 0; j < fvgsCount; j++)
{
//
XCFVG *iFVG = bearishFairValueGaps[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iFVG.Upper(),
iFVG.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iFVG.Upper(),
iFVG.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
supplyZones //
);
//
isAdded = true;
break;
}
}
}
//
result = ArraySize(supplyZones);
//
return result;
}
/**
* Detect a Zone Breaker Bar ...
*
* @param toBar: XOHCL instance Reference ...
* @param fromBar: XOHCL instance Reference ...
* @param breakerBar: XOHCL instance Reference ...
* @param forDir: ENUM_X_DIRECTION member ...
* @param symbol: String ...
* @param period: ENUM_TIMEFRAMES member ...
*
* @return ( bool )
*/
bool HasBreakerBar(
XOHCL &toBar,
XOHCL &fromBar,
XOHCL &breakerBar,
ENUM_X_DIRECTION forDir,
string symbol,
ENUM_TIMEFRAMES period,
double upper,
double lower,
datetime from,
datetime to //
)
{
//
bool result = false;
//
toBar.Clean();
fromBar.Clean();
breakerBar.Clean();
//
result =
//
upper > 0 &&
lower > 0 &&
IsValid(to) &&
upper > lower &&
IsValid(from) &&
IsValid(symbol) &&
IsValid(period) &&
HasDirection(forDir)
//
;
if (!result)
{
return result;
}
//
result = fromBar.Init(
symbol,
period,
from //
);
if (!result)
{
return result;
}
//
result = toBar.Init(
symbol,
period,
to //
);
if (!result)
{
return result;
}
//
int toIndex = toBar.Index();
int fromIndex = fromBar.Index();
//
// Detect Zone BreakerBar ...
for (int i = fromIndex; i >= toIndex; i--)
{
//
XOHCL iBar;
result = iBar.Init(
symbol,
period,
i //
);
//
if (!result)
{
continue;
}
//
result =
//
IsBullish(forDir)
?
//
iBar.low < upper &&
iBar.high > upper &&
iBar.GetUp() > upper
//
:
//
iBar.high > lower &&
iBar.low < lower &&
iBar.GetDown() < lower
//
;
if (result)
{
//
breakerBar = iBar;
break;
}
}
//
result = breakerBar.IsValid();
//
return result;
}
/**
* Validate Specified Order Block ...
*
* @param forDir: ENUM_X_DIRECTION member ...
* @param symbol: String ...
* @param period: ENUM_TIMEFRAMES member ...
*
* @return ( bool )
*/
bool IsValid(
ENUM_X_DIRECTION forDir,
string symbol,
ENUM_TIMEFRAMES period,
double upper,
double lower,
datetime from,
datetime to,
bool ignoreBreakerBar = false //
)
{
//
bool result = false;
//
result =
upper > 0 &&
lower > 0 &&
IsValid(to) &&
upper > lower &&
IsValid(from) &&
IsValid(symbol) &&
IsValid(period) &&
HasDirection(forDir)
//
;
if (!result)
{
return result;
}
//
XOHCL toBar;
XOHCL fromBar;
XOHCL breakerBar;
//
if (!ignoreBreakerBar)
{
//
result = HasBreakerBar(
toBar,
fromBar,
breakerBar,
forDir,
symbol,
period,
upper,
lower,
from,
to //
);
if (!result)
{
return result;
}
}
else
{
//
result = toBar.Init(
symbol,
period,
to //
);
if (!result)
{
return result;
}
//
result = fromBar.Init(
symbol,
period,
from //
);
if (!result)
{
return result;
}
//
breakerBar = fromBar;
}
//
int toIndex = toBar.Index();
int fromIndex = fromBar.Index();
int breakerIndex = breakerBar.Index();
//
bool isBreaked = false;
for (int i = breakerIndex - 1; i >= toIndex; i--)
{
//
XOHCL iBar;
result = iBar.Init(
fromBar.symbol,
fromBar.period,
i //
);
//
if (!result)
{
continue;
}
//
isBreaked =
//
IsBullish(forDir)
//
?
//
iBar.low < upper
//
:
//
iBar.high > lower
//
;
if (isBreaked)
{
break;
}
}
//
result = !isBreaked;
//
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;
}
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;
}
/////////////////////////////////////////////////////////////////////
/**
* Find Oldest Pivot Index ...
*
* @param pivots: XPVPivot instance ...
* @return ( int )
*/
int FindOldestPivotIndex(
XPVPivot &pivots[] //
)
{
//
int result = -1;
//
int count = ArraySize(pivots);
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XPVPivot iPivot = pivots[i];
//
bool isOldest = true;
for (int j = 0; j < count; j++)
{
//
XPVPivot jPivot = pivots[j];
//
isOldest = iPivot.from <= jPivot.from;
if (!isOldest)
{
break;
}
}
//
if (isOldest)
{
//
result = i;
break;
}
}
//
return result;
}
/**
* Sort Pivots Based On From Date ...
*
* @param pivots: XPVPivot instance Collection reference ...
*/
void SortPivots(
XPVPivot &pivots[] //
)
{
//
XPVPivot tmp[];
Copy(
pivots,
tmp //
);
//
Clean(pivots);
//
while (ArraySize(tmp) > 0)
{
//
if (ArraySize(tmp) == 1)
{
//
AddRef(
tmp[0],
pivots //
);
//
ArrayRemove(
tmp,
0,
1);
}
else
{
//
int idx = FindOldestPivotIndex(tmp);
if (IsValidIndex(idx))
{
//
AddRef(
tmp[idx],
pivots //
);
//
ArrayRemove(
tmp,
idx,
1 //
);
}
}
}
//
Clean(tmp);
}
bool IsPivotBreaked(
XPVPivot &pivot,
XPVPivot &pivots[] //
)
{
//
bool result = false;
//
result = pivot.IsValid();
if (!result)
{
return result;
}
//
int count = ArraySize(pivots);
result = IsValidSize(pivots);
if (!result)
{
return result;
}
//
// For Peaks Highs Must not Broked ...
// For Vales Lows Must not Broked ...
bool isPeak = pivot.IsPeak();
//
for (int i = 0; i < count; i++)
{
//
XPVPivot iPivot = pivots[i];
//
result = isPeak
? iPivot.upper > pivot.upper
: iPivot.lower < pivot.lower;
if (result)
{
break;
}
}
//
return result;
}
/**
* Filter Broken Pivots for Detect Order Flow ...
*
* @param pivots: XPVPivot instance Collection reference ...
*/
void FilterBrokenPivots(
XPVPivot &pivots[] //
)
{
//
XPVPivot tmp[];
Copy(
pivots,
tmp //
);
//
Clean(pivots);
//
while (ArraySize(tmp) > 0)
{
//
if (ArraySize(tmp) == 1)
{
//
AddRef(
tmp[0],
pivots //
);
//
ArrayRemove(
tmp,
0,
1 //
);
}
else
{
//
XPVPivot pivot = tmp[0];
//
ArrayRemove(
tmp,
0,
1 //
);
//
bool isBreaked = IsPivotBreaked(
pivot,
tmp //
);
if (!isBreaked)
{
//
AddRef(
pivot,
pivots //
);
}
}
}
//
Clean(tmp);
}
/**
* Calculate Order Flow Direction ...
*
* @param orderFlow: XPVPivot instance Collection reference ...
* @param dir: ENUM_X_DIRECTION member reference, Hold's Calculated Direction ...
*
* @return ( bool )
*/
bool DetectPivotDirection(
XPVPivot &orderFlow[],
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
//
int count = ArraySize(orderFlow);
result = IsValidSize(count);
if (!result)
{
return result;
}
//
// For Bullish Direction all Exists lowers must be Greater or Equal Prev ...
bool isBullish = false;
bool canLookupForBullish = true;
//
// For Bearish Direction all Exists uppers must be Lesser or Equal Prev ...
bool isBearish = false;
bool canLookupForBearish = true;
//
for (int i = 0; i < count; i++)
{
//
XPVPivot iPivot = orderFlow[i];
//
XPVPivot tmp[];
Copy(
orderFlow,
tmp //
);
ArrayRemove(
tmp,
0,
i + 1 //
);
//
int tmpCount = ArraySize(tmp);
if (IsValidSize(tmpCount))
{
//
for (int j = 0; j < tmpCount; j++)
{
//
XPVPivot jPivot = tmp[j];
//
// Check Bullish Direction ...
isBullish =
canLookupForBullish &&
jPivot.lower >= iPivot.lower;
if (!isBullish)
{
canLookupForBullish = false;
}
//
// Check Bearish Direction ...
isBearish =
canLookupForBearish &&
jPivot.upper <= iPivot.upper;
if (!isBearish)
{
canLookupForBearish = false;
}
//
if (!canLookupForBullish &&
!canLookupForBearish)
{
break;
}
}
}
Clean(tmp);
}
//
if (isBullish &&
!isBearish)
{
dir = X_DIRECTION_BULLISH;
}
else if (isBearish &&
!isBullish)
{
dir = X_DIRECTION_BEARISH;
}
//
result = dir != X_DIRECTION_NONE;
//
return result;
}
/**
* Detect all POIs which inside a Pivot ...
*
* @param pivot: XPVPivot instance, Specified Pivot ...
* @param source: XPOIState instance, Reference to Source State ...
* @param state: XPOIState instance, Reference to Detected Pivots ...
* @param lookupSwingHighs: Boolean ...
* @param lookupSwingLows: Boolean ...
* @param lookupSupportZones: Boolean ...
* @param lookupResistanceZones: Boolean ...
* @param lookupSupplyZones: Boolean ...
* @param lookupDemandZones: Boolean ...
* @param lookupBullishOrderBlocks: Boolean ...
* @param lookupBearishOrderBlocks: Boolean ...
* @param lookupBullishFairValueGaps: Boolean ...
* @param lookupBearishFairValueGaps: Boolean ...
* @param lookupBullishRejectionBars: Boolean ...
* @param lookupBearishRejectionBars: Boolean ...
* @param lookupBullishMomentumBars: Boolean ...
* @param lookupBearishMomentumBars: Boolean ...
*/
void DetectPivotPOIs(
XPVPivot &pivot,
XPOIState &source,
XPOIState &state,
bool lookupSwingHighs = true,
bool lookupSwingLows = true,
bool lookupSupportZones = true,
bool lookupResistanceZones = true,
bool lookupSupplyZones = true,
bool lookupDemandZones = true,
bool lookupBullishOrderBlocks = true,
bool lookupBearishOrderBlocks = true,
bool lookupBullishFairValueGaps = true,
bool lookupBearishFairValueGaps = true,
bool lookupBullishRejectionBars = true,
bool lookupBearishRejectionBars = true,
bool lookupBullishMomentumBars = true,
bool lookupBearishMomentumBars = true //
)
{
//
state.Clean();
//
if (!pivot.IsValid())
{
return;
}
//
int count = 0;
//
state.symbol = pivot.symbol;
state.period = pivot.period;
state.time = TimeCurrent();
//
// Swings ...
//
// Swing High ...
if (lookupSwingHighs)
{
//
count = ArraySize(source.swingHighs);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSwing *iSwing = source.swingHighs[i];
//
XOHCL iBar;
bool isFilled = iSwing.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isInside = iBar.high <= pivot.upper;
if (isInside)
{
//
// iSwing.To(pivot.to);
//
Add(
iSwing,
state.swingHighs //
);
}
}
}
}
//
// Swing Low ...
if (lookupSwingLows)
{
//
count = ArraySize(source.swingLows);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSwing *iSwing = source.swingLows[i];
//
XOHCL iBar;
bool isFilled = iSwing.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isInside = iBar.low >= pivot.lower;
if (isInside)
{
//
// iSwing.To(pivot.to);
//
Add(
iSwing,
state.swingLows //
);
}
}
}
}
//
// Support and Resistance Zones ...
//
// Support Zones ...
if (lookupSupportZones)
{
//
count = ArraySize(source.supportZones);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSupportZone *iZone = source.supportZones[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.supportZones //
);
}
}
}
}
//
// Resistance Zones ...
if (lookupResistanceZones)
{
//
count = ArraySize(source.resistanceZones);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCResistanceZone *iZone = source.resistanceZones[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.resistanceZones //
);
}
}
}
}
//
// Supply and Demand Zones ...
//
// Supply Zones ...
if (lookupSupplyZones)
{
//
count = ArraySize(source.supplyZones);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSupplyZone *iZone = source.supplyZones[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.supplyZones //
);
}
}
}
}
//
// Demand Zones ...
if (lookupDemandZones)
{
//
count = ArraySize(source.demandZones);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCDemandZone *iZone = source.demandZones[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.demandZones //
);
}
}
}
}
//
// Order Blocks ...
//
// Bullish Order Blocks ...
if (lookupBullishOrderBlocks)
{
//
count = ArraySize(source.bullishOrderBlocks);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iZone = source.bullishOrderBlocks[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.bullishOrderBlocks //
);
}
}
}
}
//
// Bearish Order Blocks ...
if (lookupBearishOrderBlocks)
{
//
count = ArraySize(source.bearishOrderBlocks);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iZone = source.bearishOrderBlocks[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.bearishOrderBlocks //
);
}
}
}
}
//
// Fair Value Gaps ...
//
// Bullish Fair Value Gaps ...
if (lookupBullishFairValueGaps)
{
//
count = ArraySize(source.bullishFairValueGaps);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iZone = source.bullishFairValueGaps[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.bullishFairValueGaps //
);
}
}
}
}
//
// Bearish Fair Value Gaps ...
if (lookupBearishFairValueGaps)
{
//
count = ArraySize(source.bearishFairValueGaps);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iZone = source.bearishFairValueGaps[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.bearishFairValueGaps //
);
}
}
}
}
//
// Rejection Bars ...
//
// Bullish Rejection Bars ...
if (lookupBullishRejectionBars)
{
//
count = ArraySize(source.bullishRejectionBars);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCRejectionBar *iRejection = source.bullishRejectionBars[i];
//
XOHCL iBar;
bool isFilled = iRejection.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isInside = iBar.low <= pivot.upper &&
iBar.low >= pivot.lower;
if (isInside)
{
//
iRejection.To(pivot.to);
//
Add(
iRejection,
state.bullishRejectionBars //
);
}
}
}
}
//
// Bearish Rejection Bars ...
if (lookupBearishRejectionBars)
{
//
count = ArraySize(source.bearishRejectionBars);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCRejectionBar *iRejection = source.bearishRejectionBars[i];
//
XOHCL iBar;
bool isFilled = iRejection.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isInside = iBar.high <= pivot.upper &&
iBar.high >= pivot.lower;
if (isInside)
{
//
iRejection.To(pivot.to);
//
Add(
iRejection,
state.bearishRejectionBars //
);
}
}
}
}
//
// Momentum Bars ...
//
// Bullish Momentum Bars ...
if (lookupBullishMomentumBars)
{
//
count = ArraySize(source.bullishMomentumBars);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCMomentumBar *iMomentum = source.bullishMomentumBars[i];
//
XOHCL iBar;
bool isFilled = iMomentum.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isInside = iBar.low <= pivot.upper &&
iBar.low >= pivot.lower;
if (isInside)
{
//
iMomentum.To(pivot.to);
//
Add(
iMomentum,
state.bullishMomentumBars //
);
}
}
}
}
//
// Bearish Momenum Bars ...
if (lookupBearishMomentumBars)
{
//
count = ArraySize(source.bearishMomentumBars);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCMomentumBar *iMomentum = source.bearishMomentumBars[i];
//
XOHCL iBar;
bool isFilled = iMomentum.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isInside = iBar.high <= pivot.upper &&
iBar.high >= pivot.lower;
if (isInside)
{
//
iMomentum.To(pivot.to);
//
Add(
iMomentum,
state.bearishMomentumBars //
);
}
}
}
}
}
/**
* Fill Pivot Tick Zone ...
*
* @param pivot: XPVPivot instance Reference ...
*/
void CalculatePivotTickZone(
XPVPivot &pivot,
int ticksLevels,
int ticksRange,
ENUM_TIMEFRAMES _period = NULL //
)
{
//
string symbol = pivot.symbol;
ENUM_TIMEFRAMES period = IsValid(_period)
? _period
: pivot.period;
//
bool isInited = false;
//
datetime from = pivot.from;
XOHCL iFromBar;
int iFromBarIndex = iBarShift(
symbol,
period,
from //
);
isInited = iFromBar.Init(
symbol,
period,
iFromBarIndex //
);
if (!isInited)
{
return;
}
//
datetime to = pivot.to;
XOHCL iToBar;
int iToBarIndex = iBarShift(
symbol,
period,
to //
);
isInited = iToBar.Init(
symbol,
period,
iToBarIndex //
);
if (!isInited)
{
return;
}
//
if (iFromBarIndex <= iToBarIndex)
{
return;
}
//
XCTicksZone *iZone;
iZone = new XCTicksZone();
//
isInited = ticksLevels > 0 &&
ticksRange > 0;
if (!isInited)
{
return;
}
//
isInited = iZone.Init(
iFromBar,
iToBar //
);
if (!isInited)
{
return;
}
//
pivot.state.ticksZone = iZone;
}
/**
* Filter State based on Pivot ...
*
* @param pivot: XPVPivot instance Reference ...
* @param state: XPOIState instance Reference ...
*/
void FilterPivotState(
XPVPivot &pivot,
XPOIState &state //
)
{
//
bool isValid =
pivot.IsValid() &&
state.IsValid() &&
state.HasChild();
if (!isValid)
{
return;
}
//
int count = 0;
//
double upper = pivot.upper;
double lower = pivot.lower;
//
//
//
//
// Resistance ...
count = state.CountResistanceZones();
if (IsValidSize(count))
{
//
XCResistanceZone *tmp[];
Copy(
state.resistanceZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCResistanceZone *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
upper,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.resistanceZones,
i,
1 //
);
}
}
//
Clean(tmp);
}
//
// Supply ...
count = state.CountSupplyZones();
if (IsValidSize(count))
{
//
XCSupplyZone *tmp[];
Copy(
state.supplyZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCSupplyZone *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
upper,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.supplyZones,
i,
1 //
);
}
}
//
Clean(tmp);
}
//
// Bearish Order Block ...
count = state.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
XCOrderBlock *tmp[];
Copy(
state.bearishOrderBlocks,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
upper,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.bearishOrderBlocks,
i,
1 //
);
}
}
//
Clean(tmp);
}
//
// Bearish Fair Value Gap ...
count = state.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
XCFVG *tmp[];
Copy(
state.bearishFairValueGaps,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCFVG *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
upper,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.bearishFairValueGaps,
i,
1 //
);
}
}
//
Clean(tmp);
}
//
//
//
//
// Support ...
count = state.CountSupportZones();
if (IsValidSize(count))
{
//
XCSupportZone *tmp[];
Copy(
state.supportZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCSupportZone *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
lower,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.supportZones,
i,
1 //
);
}
}
//
Clean(tmp);
}
//
// Demand ...
count = state.CountDemandZones();
if (IsValidSize(count))
{
//
XCDemandZone *tmp[];
Copy(
state.demandZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCDemandZone *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
lower,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.demandZones,
i,
1 //
);
}
}
//
Clean(tmp);
}
//
// Bullish Order Block ...
count = state.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
XCOrderBlock *tmp[];
Copy(
state.bullishOrderBlocks,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
lower,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.bullishOrderBlocks,
i,
1 //
);
}
}
//
Clean(tmp);
}
//
// Bullish Fair Value Gap ...
count = state.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
XCFVG *tmp[];
Copy(
state.bullishFairValueGaps,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCFVG *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
lower,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.bullishFairValueGaps,
i,
1 //
);
}
}
//
Clean(tmp);
}
}
/**
* Detect Box Date of Specified Pivot ...
*/
bool DetectPivotStateBoxData(
XPVPivot &pivot,
double &peakUpper,
double &peakLower,
datetime &peakFrom,
datetime &peakTo,
double &valeUpper,
double &valeLower,
datetime &valeFrom,
datetime &valeTo //
)
{
//
bool result = false;
//
peakUpper = 0;
peakLower = 0;
valeUpper = 0;
valeLower = 0;
//
peakFrom = NULL;
peakTo = NULL;
valeFrom = NULL;
valeTo = NULL;
//
result = pivot.IsValid();
if (!result)
{
return result;
}
//
int count = 0;
//
//
//
//
// Resistance ...
count = pivot.state.CountResistanceZones();
if (IsValidSize(count))
{
//
XCResistanceZone *tmp[];
Copy(
pivot.state.resistanceZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCResistanceZone *item = tmp[i];
//
if (peakUpper == 0 ||
peakUpper < item.Upper())
{
peakUpper = item.Upper();
}
//
if (peakLower == 0 ||
peakLower > item.Lower())
{
peakLower = item.Lower();
}
//
if (!IsValid(peakFrom) ||
peakFrom > item.From())
{
peakFrom = item.From();
}
//
if (!IsValid(peakTo) ||
peakTo < item.To())
{
peakTo = item.To();
}
}
//
Clean(tmp);
}
//
// Supply ...
count = pivot.state.CountSupplyZones();
if (IsValidSize(count))
{
//
XCSupplyZone *tmp[];
Copy(
pivot.state.supplyZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCSupplyZone *item = tmp[i];
//
if (peakUpper == 0 ||
peakUpper < item.Upper())
{
peakUpper = item.Upper();
}
//
if (peakLower == 0 ||
peakLower > item.Lower())
{
peakLower = item.Lower();
}
//
if (!IsValid(peakFrom) ||
peakFrom > item.From())
{
peakFrom = item.From();
}
//
if (!IsValid(peakTo) ||
peakTo < item.To())
{
peakTo = item.To();
}
}
//
Clean(tmp);
}
//
// Bearish Order Block ...
count = pivot.state.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
XCOrderBlock *tmp[];
Copy(
pivot.state.bearishOrderBlocks,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *item = tmp[i];
//
if (peakUpper == 0 ||
peakUpper < item.Upper())
{
peakUpper = item.Upper();
}
//
if (peakLower == 0 ||
peakLower > item.Lower())
{
peakLower = item.Lower();
}
//
if (!IsValid(peakFrom) ||
peakFrom > item.From())
{
peakFrom = item.From();
}
//
if (!IsValid(peakTo) ||
peakTo < item.To())
{
peakTo = item.To();
}
}
//
Clean(tmp);
}
//
// Bearish Fair Value Gap ...
count = pivot.state.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
XCFVG *tmp[];
Copy(
pivot.state.bearishFairValueGaps,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCFVG *item = tmp[i];
//
if (peakUpper == 0 ||
peakUpper < item.Upper())
{
peakUpper = item.Upper();
}
//
if (peakLower == 0 ||
peakLower > item.Lower())
{
peakLower = item.Lower();
}
//
if (!IsValid(peakFrom) ||
peakFrom > item.From())
{
peakFrom = item.From();
}
//
if (!IsValid(peakTo) ||
peakTo < item.To())
{
peakTo = item.To();
}
}
//
Clean(tmp);
}
//
//
//
//
// Support ...
count = pivot.state.CountSupportZones();
if (IsValidSize(count))
{
//
XCSupportZone *tmp[];
Copy(
pivot.state.supportZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCSupportZone *item = tmp[i];
//
if (valeUpper == 0 ||
valeUpper < item.Upper())
{
valeUpper = item.Upper();
}
//
if (valeLower == 0 ||
valeLower > item.Lower())
{
valeLower = item.Lower();
}
//
if (!IsValid(valeFrom) ||
valeFrom > item.From())
{
valeFrom = item.From();
}
//
if (!IsValid(valeTo) ||
valeTo < item.To())
{
valeTo = item.To();
}
}
//
Clean(tmp);
}
//
// Demand ...
count = pivot.state.CountDemandZones();
if (IsValidSize(count))
{
//
XCDemandZone *tmp[];
Copy(
pivot.state.demandZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCDemandZone *item = tmp[i];
//
if (valeUpper == 0 ||
valeUpper < item.Upper())
{
valeUpper = item.Upper();
}
//
if (valeLower == 0 ||
valeLower > item.Lower())
{
valeLower = item.Lower();
}
//
if (!IsValid(valeFrom) ||
valeFrom > item.From())
{
valeFrom = item.From();
}
//
if (!IsValid(valeTo) ||
valeTo < item.To())
{
valeTo = item.To();
}
}
//
Clean(tmp);
}
//
// Bullish Order Block ...
count = pivot.state.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
XCOrderBlock *tmp[];
Copy(
pivot.state.bullishOrderBlocks,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *item = tmp[i];
//
if (valeUpper == 0 ||
valeUpper < item.Upper())
{
valeUpper = item.Upper();
}
//
if (valeLower == 0 ||
valeLower > item.Lower())
{
valeLower = item.Lower();
}
//
if (!IsValid(valeFrom) ||
valeFrom > item.From())
{
valeFrom = item.From();
}
//
if (!IsValid(valeTo) ||
valeTo < item.To())
{
valeTo = item.To();
}
}
//
Clean(tmp);
}
//
// Bullish Fair Value Gap ...
count = pivot.state.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
XCFVG *tmp[];
Copy(
pivot.state.bullishFairValueGaps,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCFVG *item = tmp[i];
//
if (valeUpper == 0 ||
valeUpper < item.Upper())
{
valeUpper = item.Upper();
}
//
if (valeLower == 0 ||
valeLower > item.Lower())
{
valeLower = item.Lower();
}
//
if (!IsValid(valeFrom) ||
valeFrom > item.From())
{
valeFrom = item.From();
}
//
if (!IsValid(valeTo) ||
valeTo < item.To())
{
valeTo = item.To();
}
}
//
Clean(tmp);
}
//
result = peakUpper > 0 &&
peakLower > 0 &&
valeUpper > 0 &&
valeLower > 0 &&
IsValid(peakTo) &&
IsValid(valeTo) &&
IsValid(peakFrom) &&
IsValid(valeFrom) &&
peakTo > peakFrom &&
valeTo > valeFrom &&
peakUpper > peakLower &&
valeUpper > valeLower;
//
return result;
}
/**
* Detect Price Inside Zones ...
*
* @param state: XPOIState instance Reference ...
* @param bar: XOHCL instance Reference ...
* @param hasSupport: Boolean ...
* @param hasResistanceZone: Boolean ...
* @param hasSupplyZone: Boolean ...
* @param hasDemandZone: Boolean ...
* @param hasOrderBlock: Boolean ...
* @param hasFairValueGap: Boolean ...
* @return ( bool )
*/
bool DetectPriceInsideZones(
XPOIState &state,
XOHCL &bar,
int &zonesCount,
bool &hasSupportZone,
XCSupportZone *&supportZone,
bool &hasResistanceZone,
XCResistanceZone *&resistanceZone,
bool &hasSupplyZone,
XCSupplyZone *&supplyZone,
bool &hasDemandZone,
XCDemandZone *&demandZone,
bool &hasOrderBlock,
XCOrderBlock *&orderBlock,
bool &hasFairValueGap,
XCFVG *&fairValueGap //
)
{
//
bool result = false;
//
zonesCount = 0;
//
hasSupportZone = false;
hasResistanceZone = false;
hasSupplyZone = false;
hasDemandZone = false;
hasOrderBlock = false;
hasFairValueGap = false;
//
supportZone = NULL;
resistanceZone = NULL;
supplyZone = NULL;
demandZone = NULL;
orderBlock = NULL;
fairValueGap = NULL;
//
datetime cTime = TimeCurrent();
//
result = bar.IsValid() &&
state.IsValid() &&
state.HasChild();
if (!result)
{
return result;
}
//
int count = 0;
//
// Support Zone ...
count = state.CountSupportZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCSupportZone *iZone = state.supportZones[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
supportZone = iZone;
}
}
//
hasSupportZone = supportZone != NULL &&
supportZone.IsValid();
if (hasSupportZone)
{
//
zonesCount++;
supportZone.To(cTime);
}
}
//
// Resistance Zone ...
count = state.CountResistanceZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCResistanceZone *iZone = state.resistanceZones[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
resistanceZone = iZone;
}
}
//
hasResistanceZone = resistanceZone != NULL &&
resistanceZone.IsValid();
if (hasResistanceZone)
{
//
zonesCount++;
resistanceZone.To(cTime);
}
}
//
// Supply Zone ...
count = state.CountSupplyZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCSupplyZone *iZone = state.supplyZones[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
supplyZone = iZone;
}
}
//
hasSupplyZone = supplyZone != NULL &&
supplyZone.IsValid();
if (hasSupplyZone)
{
//
zonesCount++;
supplyZone.To(cTime);
}
}
//
// Demand Zone ...
count = state.CountDemandZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCDemandZone *iZone = state.demandZones[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
demandZone = iZone;
}
}
//
hasDemandZone = demandZone != NULL &&
demandZone.IsValid();
if (hasDemandZone)
{
//
zonesCount++;
demandZone.To(cTime);
}
}
//
// OrderBlock ...
count = state.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCOrderBlock *iZone = state.bullishOrderBlocks[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
orderBlock = iZone;
}
}
//
hasOrderBlock = orderBlock != NULL &&
orderBlock.IsValid();
if (hasOrderBlock)
{
//
zonesCount++;
orderBlock.To(cTime);
}
}
if (!hasOrderBlock)
{
//
count = state.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCOrderBlock *iZone = state.bearishOrderBlocks[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
orderBlock = iZone;
}
}
//
hasOrderBlock = orderBlock != NULL &&
orderBlock.IsValid();
if (hasOrderBlock)
{
//
zonesCount++;
orderBlock.To(cTime);
}
}
}
//
// Fair Value Gap ...
count = state.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iZone = state.bullishFairValueGaps[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
fairValueGap = iZone;
}
}
//
hasFairValueGap = fairValueGap != NULL &&
fairValueGap.IsValid();
if (hasFairValueGap)
{
//
zonesCount++;
fairValueGap.To(cTime);
}
}
if (!hasFairValueGap)
{
//
count = state.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iZone = state.bearishFairValueGaps[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
fairValueGap = iZone;
}
}
//
hasFairValueGap = fairValueGap != NULL &&
fairValueGap.IsValid();
if (hasFairValueGap)
{
//
zonesCount++;
fairValueGap.To(cTime);
}
}
}
//
result =
//
hasSupportZone ||
hasResistanceZone ||
hasSupplyZone ||
hasDemandZone ||
hasOrderBlock ||
hasFairValueGap
//
;
//
return result;
}
/**
* Detect Price Inside Zones ...
*
* @param state: XPOIState instance Reference ...
* @param price: Double ...
* @param hasSupport: Boolean ...
* @param hasResistanceZone: Boolean ...
* @param hasSupplyZone: Boolean ...
* @param hasDemandZone: Boolean ...
* @param hasOrderBlock: Boolean ...
* @param hasFairValueGap: Boolean ...
* @return ( bool )
*/
bool DetectPriceInsideZones(
XPOIState &state,
double price,
int &zonesCount,
bool &hasSupportZone,
XCSupportZone *&supportZone,
bool &hasResistanceZone,
XCResistanceZone *&resistanceZone,
bool &hasSupplyZone,
XCSupplyZone *&supplyZone,
bool &hasDemandZone,
XCDemandZone *&demandZone,
bool &hasOrderBlock,
XCOrderBlock *&orderBlock,
bool &hasFairValueGap,
XCFVG *&fairValueGap //
)
{
//
bool result = false;
//
zonesCount = 0;
//
hasSupportZone = false;
hasResistanceZone = false;
hasSupplyZone = false;
hasDemandZone = false;
hasOrderBlock = false;
hasFairValueGap = false;
//
supportZone = NULL;
resistanceZone = NULL;
supplyZone = NULL;
demandZone = NULL;
orderBlock = NULL;
fairValueGap = NULL;
//
datetime cTime = TimeCurrent();
//
result = price > 0 &&
state.IsValid() &&
state.HasChild();
if (!result)
{
return result;
}
//
int count = 0;
//
// Support Zone ...
count = state.CountSupportZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCSupportZone *iZone = state.supportZones[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
supportZone = iZone;
}
}
//
hasSupportZone = supportZone != NULL &&
supportZone.IsValid();
if (hasSupportZone)
{
//
zonesCount++;
supportZone.To(cTime);
}
}
//
// Resistance Zone ...
count = state.CountResistanceZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCResistanceZone *iZone = state.resistanceZones[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
resistanceZone = iZone;
}
}
//
hasResistanceZone = resistanceZone != NULL &&
resistanceZone.IsValid();
if (hasResistanceZone)
{
//
zonesCount++;
resistanceZone.To(cTime);
}
}
//
// Supply Zone ...
count = state.CountSupplyZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCSupplyZone *iZone = state.supplyZones[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
supplyZone = iZone;
}
}
//
hasSupplyZone = supplyZone != NULL &&
supplyZone.IsValid();
if (hasSupplyZone)
{
//
zonesCount++;
supplyZone.To(cTime);
}
}
//
// Demand Zone ...
count = state.CountDemandZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCDemandZone *iZone = state.demandZones[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
demandZone = iZone;
}
}
//
hasDemandZone = demandZone != NULL &&
demandZone.IsValid();
if (hasDemandZone)
{
//
zonesCount++;
demandZone.To(cTime);
}
}
//
// OrderBlock ...
count = state.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCOrderBlock *iZone = state.bullishOrderBlocks[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
orderBlock = iZone;
}
}
//
hasOrderBlock = orderBlock != NULL &&
orderBlock.IsValid();
if (hasOrderBlock)
{
//
zonesCount++;
orderBlock.To(cTime);
}
}
if (!hasOrderBlock)
{
//
count = state.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCOrderBlock *iZone = state.bearishOrderBlocks[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
orderBlock = iZone;
}
}
//
hasOrderBlock = orderBlock != NULL &&
orderBlock.IsValid();
if (hasOrderBlock)
{
//
zonesCount++;
orderBlock.To(cTime);
}
}
}
//
// Fair Value Gap ...
count = state.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iZone = state.bullishFairValueGaps[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
fairValueGap = iZone;
}
}
//
hasFairValueGap = fairValueGap != NULL &&
fairValueGap.IsValid();
if (hasFairValueGap)
{
//
zonesCount++;
fairValueGap.To(cTime);
}
}
if (!hasFairValueGap)
{
//
count = state.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iZone = state.bearishFairValueGaps[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
fairValueGap = iZone;
}
}
//
hasFairValueGap = fairValueGap != NULL &&
fairValueGap.IsValid();
if (hasFairValueGap)
{
//
zonesCount++;
fairValueGap.To(cTime);
}
}
}
//
result =
//
hasSupportZone ||
hasResistanceZone ||
hasSupplyZone ||
hasDemandZone ||
hasOrderBlock ||
hasFairValueGap
//
;
//
return result;
}
bool CalculatePriceInsideZones(
XPriceZones &zone,
XPOIState &state,
double price //
)
{
//
bool result = false;
//
zone.Clean();
//
int zonesCount = 0;
bool hasSupplyZone = false;
bool hasDemandZone = false;
bool hasOrderBlock = false;
bool hasSupportZone = false;
bool hasFairValueGap = false;
bool hasResistanceZone = false;
//
result = DetectPriceInsideZones(
state,
price,
zone.count,
hasSupportZone,
zone.supportZone,
hasResistanceZone,
zone.resistanceZone,
hasSupplyZone,
zone.supplyZone,
hasDemandZone,
zone.demandZone,
hasOrderBlock,
zone.orderBlock,
hasFairValueGap,
zone.fairValueGap //
);
if (!result)
{
return result;
}
//
zone.price = price;
//
result = zone.IsValid();
//
return result;
}
bool CalculatePriceInsideZones(
XPriceZones &zone,
XPOIState &state,
XOHCL &bar //
)
{
//
bool result = false;
//
zone.Clean();
//
int zonesCount = 0;
bool hasSupplyZone = false;
bool hasDemandZone = false;
bool hasOrderBlock = false;
bool hasSupportZone = false;
bool hasFairValueGap = false;
bool hasResistanceZone = false;
//
result = DetectPriceInsideZones(
state,
bar,
zone.count,
hasSupportZone,
zone.supportZone,
hasResistanceZone,
zone.resistanceZone,
hasSupplyZone,
zone.supplyZone,
hasDemandZone,
zone.demandZone,
hasOrderBlock,
zone.orderBlock,
hasFairValueGap,
zone.fairValueGap //
);
if (!result)
{
return result;
}
//
zone.bar = bar;
//
result = zone.IsValid();
//
return result;
}
/**
* Calculate Zone by Providing Specified Data ...
*
* @param zones: XStateZone instance Reference ...
* @param source: XPOIState instance Reference ...
* @param upper: Double ...
* @param lower: Double ...
* @param from: DateTime ...
*
* @return ( bool )
*/
bool CalculateStateZones(
XStateZones &zones,
XPOIState &source,
double upper,
double lower,
datetime from //
)
{
//
bool result = false;
//
zones.Clean();
//
datetime cTime = TimeCurrent();
//
result =
//
upper > 0 &&
lower > 0 &&
upper > lower &&
IsValid(from) &&
source.IsValid() &&
source.HasChild()
//
;
if (!result)
{
return result;
}
//
int count = 0;
//
// Support ...
count = source.CountSupportZones();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSupportZone *iZone = source.supportZones[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.supportZones //
);
}
}
}
//
// Resistance ...
count = source.CountResistanceZones();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCResistanceZone *iZone = source.resistanceZones[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.resistanceZones //
);
}
}
}
//
// Supply ...
count = source.CountSupplyZones();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSupplyZone *iZone = source.supplyZones[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.supplyZones //
);
}
}
}
//
// Demand ...
count = source.CountDemandZones();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCDemandZone *iZone = source.demandZones[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.demandZones //
);
}
}
}
//
// Bullish OrderBlocks ...
count = source.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iZone = source.bullishOrderBlocks[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.bullishOrderBlocks //
);
}
}
}
//
// Bearish OrderBlocks ...
count = source.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iZone = source.bearishOrderBlocks[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.bearishOrderBlocks //
);
}
}
}
//
// Bullish FairValueGaps ...
count = source.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iZone = source.bullishFairValueGaps[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.bullishFairValueGaps //
);
}
}
}
//
// Bearish FairValueGaps ...
count = source.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iZone = source.bearishFairValueGaps[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.bearishFairValueGaps //
);
}
}
}
//
result = zones.IsValid();
//
return result;
}
/**
* Add Value Change instance to Exists Collection if it's not Exists ...
*
* @param item: XValueChange instance Reference ...
* @param items: XValueChange instance Array Reference ...
*
* @return ( int )
*/
int AddIfNotExists(
XValueChange &item,
XValueChange &items[] //
)
{
//
int result = 0;
//
result = item.IsValid();
if (!result)
{
return result;
}
//
bool canAdd = false;
int count = ArraySize(items);
if (!IsValidSize(count))
{
canAdd = true;
}
else
{
//
XValueChange last;
bool hasItem = GetLastItem(
last,
items //
);
if (!hasItem)
{
canAdd = true;
}
else
{
//
// Compare Last Item with Current ...
canAdd = item.time > last.time;
}
}
//
// Add Item if Allowed ...
if (canAdd)
{
//
AddRef(
item,
items //
);
}
//
result = ArraySize(items);
//
return result;
}
/////////////////////////////////////////////////////////////////////////
//
//
//
//
// Pivot Types ...
enum ENUM_XPV_PIVOTS
{
XPV_NONE,
XPV_PEAK,
XPV_VALE,
};
//
// Model a Pivot structure ...
struct XPVPivot
{
//
string symbol;
ENUM_TIMEFRAMES period;
//
double upper;
double lower;
//
datetime from;
datetime to;
//
int repetition;
//
ENUM_XPV_PIVOTS type;
//
// Combined all States ...
XPOIState state;
//
XPVPivot()
{
Clean();
}
//
// Tools ...
/**
* Cleanup ...
*/
void Clean()
{
//
upper = 0;
lower = 0;
//
to = NULL;
from = NULL;
symbol = NULL;
period = NULL;
//
repetition = 0;
//
type = XPV_NONE;
//
state.Clean();
//
ZeroMemory(this);
}
/**
* Validation ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
IsValid(to) &&
IsValid(from) &&
IsValid(symbol) &&
IsValid(period) &&
repetition > 0 &&
type != XPV_NONE &&
(upper > 0 || lower > 0)
//
;
//
return result;
}
/**
* Check Pivot is Peak ...
*
* @return ( bool )
*/
bool IsPeak()
{
//
bool result = false;
//
result = IsValid() &&
type == XPV_PEAK;
//
return result;
}
/**
* Check Pivot is Vale ...
*
* @return ( bool )
*/
bool IsVale()
{
//
bool result = false;
//
result = IsValid() &&
type == XPV_VALE;
//
return result;
}
/**
* Calculate Lower for Peaks ...
*
* @return ( double )
*/
double CalculateLower()
{
//
double result = 0;
//
if (!IsValid() ||
!IsPeak())
{
return result;
}
//
int fromIndex = iBarShift(
symbol,
period,
from //
);
//
int toIndex = iBarShift(
symbol,
period,
to //
);
//
int count =
fromIndex - toIndex;
//
int llIDX = iLowest(
symbol,
period,
MODE_LOW,
count,
toIndex //
);
//
result =
iLow(
symbol,
period,
llIDX //
);
//
return result;
}
/**
* Calculate Upper for Vales ...
*
* @return ( double )
*/
double CalculateUpper()
{
//
double result = 0;
//
if (!IsValid() ||
!IsVale())
{
return result;
}
//
int fromIndex = iBarShift(
symbol,
period,
from //
);
//
int toIndex = iBarShift(
symbol,
period,
to //
);
//
int count =
fromIndex - toIndex;
//
int hhIDX = iHighest(
symbol,
period,
MODE_HIGH,
count,
toIndex //
);
//
result =
iHigh(
symbol,
period,
hhIDX //
);
//
return result;
}
/**
* Calculate Range of Pivot ...
*
* @return ( double )
*/
double CalculateRange()
{
//
double result = 0;
//
if (!IsValid() ||
upper <= 0 ||
lower <= 0)
{
return result;
}
//
result = upper - lower;
//
return result;
}
/**
* Calculate Middle of Pivot ...
* Used for
* @return ( double )
*/
double CalculateMid()
{
//
double result = 0;
//
double range = CalculateRange();
if (range <= 0)
{
return result;
}
//
result = lower + (range / 2);
//
return result;
}
/**
* Calculate Liquidity Percent for Specified Direction ...
*
* @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ...
* @param price: Double, Specified Price ...
*
* @return ( double )
*/
double CalculateLiquidityPercent(
ENUM_X_DIRECTION forDirection,
double price = 0 //
)
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = state
.CalculateLiquidityPercent(
forDirection,
price //
);
//
return result;
}
/**
* Check Price in Premium or not ...
*
* @return ( bool )
*/
bool IsPriceInPremium()
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
double ask = GetAsk(symbol);
double bid = GetBid(symbol);
//
double mid = CalculateMid();
//
result =
//
ask > mid &&
bid > mid
//
;
//
return result;
}
/**
* Check Price in Discount or not ...
*
* @return ( bool )
*/
bool IsPriceInDiscount()
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
double ask = GetAsk(symbol);
double bid = GetBid(symbol);
//
double mid = CalculateMid();
//
result =
//
ask > mid &&
bid > mid
//
;
//
return result;
}
//
/**
* Get Unique Identifier ...
*
* @return ( string )
*/
string GetTag()
{
//
string result = NULL;
//
if (!IsValid())
{
return result;
}
//
string hash = symbol + "_" +
ToString(period) + "_" +
ToString(upper) + "," +
ToString(lower) + "_" +
ToString(from) + "," +
ToString(to);
hash = ToMD5(hash);
//
string typeStr =
type == XPV_PEAK
? "Peak"
: "Vale";
//
result =
//
"XPV_" +
typeStr + "_" +
symbol + "_" +
ToString(period) +
"_" + hash
//
;
//
return result;
}
//
};
//
// Pivots ...
struct XPVPivotPoint
{
//
// Props ...
double value;
int repetition;
datetime time;
ENUM_XPV_PIVOTS type;
//
// Constructor ...
XPVPivotPoint()
{
Clean();
}
//
// Tools ...
/**
* Cleanup ...
*/
void Clean()
{
//
value = 0;
time = NULL;
repetition = 0;
type = XPV_NONE;
//
ZeroMemory(this);
}
/**
* Validate ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
value > 0 &&
IsValid(time) &&
repetition > 0 &&
type != XPV_NONE
//
;
//
return result;
}
/**
* Check current Pivot Point is Peak or not ...
*
* @return ( bool )
*/
bool IsPeak()
{
//
bool result = false;
//
result = IsValid() &&
type == XPV_PEAK;
//
return result;
}
/**
* Check current Pivot Point is Vale or not ...
*
* @return ( bool )
*/
bool IsVale()
{
//
bool result = false;
//
result = IsValid() &&
type == XPV_VALE;
//
return result;
}
//
};
//
//
//
//
// Model Value Changed ...
struct XValueChange
{
//
// Props ...
double before; // Before Change Value ...
double after; // After Change Value ...
datetime time; // Change Time ...
ENUM_X_DIRECTION dir; // Change Direction ...
//
// Constructor ...
XValueChange()
{
Clean();
}
//
// Tools ...
/**
* Initialize ...
*
* @param _before: Double, Value Before Change ...
* @param _after: Double, Value After Change ...
* @param _time: Datetime, Change Time ...
* @param _dir: ENUM_X_DIRECTION member, Specified Changed Direction ...
*
* @return ( bool )
*/
bool Init(
double _before, // Before Change Value ...
double _after, // After Change Value ...
ENUM_X_DIRECTION _dir, // Change Direction ...
datetime _time = NULL // Change Time ...
)
{
//
bool result = false;
//
_time = NormalizeTime(_time);
//
// Validate Inputs ...
result =
//
_after > 0 &&
_before > 0 &&
IsValid(_time) &&
_after != _before &&
HasDirection(_dir)
//
;
if (!result)
{
return result;
}
//
// Set Validated Values ...
dir = _dir;
time = _time;
after = _after;
before = _before;
//
result = IsValid();
//
return result;
}
/**
* Cleaning Up ...
*/
void Clean()
{
//
after = 0;
before = 0;
time = NULL;
dir = X_DIRECTION_NONE;
//
ZeroMemory(this);
}
/**
* Validate Model ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
after > 0 &&
before > 0 &&
IsValid(time) &&
after != before &&
HasDirection(dir)
//
;
//
return result;
}
/**
* Fill Change Bar ...
*
* @param bar: XOHCL instance Reference, holds Change Bar ...
* @param _symbol: String, Specified Symbol ...
* @param _period: ENUM_TIMEFRAMES _period member, Specified Period ...
*
* @return ( bool )
*/
bool FillBar(
XOHCL &bar,
string _symbol = NULL,
ENUM_TIMEFRAMES _period = NULL //
)
{
//
bool result = false;
//
bar.Clean();
_symbol = NormalizeSymbol(_symbol);
_period = NormalizePeriod(_period);
//
result = IsValid() &&
IsValid(_symbol) &&
IsValid(_period);
if (!result)
{
return result;
}
//
result = bar.Init(
_symbol,
_period,
time //
);
//
return result;
}
//
};
//
// Price Zones Model ...
struct XPriceZones
{
//
XOHCL bar; // if Based On Bar it's Filled ...
double price; // if Based on Price, it's Filled ...
//
int count; // Exists Zones Count ...
//
XCFVG *fairValueGap; // Exists Fair Value Gap ...
XCSupplyZone *supplyZone; // Exists Supply Zone ...
XCDemandZone *demandZone; // Exists Demand Zone ...
XCOrderBlock *orderBlock; // Exists Order Block ...
XCSupportZone *supportZone; // Exists Support Zone ...
XCResistanceZone *resistanceZone; // Exists Resistance Zone ...ّ
//
// Constructor ...
XPriceZones()
{
Clean();
}
/**
* Cleanup ...
*/
void Clean()
{
//
bar.Clean();
price = 0;
//
supplyZone = NULL;
demandZone = NULL;
orderBlock = NULL;
supportZone = NULL;
fairValueGap = NULL;
resistanceZone = NULL;
//
ZeroMemory(this);
}
/**
* Check Zone is Valid ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
(IsBasedOnBar() ||
IsBasedOnPrice()) &&
IsValidSize(count)
//
;
//
return result;
}
/**
* Check Zones Base on Bar ...
*
* @return ( bool )
*/
bool IsBasedOnBar()
{
return bar.IsValid();
}
/**
* Check Zones Based on Price ...
*
* @return ( bool )
*/
bool IsBasedOnPrice()
{
return price > 0;
}
/**
* Check Has Supply Zone ...
*
* @return ( bool )
*/
bool HasSupplyZone()
{
//
return IsValidSize(count) &&
supplyZone != NULL &&
supplyZone.IsValid();
}
/**
* Check Has Demand Zone ...
*
* @return ( bool )
*/
bool HasDemandZone()
{
//
return IsValidSize(count) &&
demandZone != NULL &&
demandZone.IsValid();
}
/**
* Check Has OrderBlock ...
*
* @return ( bool )
*/
bool HasOrderBlock()
{
//
return IsValidSize(count) &&
orderBlock != NULL &&
orderBlock.IsValid();
}
/**
* Check Has Support Zone ...
*
* @return ( bool )
*/
bool HasSupportZone()
{
//
return IsValidSize(count) &&
supportZone != NULL &&
supportZone.IsValid();
}
/**
* Check Has FairValueGap ...
*
* @return ( bool )
*/
bool HasFairValueGap()
{
//
return IsValidSize(count) &&
fairValueGap != NULL &&
fairValueGap.IsValid();
}
/**
* Check Has Resistance Zone ...
*
* @return ( bool )
*/
bool HasResistanceZone()
{
//
return IsValidSize(count) &&
resistanceZone != NULL &&
resistanceZone.IsValid();
}
/**
* Check Zones are Overal Bullish ...
*
* @return ( bool )
*/
bool IsBullish()
{
//
bool result = false;
//
result =
//
HasDemandZone()
//
||
//
HasSupportZone()
//
||
//
(HasOrderBlock() &&
orderBlock.IsBullish())
//
||
//
(HasFairValueGap() &&
fairValueGap.IsBullish())
//
;
//
return result;
}
/**
* Check Zones are Overal Bearish ...
*
* @return ( bool )
*/
bool IsBearish()
{
//
bool result = false;
//
result =
//
HasSupplyZone()
//
||
//
HasResistanceZone()
//
||
//
(HasOrderBlock() &&
orderBlock.IsBearish())
//
||
//
(HasFairValueGap() &&
fairValueGap.IsBearish())
//
;
//
return result;
}
/**
* Fill Zones Based On required Direction ...
*
* @param dir: ENUM_X_DIRECTION member ...
*
* @return ( int )
*/
int FillZones(
ENUM_X_DIRECTION dir,
XCZone *&zones[] //
)
{
//
int result = 0;
//
Clean(zones);
//
bool isBullish = IsBullish(dir);
bool isBoth = dir == X_DIRECTION_ALL ||
dir == X_DIRECTION_NONE;
//
if (isBoth || isBullish)
{
//
if (HasSupportZone())
{
//
Add(
(XCZone *)supportZone,
zones //
);
}
//
if (HasDemandZone())
{
//
Add(
(XCZone *)demandZone,
zones //
);
}
//
if (HasOrderBlock() &&
orderBlock.IsBullish())
{
//
Add(
(XCZone *)orderBlock,
zones //
);
}
//
if (HasFairValueGap() &&
fairValueGap.IsBullish())
{
//
Add(
(XCZone *)fairValueGap,
zones //
);
}
}
//
if (isBoth || !isBullish)
{
//
if (HasResistanceZone())
{
//
Add(
(XCZone *)resistanceZone,
zones //
);
}
//
if (HasSupplyZone())
{
//
Add(
(XCZone *)supplyZone,
zones //
);
}
//
if (HasOrderBlock() &&
orderBlock.IsBearish())
{
//
Add(
(XCZone *)orderBlock,
zones //
);
}
//
if (HasFairValueGap() &&
fairValueGap.IsBearish())
{
//
Add(
(XCZone *)fairValueGap,
zones //
);
}
}
// s
result = ArraySize(zones);
//
return result;
}
/**
* Calculate Boundary of Zones ...
*
* @param dir: ENUM_X_DIRECTION Member, Specified Direction ...
* @param upper: Double ...
* @param lower: Double ...
*
* @return ( bool )
*/
bool GetBoundary(
ENUM_X_DIRECTION dir,
double &upper,
double &lower //
)
{
//
bool result = false;
//
upper = 0;
lower = 0;
//
XCZone *zones[];
int mCount = FillZones(dir, zones);
result = IsValidSize(mCount);
if (!result)
{
return result;
}
//
for (int i = 0; i < mCount; i++)
{
//
XCZone *iZone = zones[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
//
upper =
upper == 0
? iUpper
: iUpper > upper
? iUpper
: upper;
//
lower =
lower == 0
? iLower
: iLower < lower
? iLower
: lower;
}
//
return result;
}
/**
* Calculate Lifetime of Zones ...
*
* @param dir: ENUM_X_DIRECTION Member, Specified Direction ...
* @param from: DateTime ...
* @param to: DateTime ...
*
* @return ( bool )
*/
bool GetLifetime(
ENUM_X_DIRECTION dir,
datetime &from,
datetime &to //
)
{
//
bool result = false;
//
to = NULL;
from = NULL;
//
XCZone *zones[];
int mCount = FillZones(dir, zones);
result = IsValidSize(mCount);
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(dir);
bool isAll = dir == X_DIRECTION_NONE ||
dir == X_DIRECTION_ALL;
//
if (isAll || isBullish)
{
//
// Support Zone ...
bool hasSupportZone = HasSupportZone();
if (hasSupportZone)
{
//
XCSupportZone *zone = supportZone;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
//
// Demand Zone ...
bool hasDemandZone = HasDemandZone();
if (hasDemandZone)
{
//
XCDemandZone *zone = demandZone;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
//
// Order Block ...
bool hasOrderBlock = HasOrderBlock() &&
orderBlock.IsBullish();
if (hasOrderBlock)
{
//
XCOrderBlock *zone = orderBlock;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
//
// Fair Value Gap ...
bool hasFairValueGap = HasFairValueGap() &&
fairValueGap.IsBullish();
if (hasFairValueGap)
{
//
XCFVG *zone = fairValueGap;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
}
//
if (isAll || !isBullish)
{
//
// Resistance Zone ...
bool hasResistanceZone = HasResistanceZone();
if (hasResistanceZone)
{
//
XCResistanceZone *zone = resistanceZone;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
//
// Supply Zone ...
bool hasSupplyZone = HasSupplyZone();
if (hasSupplyZone)
{
//
XCSupplyZone *zone = supplyZone;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
//
// Order Block ...
bool hasOrderBlock = HasOrderBlock() &&
orderBlock.IsBearish();
if (hasOrderBlock)
{
//
XCOrderBlock *zone = orderBlock;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
//
// Fair Value Gap ...
bool hasFairValueGap = HasFairValueGap() &&
fairValueGap.IsBearish();
if (hasFairValueGap)
{
//
XCFVG *zone = fairValueGap;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
}
//
result =
to > from &&
IsValid(to) &&
IsValid(from);
//
return result;
}
/**
* Calculate Box Model Data ...
*
* @param dir: ENUM_X_DIRECTION Member, Specified Direction ...
* @param upper: Double ...
* @param lower: Double ...
* @param from: DateTime ...
* @param to: DateTime ...
*
* @return ( bool )
*/
bool GetBoxData(
ENUM_X_DIRECTION dir,
double &upper,
double &lower,
datetime &from,
datetime &to //
)
{
//
bool result = false;
//
bool hasBoundary = GetBoundary(
dir,
upper,
lower //
);
//
bool hasLifetime = GetLifetime(
dir,
from,
to //
);
//
result =
hasBoundary &&
hasLifetime;
//
return result;
}
//
};
//
// Market Strucutre Model ...
struct XMarketStructure
{
//
string symbol;
ENUM_TIMEFRAMES period;
//
ENUM_X_DIRECTION bias;
//
XPVPivotPoint vales[];
XPriceZones valePriceZones[];
//
XPVPivotPoint peaks[];
XPriceZones peakPriceZones[];
//
XOHCL lowestValeBar;
XOHCL lowestValePeakBreakeUpBar;
XOHCL valeAboveLowestValePeakBar;
//
XOHCL highestPeakBar;
XOHCL peakBelowHighestPeakValeBar;
XOHCL highestPeakValeBreakeDownBar;
//
XMarketStructure()
{
Clean();
}
/**
* Cleanup ...
*/
void Clean()
{
//
symbol = NULL;
period = NULL;
bias = X_DIRECTION_NONE;
//
Clean(vales);
Clean(peaks);
Clean(valePriceZones);
Clean(peakPriceZones);
//
lowestValeBar.Clean();
lowestValePeakBreakeUpBar.Clean();
valeAboveLowestValePeakBar.Clean();
//
highestPeakBar.Clean();
peakBelowHighestPeakValeBar.Clean();
highestPeakValeBreakeDownBar.Clean();
//
ZeroMemory(this);
}
/**
* Validate Model ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
IsValid(symbol) &&
IsValid(period) &&
bias != X_DIRECTION_NONE;
//
return result;
}
/**
* Check Bullish Trend ...
*
* @return ( bool )
*/
bool IsBullish()
{
//
bool result = false;
//
result =
//
IsValid() &&
IsBullish(bias) &&
HasChild(peaks) &&
HasDirection(bias) &&
lowestValeBar.IsValid() &&
HasChild(peakPriceZones) &&
lowestValePeakBreakeUpBar.IsValid() &&
valeAboveLowestValePeakBar.IsValid()
//
;
//
return result;
}
/**
* Check Bearish Trend ...
*
* @return ( bool )
*/
bool IsBearish()
{
//
bool result = false;
//
result =
//
IsValid() &&
IsBearish(bias) &&
HasChild(vales) &&
HasDirection(bias) &&
highestPeakBar.IsValid() &&
HasChild(valePriceZones) &&
peakBelowHighestPeakValeBar.IsValid() &&
highestPeakValeBreakeDownBar.IsValid()
//
;
//
return result;
}
/**
* Check Has Trend ...
*
* @return ( bool )
*/
bool HasTrend()
{
//
bool result = false;
//
result = IsValid() &&
(IsBullish() ||
IsBearish());
//
return result;
}
//
};
struct XStateZones
{
//
XCSupportZone *supportZones[]; // Holds Founded Support Zones ...
XCResistanceZone *resistanceZones[]; // Holds Founded Resistance Zones ...
XCSupplyZone *supplyZones[]; // Holds Founded Supply Zones ...
XCDemandZone *demandZones[]; // Holds Founded Demand Zones ...
XCOrderBlock *bullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ...
XCOrderBlock *bearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ...
XCFVG *bullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ...
XCFVG *bearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ...
//
XStateZones()
{
Clean();
}
/**
* Cleaning Model ...
*/
void Clean()
{
//
Clean(supportZones);
Clean(resistanceZones);
Clean(supplyZones);
Clean(demandZones);
Clean(bullishOrderBlocks);
Clean(bearishOrderBlocks);
Clean(bullishFairValueGaps);
Clean(bearishFairValueGaps);
//
ZeroMemory(this);
}
/**
* Validate Model ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
IsValidSize(CountSupportZones()) ||
IsValidSize(CountResistanceZones()) ||
IsValidSize(CountSupplyZones()) ||
IsValidSize(CountDemandZones()) ||
IsValidSize(CountBullishOrderBlocks()) ||
IsValidSize(CountBearishOrderBlocks()) ||
IsValidSize(CountBullishFairValueGaps()) ||
IsValidSize(CountBearishFairValueGaps())
//
;
//
return result;
}
//
// Tools ...
//
int CountSupportZones()
{
//
int result = 0;
//
result = ArraySize(supportZones);
//
return result;
}
//
int CountResistanceZones()
{
//
int result = 0;
//
result = ArraySize(resistanceZones);
//
return result;
}
//
int CountSupplyZones()
{
//
int result = 0;
//
result = ArraySize(supplyZones);
//
return result;
}
//
int CountDemandZones()
{
//
int result = 0;
//
result = ArraySize(demandZones);
//
return result;
}
//
int CountBullishOrderBlocks()
{
//
int result = 0;
//
result = ArraySize(bullishOrderBlocks);
//
return result;
}
//
int CountBearishOrderBlocks()
{
//
int result = 0;
//
result = ArraySize(bearishOrderBlocks);
//
return result;
}
//
int CountBullishFairValueGaps()
{
//
int result = 0;
//
result = ArraySize(bullishFairValueGaps);
//
return result;
}
//
int CountBearishFairValueGaps()
{
//
int result = 0;
//
result = ArraySize(bearishFairValueGaps);
//
return result;
}
};
struct XFVGOrderBlock
{
//
// Props ...
XCOrderBlock *orderBlock;
XCFVG *fairValueGap;
// XStateZones stateZones;
//
XFVGOrderBlock()
{
Clean();
}
/**
* Cleanup Model ...
*/
void Clean()
{
//
orderBlock = NULL;
fairValueGap = NULL;
//
ZeroMemory(this);
}
/**
* Validate Model ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
orderBlock != NULL &&
fairValueGap != NULL &&
// stateZones.IsValid() &&
((orderBlock.IsBullish() &&
fairValueGap.IsBullish()) ||
((orderBlock.IsBearish() &&
fairValueGap.IsBearish())))
//
;
//
return result;
}
/**
* Get Model Direction ...
*
* @param dir: ENUM_X_DIRECTION member ...
*
* @return ( bool )
*/
bool GetDirection(
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
//
result = IsValid();
if (!result)
{
return result;
}
//
dir = orderBlock.IsBullish()
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
return result;
}
/**
* Retrieve Boundary of Zone ...
*
* @param upper: Upper Boundary ...ّ
* @param lower: Lower Bondary ...
* @return ( bool )
*/
bool GetBoundary(
double &upper,
double &lower //
)
{
//
bool result = false;
//
upper = 0;
lower = 0;
//
result = IsValid();
if (!result)
{
return result;
}
//
upper = orderBlock.Upper();
upper = MathMax(upper, fairValueGap.Upper());
//
lower = orderBlock.Lower();
lower = MathMax(lower, fairValueGap.Lower());
//
result = lower > 0 &&
upper > 0 &&
upper > lower;
//
return result;
}
/**
* Check Model is same as another Istance ...
*
* @param value: XFVGOrderBlock instance Reference ...
*
* @return ( bool )
*/
bool IsSameAs(XFVGOrderBlock &value)
{
//
bool result = false;
//
result =
IsValid() &&
value.IsValid();
if (!result)
{
return result;
}
//
ENUM_X_DIRECTION dir;
result = GetDirection(dir);
if (!result)
{
return result;
}
//
ENUM_X_DIRECTION valueDir;
result = value.GetDirection(valueDir);
if (!result)
{
return result;
}
//
result =
//
dir == valueDir
//
&&
//
orderBlock.From() == value.orderBlock.From() &&
orderBlock.Upper() == value.orderBlock.Upper() &&
orderBlock.Lower() == value.orderBlock.Lower()
//
&&
//
fairValueGap.From() == value.fairValueGap.From() &&
fairValueGap.Upper() == value.fairValueGap.Upper() &&
fairValueGap.Lower() == value.fairValueGap.Lower()
//
;
//
return result;
}
//
};
//
//
//
//
// XPVPivot Object ...
class XCXPVPivotObject : public XCBaseObject
{
//
public:
//
/**
* Creator ...
*
* @param chart_id: Long, Specified Chart ID ...
* @param window: Integer, Specified Chart Window ID ...
* @param pivot: XPVPivot instance ...
* @param prefix: String ...
*
* @return ( bool )
*/
bool Create(
long chart_id,
int window,
XPVPivot &pivot,
string prefix = NULL //
)
{
//
bool result = false;
//
result = pivot.IsValid();
if (!result)
{
return result;
}
//
string name = pivot.GetTag();
if (IsValid(prefix))
{
name = prefix + "_" + name;
}
//
result = mRect.Create(
chart_id,
name,
window,
pivot.from,
pivot.upper,
pivot.to,
pivot.lower //
);
//
if (result)
{
ObjName(name);
}
//
string mTrendName = "MID_" + name;
double mid = pivot.CalculateMid();
result = mTrend.Create(
chart_id,
mTrendName,
window,
pivot.from,
mid,
pivot.to,
mid //
);
if (!result)
{
//
mRect.Delete();
mRect.Detach();
}
//
return result;
}
//
// Getter(s) / Setter(s) ...
/**
* Set Pivot Width ...
*
* @param value: Integer ...
*/
void PivotWidth(int value)
{
//
if (value < 1)
{
value = 1;
}
//
mRect.Width(value);
mTrend.Width(value);
}
/**
* Set Pivot Color ...
*
* @param value: Color ...
*/
void PivotColor(color value)
{
//
mRect.Color(value);
mTrend.Color(value);
}
/**
* Set Pivot Style ...
*
* @param value: ENUM_LINE_STYLE member ...
*/
void PivotStyle(ENUM_LINE_STYLE value)
{
//
mRect.Style(value);
mTrend.Style(value);
}
/**
* Set Pivot Fill ...
*
* @param value: Boolean ...
*/
void PivotFill(bool value)
{
mRect.Fill(value);
}
//
// Virtual ...
/**
* Retrieve Object Type ...
*
* @return ( ENUM_XCHARTOBJECTS )
*/
virtual ENUM_XCHARTOBJECTS Type()
{
return X_XPVPIVOT_OBJ;
}
//
private:
//
//
// Props ...
CChartObjectRectangle mRect;
CChartObjectTrend mTrend;
};
//
//
//
/**
* Draw Specified State Zone ...
*
* @param source: XStateZones instance Reference ...
*
* @return ( int )
*/
int DrawStateZones(
XStateZones &source,
XCBaseObject *&drawnObjects[] //
)
{
//
int result = 0;
//
Clean(drawnObjects);
//
if (!source.IsValid())
{
return result;
}
//
// SupportZones ...
int count = source.CountSupportZones();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSupportZone *iZone = source.supportZones[i];
XCSupportZoneObject *iObj;
//
bool isCreated = CreateSupportZone(
iZone,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
}
//
// ResistanceZones ...
count = source.CountResistanceZones();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCResistanceZone *iZone = source.resistanceZones[i];
XCResistanceZoneObject *iObj;
//
bool isCreated = CreateResistanceZone(
iZone,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
}
//
// SupplyZones ...
count = source.CountSupplyZones();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSupplyZone *iZone = source.supplyZones[i];
XCSupplyZoneObject *iObj;
//
bool isCreated = CreateSupplyZone(
iZone,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
}
//
// DemandZones ...
count = source.CountDemandZones();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCDemandZone *iZone = source.demandZones[i];
XCDemandZoneObject *iObj;
//
bool isCreated = CreateDemandZone(
iZone,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
}
//
// BullishOrderBlocks ...
count = source.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iZone = source.bullishOrderBlocks[i];
XCBullishOrderBlockObject *iObj;
//
bool isCreated = CreateBullishOrderBlock(
iZone,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
}
//
// BearishOrderBlocks ...
count = source.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iZone = source.bearishOrderBlocks[i];
XCBearishOrderBlockObject *iObj;
//
bool isCreated = CreateBearishOrderBlock(
iZone,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
}
//
// BullishFairValueGaps ...
count = source.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iZone = source.bullishFairValueGaps[i];
XCBullishFairValueGapObject *iObj;
//
bool isCreated = CreateBullishFairValueGap(
iZone,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
}
//
// BearishFairValueGaps ...
count = source.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iZone = source.bearishFairValueGaps[i];
XCBearishFairValueGapObject *iObj;
//
bool isCreated = CreateBearishFairValueGap(
iZone,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
}
//
result = ArraySize(drawnObjects);
//
return result;
}
/**
* Draw Specified Market Structure ...
*
* @param model: XMarketStructure instance Reference ...
*
* @return ( int )
*/
int DrawMarketStructure(
XMarketStructure &model,
XCBaseObject *&drawnObjects[] //
)
{
//
int result = 0;
//
Clean(drawnObjects);
//
datetime cTime = TimeCurrent();
//
bool isValid =
model.IsValid();
if (!isValid)
{
return result;
}
//
if (model.lowestValeBar.IsValid())
{
//
XCOHCLObject *iObj;
bool isCreated = CreateBar(
model.lowestValeBar,
iObj,
cTime //
);
//
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
//
if (model.lowestValePeakBreakeUpBar.IsValid())
{
//
XCOHCLObject *iObj;
bool isCreated = CreateBar(
model.lowestValePeakBreakeUpBar,
iObj,
cTime //
);
//
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
//
if (model.valeAboveLowestValePeakBar.IsValid())
{
//
XCOHCLObject *iObj;
bool isCreated = CreateBar(
model.valeAboveLowestValePeakBar,
iObj,
cTime //
);
//
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
//
if (model.highestPeakBar.IsValid())
{
//
XCOHCLObject *iObj;
bool isCreated = CreateBar(
model.highestPeakBar,
iObj,
cTime //
);
//
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
//
if (model.peakBelowHighestPeakValeBar.IsValid())
{
//
XCOHCLObject *iObj;
bool isCreated = CreateBar(
model.peakBelowHighestPeakValeBar,
iObj,
cTime //
);
//
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
//
if (model.highestPeakValeBreakeDownBar.IsValid())
{
//
XCOHCLObject *iObj;
bool isCreated = CreateBar(
model.highestPeakValeBreakeDownBar,
iObj,
cTime //
);
//
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
//
if (HasChild(model.valePriceZones))
{
//
int count = ArraySize(model.valePriceZones);
for (int i = 0; i < count; i++)
{
//
XPriceZones ipZone = model.valePriceZones[i];
//
XCBaseObject *ipObjects[];
int ipDrawnObjects = DrawPriceZone(
ipZone,
ipObjects,
model.bias //
);
if (IsValidSize(ipObjects))
{
//
Copy(
ipObjects,
drawnObjects,
false //
);
}
}
}
//
if (HasChild(model.peakPriceZones))
{
//
int count = ArraySize(model.peakPriceZones);
for (int i = 0; i < count; i++)
{
//
XPriceZones ipZone = model.peakPriceZones[i];
//
XCBaseObject *ipObjects[];
int ipDrawnObjects = DrawPriceZone(
ipZone,
ipObjects,
model.bias //
);
if (IsValidSize(ipObjects))
{
//
Copy(
ipObjects,
drawnObjects,
false //
);
}
}
}
//
result = ArraySize(drawnObjects);
//
return result;
}
//
//
//
/**
* Draw Specific Pivot ...
*
* @param pivot: XPVPivot instance Reference ...
* @param drawState: Boolean ...
* @param drawTicksZone: Boolean ...
* @param ignoreSwingHighs: Boolean ...
* @param ignoreSwingLows: Boolean ...
* @param ignoreSupportZones: Boolean ...
* @param ignoreResistanceZones: Boolean ...
* @param ignoreSupplyZones: Boolean ...
* @param ignoreDemandZones: Boolean ...
* @param ignoreBullishOrderBlocks: Boolean ...
* @param ignoreBearishOrderBlocks: Boolean ...
* @param ignoreBullishFairValueGaps: Boolean ...
* @param ignoreBearishFairValueGaps: Boolean ...
* @param ignoreBullishRejectionBars: Boolean ...
* @param ignoreBearishRejectionBars: Boolean ...
* @param ignoreBullishMomentumBars: Boolean ...
* @param ignoreBearishMomentumBars: Boolean ...
*/
int DrawPivot(
XPVPivot &pivot,
XCBaseObject *&drawnObjects[],
bool drawState = false,
bool drawStateAsBox = false,
bool drawTicksZone = false,
bool ignoreSwingHighs = false,
bool ignoreSwingLows = false,
bool ignoreSupportZones = false,
bool ignoreResistanceZones = false,
bool ignoreSupplyZones = false,
bool ignoreDemandZones = false,
bool ignoreBullishOrderBlocks = false,
bool ignoreBearishOrderBlocks = false,
bool ignoreBullishFairValueGaps = false,
bool ignoreBearishFairValueGaps = false,
bool ignoreBullishRejectionBars = false,
bool ignoreBearishRejectionBars = false,
bool ignoreBullishMomentumBars = false,
bool ignoreBearishMomentumBars = false //
)
{
//
int result = 0;
//
Clean(drawnObjects);
//
if (!pivot.IsValid())
{
return result;
}
//
string prefix = Prefix();
long chartID = ChartIdentification();
int window = SubWindowIdentification();
//
// Draw Pivot it self ...
XCXPVPivotObject *iPivotObj;
iPivotObj = new XCXPVPivotObject();
bool isCreated = iPivotObj.Create(
chartID,
window,
pivot,
prefix //
);
if (!isCreated)
{
return result;
}
//
color clrPivotColor = pivot.IsPeak()
? clrAqua
: clrMagenta;
iPivotObj.PivotColor(clrPivotColor);
iPivotObj.PivotWidth(2);
//
Add(
(XCBaseObject *)iPivotObj,
drawnObjects //
);
//
result = ArraySize(drawnObjects);
//
if (!drawState)
{
return result;
}
//
if (!pivot.state.IsValid())
{
return result;
}
//
XCBaseObject *stateObjects[];
int stateCount = 0;
//
if (!drawStateAsBox)
{
//
stateCount = DrawState(
pivot.state,
stateObjects,
drawTicksZone,
ignoreSwingHighs,
ignoreSwingLows,
ignoreSupportZones,
ignoreResistanceZones,
ignoreSupplyZones,
ignoreDemandZones,
ignoreBullishOrderBlocks,
ignoreBearishOrderBlocks,
ignoreBullishFairValueGaps,
ignoreBearishFairValueGaps,
ignoreBullishRejectionBars,
ignoreBearishRejectionBars,
ignoreBullishMomentumBars,
ignoreBearishMomentumBars //
);
}
else
{
//
double peakUpper = 0;
double peakLower = 0;
double valeUpper = 0;
double valeLower = 0;
//
datetime peakTo = NULL;
datetime valeTo = NULL;
datetime peakFrom = NULL;
datetime valeFrom = NULL;
//
bool hasBoxData = DetectPivotStateBoxData(
pivot,
peakUpper,
peakLower,
peakFrom,
peakTo,
valeUpper,
valeLower,
valeFrom,
valeTo //
);
//
if (hasBoxData)
{
//
XCBoxObject *peakBox;
bool isCreated = CreateBox(
peakBox,
peakUpper,
peakLower,
peakFrom,
peakTo,
clrMagenta,
1,
false,
STYLE_DASHDOT //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)peakBox,
stateObjects //
);
}
//
XCBoxObject *valeBox;
isCreated = CreateBox(
valeBox,
valeUpper,
valeLower,
valeFrom,
valeTo,
clrAqua,
1,
false,
STYLE_DASHDOT //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)valeBox,
stateObjects //
);
}
}
}
//
if (IsValidSize(stateCount))
{
//
Copy(
stateObjects,
drawnObjects,
false // Doesn't Clean ...
);
//
Clean(stateObjects);
}
//
result = ArraySize(drawnObjects);
//
return result;
}
/**
* Draw Specified XFVGOrderBlock Object ...
*
* @param models: XFVGOrderBlock instance Reference ...
*
* @return ( int )
*/
int DrawFVGOrderBlock(
XFVGOrderBlock &model,
XCBaseObject *&drawnObjects[] //
)
{
//
int result = 0;
//
Clean(drawnObjects);
//
if (!model.IsValid())
{
return result;
}
//
ENUM_X_DIRECTION iDir;
result = model.GetDirection(iDir);
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(iDir);
if (isBullish)
{
//
// Order Block ...
XCBullishOrderBlockObject *iOBObj;
bool isCreated = CreateBullishOrderBlock(
model.orderBlock,
iOBObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iOBObj,
drawnObjects //
);
}
//
// FVG ...
XCBullishFairValueGapObject *iFVGObj;
isCreated = CreateBullishFairValueGap(
model.fairValueGap,
iFVGObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iOBObj,
drawnObjects //
);
}
}
else
{
//
// Order Block ...
XCBearishOrderBlockObject *iOBObj;
bool isCreated = CreateBearishOrderBlock(
model.orderBlock,
iOBObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iOBObj,
drawnObjects //
);
}
//
// FVG ...
XCBearishFairValueGapObject *iFVGObj;
isCreated = CreateBearishFairValueGap(
model.fairValueGap,
iFVGObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iFVGObj,
drawnObjects //
);
}
}
//
result = ArraySize(drawnObjects);
//
return result;
}
//
//
//
/**
* Draw Price Zone ...
*
* @param zone: XPriceZones instance Reference ...
* @param forDir: ENUM_X_DIRECTION member ...
*
* @return ( int )
*/
int DrawPriceZone(
XPriceZones &zone,
XCBaseObject *&drawnObjects[],
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
bool onlyBoundary = false //
)
{
//
int result = 0;
//
Clean(drawnObjects);
//
if (!zone.IsValid())
{
return result;
}
//
bool isBullish = IsBullish(forDir);
bool isBearish = IsBearish(forDir);
bool isAll = forDir == X_DIRECTION_ALL ||
forDir == X_DIRECTION_NONE;
//
if (isAll || isBullish)
{
//
if (onlyBoundary)
{
//
double upper = 0;
double lower = 0;
datetime to = NULL;
datetime from = NULL;
//
bool isRetrieved = zone.GetBoxData(
X_DIRECTION_NONE,
upper,
lower,
from,
to //
);
if (isRetrieved)
{
//
color clr =
isBullish
? BarBullishColor()
: isBearish
? BarBearishColor()
: clrGray;
XCBoxObject *iObj;
result = CreateBox(
iObj,
upper,
lower,
from,
to,
clr,
1,
false,
STYLE_DOT //
);
if (result)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
}
else
{
//
// Support Zone ...
if (zone.HasSupportZone())
{
//
XCSupportZoneObject *iObj;
bool isCreated = CreateSupportZone(
zone.supportZone,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
//
// Demand Zone ...
if (zone.HasDemandZone())
{
//
XCDemandZoneObject *iObj;
bool isCreated = CreateDemandZone(
zone.demandZone,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
//
// OrderBlock ...
if (zone.HasOrderBlock() &&
zone.orderBlock.IsBullish())
{
//
XCBullishOrderBlockObject *iObj;
bool isCreated = CreateBullishOrderBlock(
zone.orderBlock,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
//
// FairValueGap ...
if (zone.HasFairValueGap() &&
zone.fairValueGap.IsBullish())
{
//
XCBullishFairValueGapObject *iObj;
bool isCreated = CreateBullishFairValueGap(
zone.fairValueGap,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
}
}
//
if (isAll || isBearish)
{
//
if (onlyBoundary)
{
//
double upper = 0;
double lower = 0;
datetime to = NULL;
datetime from = NULL;
//
bool isRetrieved = zone.GetBoxData(
X_DIRECTION_NONE,
upper,
lower,
from,
to //
);
if (isRetrieved)
{
//
color clr =
isBullish
? BarBullishColor()
: isBearish
? BarBearishColor()
: clrGray;
XCBoxObject *iObj;
result = CreateBox(
iObj,
upper,
lower,
from,
to,
clr,
1,
false,
STYLE_DOT //
);
if (result)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
}
else
{
//
// Resistance Zone ...
if (zone.HasResistanceZone())
{
//
XCResistanceZoneObject *iObj;
bool isCreated = CreateResistanceZone(
zone.resistanceZone,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
//
// Supply Zone ...
if (zone.HasSupplyZone())
{
//
XCSupplyZoneObject *iObj;
bool isCreated = CreateSupplyZone(
zone.supplyZone,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
//
// OrderBlock ...
if (zone.HasOrderBlock() &&
zone.orderBlock.IsBearish())
{
//
XCBearishOrderBlockObject *iObj;
bool isCreated = CreateBearishOrderBlock(
zone.orderBlock,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
//
// FairValueGap ...
if (zone.HasFairValueGap() &&
zone.fairValueGap.IsBearish())
{
//
XCBearishFairValueGapObject *iObj;
bool isCreated = CreateBearishFairValueGap(
zone.fairValueGap,
iObj //
);
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
}
}
//
result = ArraySize(drawnObjects);
//
return result;
}
//
//
//