7951 lines
158 KiB
Plaintext
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;
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
|